├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── LICENSE.md
├── README.md
├── nest-cli.json
├── package-lock.json
├── package.json
├── src
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── auth
│ ├── auth.module.ts
│ ├── bcrypt
│ │ └── bcrypt.ts
│ ├── constants
│ │ └── constants.ts
│ ├── controllers
│ │ └── auth.controller.ts
│ ├── entites
│ │ └── userlogin.entity.ts
│ ├── guard
│ │ ├── jwt-auth.guard.ts
│ │ └── local-auth.guard.ts
│ ├── services
│ │ └── auth.service.ts
│ └── strategy
│ │ ├── jwt.strategy.ts
│ │ └── local-strategy.ts
├── coverageArea
│ ├── controllers
│ │ └── coverageArea.controller.ts
│ ├── coverageArea.module.ts
│ ├── entities
│ │ └── coverageArea.entity.ts
│ └── services
│ │ └── coverageArea.service.ts
├── data
│ └── services
│ │ ├── dev.service.ts
│ │ └── prod.service.ts
├── infrastructure
│ ├── controllers
│ │ └── infrastructure.controller.ts
│ ├── entities
│ │ └── infrastructure.entity.ts
│ ├── insfrastructure.module.ts
│ └── services
│ │ └── infrastructure.service.ts
├── main.ts
├── offering
│ ├── controllers
│ │ └── offering.controller.ts
│ ├── entities
│ │ └── offering.entity.ts
│ ├── offering.module.ts
│ └── services
│ │ └── offering.service.ts
├── provider
│ ├── controllers
│ │ └── provider.controller.ts
│ ├── entities
│ │ └── provider.entity.ts
│ ├── provider.module.ts
│ └── services
│ │ └── provider.service.ts
├── request
│ ├── controllers
│ │ └── request.controller.ts
│ ├── entites
│ │ └── request.entity.ts
│ ├── request.module.ts
│ └── services
│ │ └── request.service.ts
└── user
│ ├── controllers
│ └── user.controller.ts
│ ├── entities
│ └── user.entity.ts
│ ├── services
│ └── user.service.ts
│ └── user.module.ts
├── test
├── app.e2e-spec.ts
└── jest-e2e.json
├── tsconfig.build.json
└── tsconfig.json
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | parserOptions: {
4 | project: 'tsconfig.json',
5 | tsconfigRootDir: __dirname,
6 | sourceType: 'module',
7 | },
8 | plugins: ['@typescript-eslint/eslint-plugin'],
9 | extends: [
10 | 'plugin:@typescript-eslint/recommended',
11 | 'plugin:prettier/recommended',
12 | ],
13 | root: true,
14 | env: {
15 | node: true,
16 | jest: true,
17 | },
18 | ignorePatterns: ['.eslintrc.js'],
19 | rules: {
20 | '@typescript-eslint/interface-name-prefix': 'off',
21 | '@typescript-eslint/explicit-function-return-type': 'off',
22 | '@typescript-eslint/explicit-module-boundary-types': 'off',
23 | '@typescript-eslint/no-explicit-any': 'off',
24 | "linebreak-style": ["error", "auto"]
25 | },
26 | };
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist
3 | /node_modules
4 | /build
5 |
6 | # Logs
7 | logs
8 | *.log
9 | npm-debug.log*
10 | pnpm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 | lerna-debug.log*
14 |
15 | # OS
16 | .DS_Store
17 |
18 | # Tests
19 | /coverage
20 | /.nyc_output
21 |
22 | # IDEs and editors
23 | /.idea
24 | .project
25 | .classpath
26 | .c9/
27 | *.launch
28 | .settings/
29 | *.sublime-workspace
30 |
31 | # IDE - VSCode
32 | .vscode/*
33 | !.vscode/settings.json
34 | !.vscode/tasks.json
35 | !.vscode/launch.json
36 | !.vscode/extensions.json
37 |
38 | # dotenv environment variable files
39 | .env
40 | .env.development.local
41 | .env.test.local
42 | .env.production.local
43 | .env.local
44 |
45 | # temp directory
46 | .temp
47 | .tmp
48 |
49 | # Runtime data
50 | pids
51 | *.pid
52 | *.seed
53 | *.pid.lock
54 |
55 | # Diagnostic reports (https://nodejs.org/api/report.html)
56 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
57 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all",
4 | "endOfLine": "auto"
5 | }
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Softex | Recife
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # FBR digital - Cadastro de Provedores
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | ## Descrição
17 | O Cadastro de Provedores da FBR Digital é uma aplicação que visa facilitar o cadastro e homologação de provedores de internet na base da FBR Digital. A plataforma permite o registro detalhado dos provedores, incluindo informações de infraestrutura, área de cobertura e serviços oferecidos, proporcionando maior visibilidade para a geração de novas demandas de serviços.
18 |
19 | ## Objetivo
20 | O objetivo principal é garantir que os provedores de internet tenham seus cadastros completos, permitindo a homologação e visualização de demandas de serviços de acordo com a área de cobertura cadastrada.
21 |
22 | ## Funcionalidades Principais
23 | - Cadastro de Provedores: Registro de informações corporativas como CNPJ, Nome Fantasia, Endereço e Contatos.
24 | - Cadastro de Áreas de Cobertura: Definição das áreas onde o provedor opera, com a possibilidade de upload via CSV ou KMZ.
25 | - Cadastro de Infraestrutura: Detalhamento da infraestrutura, incluindo ASN, participação em PTTs e operadoras de backbone.
26 | - Cadastro de Serviços: Registro dos planos oferecidos, velocidade de conexão, SLA e preços.
27 | - Sistema de Ranking: Ranking dos serviços baseado na razão preço/velocidade.
28 | - Apresentação de Demandas: Exibição de demandas recebidas através de um painel que permite envio de propostas.
29 |
30 | ## Tecnologias Utilizadas
31 | - Backend: NestJS
32 | - Banco de Dados: MySQL
33 | - ORM: TypeORM
34 | - Linguagem: TypeScript
35 | - Banco de dados em desenvolvimento: PostgreSQL
36 |
37 | ## Instalação e Configuração
38 | - Node.js (>= 14.x)
39 | - MySQL
40 |
41 | ## Passos para rodar o projeto localmente
42 |
43 | 1- Clone o repositório:
44 |
45 | git clone https://github.com/softexrecifepe/PI-T1-GP1-FBR.git
46 |
47 |
48 | 2- Acesse o diretório do projeto:
49 |
50 | cd fbr-digital-provedores
51 |
52 |
53 | 3- Instale as dependências:
54 |
55 | npm install
56 |
57 |
58 | 4- Configure as variáveis de ambiente no arquivo .env:
59 |
60 | DB_HOST=localhost
61 | DB_PORT=3306
62 | DB_USERNAME=root
63 | DB_PASSWORD=sua_senha
64 | DB_DATABASE=fbr_digital
65 |
66 |
67 | 5- Inicie o servidor de desenvolvimento:
68 |
69 | npm run start:dev
70 | #### O projeto estará rodando em:
71 | http://localhost:4000
72 |
73 |
74 |
75 | > [!Note]\
76 | > Ao acessar a API no navegador você terá acesso a uma documentação das rotas construida com o [Swagger](https://fbrdigital-pvsh.onrender.com)
77 |
78 |
79 | ## Contribuição
80 | - Faça um fork do projeto.
81 | - Crie uma branch para sua nova funcionalidade (git checkout -b feat/nova-funcionalidade).
82 | - Faça commit das suas alterações (git commit -m 'Adiciona nova funcionalidade').
83 | - Envie para o repositório remoto (git push origin feat/nova-funcionalidade).
84 | - Crie um pull request.
85 |
86 | ## Equipe
87 |
171 |
172 | ## Licença
173 | Este projeto é licenciado sob a licença MIT. Veja o arquivo LICENSE para mais detalhes.
174 |
175 | ## Contato
176 | Para maiores informações ou sugestões, entre em contato: projetofbr@gmail.com
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
--------------------------------------------------------------------------------
/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/nest-cli",
3 | "collection": "@nestjs/schematics",
4 | "sourceRoot": "src",
5 | "compilerOptions": {
6 | "deleteOutDir": true
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fbr_providers",
3 | "version": "0.0.1",
4 | "description": "",
5 | "author": "",
6 | "private": true,
7 | "license": "UNLICENSED",
8 | "scripts": {
9 | "build": "nest build",
10 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
11 | "start": "nest start",
12 | "start:dev": "nest start --watch",
13 | "start:debug": "nest start --debug --watch",
14 | "start:prod": "node dist/main",
15 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
16 | "test": "jest",
17 | "test:watch": "jest --watch",
18 | "test:cov": "jest --coverage",
19 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
20 | "test:e2e": "jest --config ./test/jest-e2e.json"
21 | },
22 | "dependencies": {
23 | "@nestjs/common": "^10.0.0",
24 | "@nestjs/config": "^3.3.0",
25 | "@nestjs/core": "^10.0.0",
26 | "@nestjs/jwt": "^10.2.0",
27 | "@nestjs/passport": "^10.0.3",
28 | "@nestjs/platform-express": "^10.0.0",
29 | "@nestjs/swagger": "^7.4.2",
30 | "@nestjs/typeorm": "^10.0.2",
31 | "@types/bcrypt": "^5.0.2",
32 | "bcrypt": "^5.1.1",
33 | "class-transformer": "^0.5.1",
34 | "class-validator": "^0.14.1",
35 | "mysql2": "^3.11.3",
36 | "passport": "^0.7.0",
37 | "passport-jwt": "^4.0.1",
38 | "passport-local": "^1.0.0",
39 | "pg": "^8.13.1",
40 | "reflect-metadata": "^0.2.0",
41 | "rxjs": "^7.8.1",
42 | "swagger-ui-express": "^5.0.1",
43 | "typeorm": "^0.3.20"
44 | },
45 | "devDependencies": {
46 | "@nestjs/cli": "^10.0.0",
47 | "@nestjs/schematics": "^10.0.0",
48 | "@nestjs/testing": "^10.0.0",
49 | "@types/express": "^4.17.17",
50 | "@types/jest": "^29.5.2",
51 | "@types/node": "^20.3.1",
52 | "@types/passport-jwt": "^4.0.1",
53 | "@types/passport-local": "^1.0.38",
54 | "@types/supertest": "^6.0.0",
55 | "@typescript-eslint/eslint-plugin": "^8.0.0",
56 | "@typescript-eslint/parser": "^8.0.0",
57 | "eslint": "^8.42.0",
58 | "eslint-config-prettier": "^9.0.0",
59 | "eslint-plugin-prettier": "^5.0.0",
60 | "jest": "^29.5.0",
61 | "prettier": "^3.0.0",
62 | "source-map-support": "^0.5.21",
63 | "supertest": "^7.0.0",
64 | "ts-jest": "^29.1.0",
65 | "ts-loader": "^9.4.3",
66 | "ts-node": "^10.9.1",
67 | "tsconfig-paths": "^4.2.0",
68 | "typescript": "^5.1.3"
69 | },
70 | "jest": {
71 | "moduleFileExtensions": [
72 | "js",
73 | "json",
74 | "ts"
75 | ],
76 | "rootDir": "src",
77 | "testRegex": ".*\\.spec\\.ts$",
78 | "transform": {
79 | "^.+\\.(t|j)s$": "ts-jest"
80 | },
81 | "collectCoverageFrom": [
82 | "**/*.(t|j)s"
83 | ],
84 | "coverageDirectory": "../coverage",
85 | "testEnvironment": "node"
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/app.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get, Res } from '@nestjs/common';
2 | import { ApiExcludeEndpoint } from '@nestjs/swagger';
3 |
4 | @Controller()
5 | export class AppController {
6 | constructor() {}
7 |
8 | @ApiExcludeEndpoint()
9 | @Get()
10 | async redirect(@Res() resposta: any) {
11 | return resposta.redirect('/swagger');
12 | }
13 | }
--------------------------------------------------------------------------------
/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { TypeOrmModule } from '@nestjs/typeorm';
3 | import { AuthModule } from './auth/auth.module';
4 | import { User } from './user/entities/user.entity';
5 | import { UserModule } from './user/user.module';
6 | import { AppController } from './app.controller';
7 | import { CoverageArea } from './coverageArea/entities/coverageArea.entity';
8 | import { CoverageAreaModule } from './coverageArea/coverageArea.module';
9 | import { Offering } from './offering/entities/offering.entity';
10 | import { OfferingModule } from './offering/offering.module';
11 | import { Provider } from './provider/entities/provider.entity';
12 | import { ProviderModule } from './provider/provider.module';
13 | import { Infrastructure } from './infrastructure/entities/infrastructure.entity';
14 | import { InfrastructureModule } from './infrastructure/insfrastructure.module';
15 | import { Request } from './request/entites/request.entity';
16 | import { RequestModule } from './request/request.module';
17 | import { ConfigModule } from '@nestjs/config';
18 | import { ProdService } from './data/services/prod.service';
19 |
20 |
21 |
22 | @Module({
23 | imports: [
24 | ConfigModule.forRoot(),
25 | TypeOrmModule.forRootAsync({
26 | useClass: ProdService,
27 | imports: [ConfigModule],
28 | }),
29 | AuthModule,
30 | UserModule,
31 | CoverageAreaModule,
32 | OfferingModule,
33 | ProviderModule,
34 | InfrastructureModule,
35 | RequestModule
36 | ],
37 | controllers: [AppController],
38 | providers: [],
39 | })
40 | export class AppModule {}
41 |
--------------------------------------------------------------------------------
/src/app.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 |
3 | @Injectable()
4 | export class AppService {
5 | getHello(): string {
6 | return 'Hello World!';
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/auth/auth.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from "@nestjs/common";
2 | import { Bcrypt } from "./bcrypt/bcrypt";
3 | import { AuthService } from "./services/auth.service";
4 | import { LocalStrategy } from "./strategy/local-strategy";
5 | import { UserModule } from "../user/user.module";
6 | import { PassportModule } from "@nestjs/passport";
7 | import { JwtModule } from "@nestjs/jwt";
8 | import { jwtConstants } from "./constants/constants";
9 | import { JwtStrategy } from "./strategy/jwt.strategy";
10 | import { AuthController } from "./controllers/auth.controller";
11 |
12 | @Module({
13 | imports: [
14 | UserModule,
15 | PassportModule,
16 | JwtModule.register({
17 | secret: jwtConstants.secret,
18 | signOptions: { expiresIn: '1h'}
19 | }),
20 | ],
21 | providers: [Bcrypt, AuthService, LocalStrategy, JwtStrategy],
22 | controllers: [AuthController],
23 | exports: [Bcrypt],
24 | })
25 |
26 | export class AuthModule { }
--------------------------------------------------------------------------------
/src/auth/bcrypt/bcrypt.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from "@nestjs/common";
2 | import * as bcrypt from 'bcrypt';
3 |
4 | @Injectable()
5 | export class Bcrypt{
6 |
7 | async criptografarSenha(senha: string): Promise {
8 |
9 | let saltos: number = 10;
10 | return await bcrypt.hash(senha, saltos)
11 |
12 | }
13 |
14 | async compararSenhas(senhaDigitada: string, senhaBanco: string): Promise {
15 | return await bcrypt.compare(senhaDigitada, senhaBanco);
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/src/auth/constants/constants.ts:
--------------------------------------------------------------------------------
1 | export const jwtConstants = {
2 | secret: '37eb3d74e44561d2b9ec3e40da179f9e91571b7f350aee31cfee06b481f146fe',
3 | };
--------------------------------------------------------------------------------
/src/auth/controllers/auth.controller.ts:
--------------------------------------------------------------------------------
1 | import { Body, Controller, HttpCode, HttpStatus, Post, UseGuards } from '@nestjs/common';
2 | import { LocalAuthGuard } from '../guard/local-auth.guard';
3 | import { AuthService } from '../services/auth.service';
4 | import { UserLogin } from '../entites/userlogin.entity';
5 | import { ApiTags } from '@nestjs/swagger';
6 |
7 | @ApiTags('User')
8 | @Controller("/user")
9 | export class AuthController {
10 | constructor(private authService: AuthService) { }
11 |
12 | @UseGuards(LocalAuthGuard)
13 | @HttpCode(HttpStatus.OK)
14 | @Post('/logar')
15 | async login(@Body() user: UserLogin): Promise {
16 | return this.authService.login(user);
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/src/auth/entites/userlogin.entity.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from "@nestjs/swagger"
2 |
3 | export class UserLogin {
4 |
5 | @ApiProperty()
6 | public usuario: string
7 |
8 | @ApiProperty()
9 | public senha: string
10 |
11 | }
--------------------------------------------------------------------------------
/src/auth/guard/jwt-auth.guard.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { AuthGuard } from '@nestjs/passport';
3 |
4 | @Injectable()
5 | export class JwtAuthGuard extends AuthGuard('jwt') {}
--------------------------------------------------------------------------------
/src/auth/guard/local-auth.guard.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 | import { AuthGuard } from '@nestjs/passport';
3 |
4 | @Injectable()
5 | export class LocalAuthGuard extends AuthGuard('local') {}
--------------------------------------------------------------------------------
/src/auth/services/auth.service.ts:
--------------------------------------------------------------------------------
1 | import { JwtService } from '@nestjs/jwt';
2 | import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
3 | import { Bcrypt } from '../bcrypt/bcrypt';
4 | import { UserService } from '../../user/services/user.service';
5 | import { UserLogin } from '../entites/userlogin.entity';
6 |
7 |
8 | @Injectable()
9 | export class AuthService{
10 | constructor(
11 | private usuarioService: UserService,
12 | private jwtService: JwtService,
13 | private bcrypt: Bcrypt
14 | ){ }
15 |
16 | async validateUser(username: string, password: string): Promise{
17 |
18 | const buscaUsuario = await this.usuarioService.findByUsuario(username)
19 |
20 | if(!buscaUsuario)
21 | throw new HttpException('Usuário não encontrado!', HttpStatus.NOT_FOUND)
22 |
23 | const matchPassword = await this.bcrypt.compararSenhas(password, buscaUsuario.senha)
24 |
25 | if(buscaUsuario && matchPassword){
26 | const { senha, ...resposta } = buscaUsuario
27 | return resposta
28 | }
29 |
30 | return null
31 |
32 | }
33 |
34 | async login(usuarioLogin: UserLogin){
35 |
36 | const payload = { sub: usuarioLogin.usuario }
37 |
38 | const buscaUsuario = await this.usuarioService.findByUsuario(usuarioLogin.usuario)
39 |
40 | return{
41 | id: buscaUsuario.id,
42 | nome: buscaUsuario.nome,
43 | usuario: usuarioLogin.usuario,
44 | senha: '',
45 | foto: buscaUsuario.foto,
46 | token: `Bearer ${this.jwtService.sign(payload)}`,
47 | }
48 |
49 | }
50 | }
--------------------------------------------------------------------------------
/src/auth/strategy/jwt.strategy.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from "@nestjs/common";
2 | import { PassportStrategy } from "@nestjs/passport";
3 | import { ExtractJwt, Strategy } from "passport-jwt";
4 | import { jwtConstants } from "../constants/constants";
5 |
6 | @Injectable()
7 | export class JwtStrategy extends PassportStrategy(Strategy) {
8 | constructor(){
9 | super({
10 | jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
11 | ignoreExpiration: false,
12 | secretOrKey: jwtConstants.secret,
13 | });
14 | }
15 |
16 | async validate(payload: any){
17 | return payload;
18 | }
19 | }
--------------------------------------------------------------------------------
/src/auth/strategy/local-strategy.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, UnauthorizedException } from "@nestjs/common";
2 | import { PassportStrategy } from "@nestjs/passport";
3 | import { Strategy } from "passport-local";
4 | import { AuthService } from "../services/auth.service";
5 |
6 |
7 | @Injectable()
8 | export class LocalStrategy extends PassportStrategy(Strategy) {
9 | constructor(private authService: AuthService) {
10 | super({
11 | usernameField: 'usuario',
12 | passwordField: 'senha'
13 | })
14 | }
15 |
16 | async validate(username: string, password: string): Promise {
17 |
18 | const user = await this.authService.validateUser(username, password);
19 |
20 | if(!user){
21 | throw new UnauthorizedException();
22 | }
23 |
24 | return user;
25 | }
26 | }
--------------------------------------------------------------------------------
/src/coverageArea/controllers/coverageArea.controller.ts:
--------------------------------------------------------------------------------
1 | import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
2 | import { CoverageArea } from '../entities/coverageArea.entity';
3 | import { CoverageAreaService } from './../services/coverageArea.service';
4 | import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, ParseIntPipe, Post, Put, UseGuards } from "@nestjs/common";
5 | import { JwtAuthGuard } from '../../auth/guard/jwt-auth.guard';
6 |
7 | @ApiTags('CoverageArea')
8 | @UseGuards(JwtAuthGuard)
9 | @ApiBearerAuth()
10 | @Controller("/coverage-area")
11 | export class CoverageAreaController {
12 | constructor(private readonly coverageAreaService: CoverageAreaService){ }
13 |
14 | @Get()
15 | @HttpCode(HttpStatus.OK)
16 | findAll(): Promise {
17 | return this.coverageAreaService.findAll();
18 | }
19 |
20 | @Get('/:id')
21 | @HttpCode(HttpStatus.OK)
22 | findById(@Param('id', ParseIntPipe) id: number): Promise {
23 | return this.coverageAreaService.findById(id);
24 | }
25 |
26 | @Get('/provider-name/:providerName')
27 | @HttpCode(HttpStatus.OK)
28 | findByProviderName(@Param('providerName')providerName: string): Promise {
29 | return this.coverageAreaService.findByProviderName(providerName);
30 | }
31 |
32 | @Post()
33 | @HttpCode(HttpStatus.CREATED)
34 | create(@Body() coverageArea: CoverageArea): Promise{
35 | return this.coverageAreaService.create(coverageArea)
36 | }
37 |
38 | @Put()
39 | @HttpCode(HttpStatus.OK)
40 | update(@Body() coverageArea: CoverageArea): Promise {
41 | return this.coverageAreaService.update(coverageArea)
42 | }
43 |
44 | @Delete('/:id')
45 | @HttpCode(HttpStatus.NO_CONTENT)
46 | delete(@Param('id', ParseIntPipe) id: number) {
47 | return this.coverageAreaService.delete(id)
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/coverageArea/coverageArea.module.ts:
--------------------------------------------------------------------------------
1 | import { CoverageAreaService } from './services/coverageArea.service';
2 | import { Module } from "@nestjs/common";
3 | import { TypeOrmModule } from "@nestjs/typeorm";
4 | import { CoverageArea } from "./entities/coverageArea.entity";
5 | import { CoverageAreaController } from './controllers/coverageArea.controller';
6 | import { OfferingModule } from '../offering/offering.module';
7 | import { OfferingService } from '../offering/services/offering.service';
8 | import { ProviderModule } from '../provider/provider.module';
9 | import { ProviderService } from '../provider/services/provider.service';
10 |
11 | @Module({
12 | imports: [TypeOrmModule.forFeature([CoverageArea]), OfferingModule, ProviderModule],
13 | providers:[CoverageAreaService, OfferingService, ProviderService],
14 | controllers: [CoverageAreaController],
15 | exports: [TypeOrmModule]
16 | })
17 | export class CoverageAreaModule { }
--------------------------------------------------------------------------------
/src/coverageArea/entities/coverageArea.entity.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from "@nestjs/swagger";
2 | import { IsNotEmpty } from "class-validator";
3 | import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";
4 | import { Offering } from "../../offering/entities/offering.entity";
5 |
6 | @Entity({name: "tb_coverage_area"})
7 | export class CoverageArea {
8 |
9 | @ApiProperty()
10 | @PrimaryGeneratedColumn()
11 | id: number;
12 |
13 | @ApiProperty()
14 | @IsNotEmpty()
15 | @Column({ type: 'varchar', length: 100, nullable: false })
16 | providerName: string; // Nome do provedor de internet
17 |
18 | @ApiProperty()
19 | @IsNotEmpty()
20 | @Column({ type: 'text', nullable: true })
21 | description: string; // Descrição da área de cobertura
22 |
23 | // @ApiProperty()
24 | // @IsNotEmpty()
25 | // @Column({ type: 'varchar', length: 255 })
26 | // coverageFilePath: string; // Caminho do arquivo de área de cobertura (CSV/KMZ)
27 |
28 | @ApiProperty()
29 | @IsNotEmpty()
30 | @Column({ type: 'varchar', length: 255, nullable: false })
31 | city: string; // Cidade onde o provedor oferece cobertura
32 |
33 | @ApiProperty()
34 | @IsNotEmpty()
35 | @Column({ type: 'varchar', length: 255, nullable: false })
36 | state: string; // Estado onde o provedor oferece cobertura
37 |
38 | @ApiProperty()
39 | @IsNotEmpty()
40 | @Column({ type: 'varchar', length: 50, nullable: false })
41 | technology: string; // Tecnologia usada (fibra, rádio, satélite, etc.)
42 |
43 | @ApiProperty()
44 | @IsNotEmpty()
45 | @Column({ type: 'decimal', precision: 10, scale: 7, nullable: false })
46 | latitude: number; // Latitude da área de cobertura
47 |
48 | @ApiProperty()
49 | @IsNotEmpty()
50 | @Column({ type: 'decimal', precision: 10, scale: 7, nullable: false })
51 | longitude: number; // Longitude da área de cobertura
52 |
53 | @ApiProperty()
54 | @CreateDateColumn()
55 | createdAt: Date; // Data de criação do registro
56 |
57 | @ApiProperty()
58 | @UpdateDateColumn()
59 | updatedAt: Date; // Data de atualização do registro
60 |
61 | @ApiProperty({type: ()=> Offering})
62 | @ManyToOne(() => Offering, (offering) => offering.coverageArea, {
63 | onDelete: 'CASCADE',
64 | })
65 | offering: Offering;
66 | }
--------------------------------------------------------------------------------
/src/coverageArea/services/coverageArea.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
2 | import { InjectRepository } from "@nestjs/typeorm";
3 | import { CoverageArea } from "../entities/coverageArea.entity";
4 | import { DeleteResult, ILike, Repository } from "typeorm";
5 | import { OfferingService } from "../../offering/services/offering.service";
6 |
7 | @Injectable()
8 | export class CoverageAreaService {
9 | constructor(
10 | @InjectRepository(CoverageArea)
11 | private coverageAreaRepository: Repository,
12 | private offeringService: OfferingService
13 | ){ }
14 |
15 | async findAll(): Promise {
16 | return await this.coverageAreaRepository.find({
17 | relations:{
18 | offering: true
19 | }
20 | });
21 | }
22 |
23 | async findById(id: number): Promise {
24 |
25 | let coverageArea = await this.coverageAreaRepository.findOne({
26 | where: {
27 | id
28 | },
29 | relations:{
30 | offering: true
31 | }
32 | });
33 |
34 | if (!coverageArea)
35 | throw new HttpException("Área de Cobertura não localizada!", HttpStatus.NOT_FOUND);
36 |
37 | return coverageArea;
38 | }
39 |
40 | async findByProviderName(providerName: string): Promise {
41 | return await this.coverageAreaRepository.find({
42 | where: {
43 | providerName: ILike(`${providerName}`)
44 | },
45 | relations:{
46 | offering: true
47 | }
48 | })
49 | }
50 |
51 | async create(coverageArea: CoverageArea): Promise{
52 |
53 | if(coverageArea.offering){
54 |
55 | let offering = await this.offeringService.findById(coverageArea.offering.id)
56 |
57 | if(!offering)
58 | throw new HttpException('Serviço não encontrado!', HttpStatus.NOT_FOUND);
59 |
60 | return await this.coverageAreaRepository.save(coverageArea)
61 | }
62 |
63 | return await this.coverageAreaRepository.save(coverageArea)
64 | }
65 |
66 |
67 | async update(coverageArea: CoverageArea): Promise {
68 |
69 | let findCoverageArea: CoverageArea = await this.findById(coverageArea.id)
70 |
71 | if(!findCoverageArea || !coverageArea.id)
72 | throw new HttpException('Área de Cobertura não localizada!', HttpStatus.NOT_FOUND);
73 |
74 | if (coverageArea.offering){
75 |
76 | let offering = await this.offeringService.findById(coverageArea.offering.id)
77 |
78 | if (!offering)
79 | throw new HttpException("Serviço não encontrado!", HttpStatus.NOT_FOUND);
80 |
81 | return await this.coverageAreaRepository.save(coverageArea)
82 | }
83 |
84 | return await this.coverageAreaRepository.save(coverageArea)
85 | }
86 |
87 | async delete(id: number): Promise{
88 |
89 | let findCoverageArea = await this.findById(id);
90 |
91 | if (!findCoverageArea)
92 | throw new HttpException("Área de Cobertura não localizada!", HttpStatus.NOT_FOUND)
93 |
94 | return await this.coverageAreaRepository.delete(id)
95 | }
96 | }
--------------------------------------------------------------------------------
/src/data/services/dev.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from "@nestjs/common";
2 | import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from "@nestjs/typeorm";
3 | import { User } from "../../user/entities/user.entity";
4 | import { CoverageArea } from "../../coverageArea/entities/coverageArea.entity";
5 | import { Offering } from "../../offering/entities/offering.entity";
6 | import { Infrastructure } from "../../infrastructure/entities/infrastructure.entity";
7 | import { Provider } from "../../provider/entities/provider.entity";
8 |
9 |
10 | @Injectable()
11 | export class DevService implements TypeOrmOptionsFactory {
12 |
13 | createTypeOrmOptions(): TypeOrmModuleOptions {
14 | return {
15 | type: 'mysql',
16 | host: 'localhost',
17 | port: 3306,
18 | username: 'root',
19 | password: 'root',
20 | database: 'db_fbr_digital',
21 | entities: [User, CoverageArea, Offering, Provider, Infrastructure, Request],
22 | synchronize: true,
23 | };
24 | }
25 | }
--------------------------------------------------------------------------------
/src/data/services/prod.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from "@nestjs/common";
2 | import { ConfigService } from "@nestjs/config";
3 | import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from "@nestjs/typeorm";
4 |
5 | @Injectable()
6 | export class ProdService implements TypeOrmOptionsFactory {
7 |
8 | createTypeOrmOptions(): TypeOrmModuleOptions {
9 | return {
10 | type: 'postgres',
11 | url: process.env.DATABASE_URL,
12 | logging: false,
13 | dropSchema: false,
14 | ssl: {
15 | rejectUnauthorized: false,
16 | },
17 | synchronize: true,
18 | autoLoadEntities: true,
19 | };
20 | }
21 | }
--------------------------------------------------------------------------------
/src/infrastructure/controllers/infrastructure.controller.ts:
--------------------------------------------------------------------------------
1 | import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, ParseIntPipe, Post, Put, UseGuards } from "@nestjs/common";
2 | import { ApiBearerAuth, ApiTags } from "@nestjs/swagger";
3 | import { JwtAuthGuard } from "../../auth/guard/jwt-auth.guard";
4 | import { InfrastructureService } from "../services/infrastructure.service";
5 | import { Infrastructure } from "../entities/infrastructure.entity";
6 |
7 |
8 | @ApiTags('Infrastructure')
9 | @UseGuards(JwtAuthGuard)
10 | @Controller('/infrastructure')
11 | @ApiBearerAuth()
12 | export class InfrastructureController{
13 | constructor(private readonly infrastructureService: InfrastructureService) {}
14 |
15 | @Get()
16 | @HttpCode(HttpStatus.OK)
17 | findAll(): Promise {
18 | return this.infrastructureService.findAll();
19 | }
20 |
21 | @Get('/:id')
22 | @HttpCode(HttpStatus.OK)
23 | findById(@Param('id', ParseIntPipe) id: number): Promise {
24 | return this.infrastructureService.findById(id)
25 | }
26 |
27 | @Post()
28 | @HttpCode(HttpStatus.CREATED)
29 | create(@Body() infrastructure: Infrastructure): Promise {
30 | return this.infrastructureService.create(infrastructure);
31 | }
32 |
33 | @Put()
34 | @HttpCode(HttpStatus.OK)
35 | update(@Body() infrastructure: Infrastructure): Promise {
36 | return this.infrastructureService.update(infrastructure)
37 | }
38 |
39 | @Delete('/:id')
40 | @HttpCode(HttpStatus.NO_CONTENT)
41 | delete(@Param('id', ParseIntPipe) id: number){
42 | return this.infrastructureService.delete(id)
43 | }
44 |
45 | }
--------------------------------------------------------------------------------
/src/infrastructure/entities/infrastructure.entity.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from "@nestjs/swagger";
2 | import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
3 | import { Provider } from "../../provider/entities/provider.entity";
4 |
5 | @Entity({ name: 'tb_infrastructure' })
6 | export class Infrastructure {
7 | @ApiProperty()
8 | @PrimaryGeneratedColumn()
9 | id: number;
10 |
11 | @ApiProperty()
12 | @Column({ length: 100 })
13 | asn: string;
14 |
15 | @ApiProperty()
16 | @Column({ length: 100 })
17 | ptts: string;
18 |
19 | @ApiProperty()
20 | @Column({ length: 255 })
21 | backbone: string;
22 |
23 | @ApiProperty({type: ()=> Provider})
24 | @ManyToOne(() => Provider, (provider) => provider.infrastructure, {
25 | onDelete: 'CASCADE',
26 | })
27 | provider: Provider;
28 | }
--------------------------------------------------------------------------------
/src/infrastructure/insfrastructure.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from "@nestjs/common";
2 | import { TypeOrmModule } from "@nestjs/typeorm";
3 | import { Infrastructure } from "./entities/infrastructure.entity";
4 | import { ProviderModule } from "../provider/provider.module";
5 | import { InfrastructureService } from "./services/infrastructure.service";
6 | import { ProviderService } from "../provider/services/provider.service";
7 | import { InfrastructureController } from "./controllers/infrastructure.controller";
8 |
9 | @Module({
10 | imports: [TypeOrmModule.forFeature([Infrastructure]), ProviderModule],
11 | providers: [InfrastructureService, ProviderService],
12 | controllers: [InfrastructureController],
13 | exports: [TypeOrmModule]
14 | })
15 | export class InfrastructureModule {}
--------------------------------------------------------------------------------
/src/infrastructure/services/infrastructure.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
2 | import { InjectRepository } from "@nestjs/typeorm";
3 | import { DeleteResult, Repository } from "typeorm";
4 | import { Infrastructure } from "../entities/infrastructure.entity";
5 | import { ProviderService } from "../../provider/services/provider.service";
6 |
7 |
8 | @Injectable()
9 | export class InfrastructureService {
10 | constructor(
11 | @InjectRepository(Infrastructure)
12 | private infrastrutureRepository: Repository,
13 | private providerService: ProviderService
14 | ) {}
15 |
16 | async findAll(): Promise {
17 | return await this.infrastrutureRepository.find({
18 | relations: {
19 | provider: true
20 | }
21 | });
22 | }
23 |
24 | async findById(id: number): Promise {
25 |
26 | let infrastructure = await this.infrastrutureRepository.findOne({
27 | where: {
28 | id
29 | },
30 | relations: {
31 | provider: true
32 | }
33 | })
34 |
35 | if(!infrastructure)
36 | throw new HttpException('Infraestrutura não encontrada!', HttpStatus.NOT_FOUND);
37 |
38 | return infrastructure
39 | }
40 |
41 | async create(infrastructure: Infrastructure): Promise {
42 |
43 | if (infrastructure.provider){
44 |
45 | let provider = await this.providerService.findById(infrastructure.provider.id)
46 |
47 | if (!provider)
48 | throw new HttpException('Provedor não encontrado!', HttpStatus.NOT_FOUND)
49 |
50 | return await this.infrastrutureRepository.save(infrastructure)
51 | }
52 |
53 | return await this.infrastrutureRepository.save(infrastructure)
54 | }
55 |
56 | async update(infrastructure: Infrastructure): Promise {
57 |
58 | let findInfrastructure: Infrastructure = await this.findById(infrastructure.id);
59 |
60 | if(!findInfrastructure || infrastructure.id)
61 | throw new HttpException('Infraestrutura não encontrada!', HttpStatus.NOT_FOUND);
62 |
63 | if (infrastructure.provider){
64 |
65 | let provider = await this.providerService.findById(infrastructure.provider.id)
66 |
67 | if (!provider)
68 | throw new HttpException('Provedor não encontrado!', HttpStatus.NOT_FOUND)
69 |
70 | return await this.infrastrutureRepository.save(infrastructure)
71 | }
72 |
73 | return await this.infrastrutureRepository.save(infrastructure)
74 | }
75 |
76 | async delete(id: number): Promise {
77 |
78 | let findInfrastructure = await this.findById(id);
79 |
80 | if(!findInfrastructure)
81 | throw new HttpException('Infraestrutura não encontrada!', HttpStatus.NOT_FOUND);
82 |
83 | return await this.infrastrutureRepository.delete(id)
84 | }
85 | }
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { NestFactory } from '@nestjs/core';
2 | import { AppModule } from './app.module';
3 | import { ValidationPipe } from '@nestjs/common';
4 | import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
5 |
6 | async function bootstrap() {
7 | const app = await NestFactory.create(AppModule);
8 |
9 | const config = new DocumentBuilder()
10 | .setTitle('FBR Digital')
11 | .setDescription('API de cadastro de provedores')
12 | .setContact("Projeto Integrador - Softex | Recife ","https://github.com/softexrecifepe/PI-T1-GP1-FBR","projetofbr@gmail.com")
13 | .setVersion('1.0')
14 | .addBearerAuth()
15 | .build();
16 | const document = SwaggerModule.createDocument(app, config);
17 | SwaggerModule.setup('/swagger', app, document);
18 |
19 | process.env.TZ= '-03:00'
20 |
21 | app.useGlobalPipes(new ValidationPipe())
22 | app.enableCors()
23 | await app.listen(process.env.PORT || 4000);
24 | }
25 | bootstrap();
26 |
--------------------------------------------------------------------------------
/src/offering/controllers/offering.controller.ts:
--------------------------------------------------------------------------------
1 | import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, ParseIntPipe, Post, Put, UseGuards } from "@nestjs/common";
2 | import { OfferingService } from "../services/offering.service";
3 | import { Offering } from "../entities/offering.entity";
4 | import { JwtAuthGuard } from "../../auth/guard/jwt-auth.guard";
5 | import { ApiBearerAuth, ApiTags } from "@nestjs/swagger";
6 |
7 | @ApiTags('Offering')
8 | @UseGuards(JwtAuthGuard)
9 | @Controller("/offering")
10 | @ApiBearerAuth()
11 | export class OfferingController {
12 | constructor(private readonly offeringService: OfferingService) { }
13 |
14 | @Get()
15 | @HttpCode(HttpStatus.OK)
16 | findAll(): Promise {
17 | return this.offeringService.findAll();
18 | }
19 |
20 | @Get('/:id')
21 | @HttpCode(HttpStatus.OK)
22 | findById(@Param('id', ParseIntPipe) id: number): Promise {
23 | return this.offeringService.findById(id);
24 | }
25 |
26 | @Get('/tipo-do-plano/:tipoPlano')
27 | @HttpCode(HttpStatus.OK)
28 | findBydescricao(@Param('tipoPlano') tipoPlano: string): Promise {
29 | return this.offeringService.findByTipoPlano(tipoPlano);
30 | }
31 |
32 | @Post()
33 | @HttpCode(HttpStatus.CREATED)
34 | create(@Body() offering: Offering): Promise {
35 | return this.offeringService.create(offering);
36 | }
37 |
38 | @Put()
39 | @HttpCode(HttpStatus.OK)
40 | update(@Body() offering: Offering): Promise {
41 | return this.offeringService.update(offering);
42 | }
43 |
44 | @Delete('/:id')
45 | @HttpCode(HttpStatus.NO_CONTENT)
46 | delete(@Param('id', ParseIntPipe) id: number){
47 | return this.offeringService.delete(id);
48 | }
49 |
50 | }
--------------------------------------------------------------------------------
/src/offering/entities/offering.entity.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from "@nestjs/swagger";
2 | import { IsNotEmpty } from "class-validator";
3 | import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
4 | import { CoverageArea } from "../../coverageArea/entities/coverageArea.entity";
5 | import { Provider } from "../../provider/entities/provider.entity";
6 |
7 | @Entity({ name: 'tb_offering' })
8 | export class Offering {
9 |
10 | @ApiProperty()
11 | @PrimaryGeneratedColumn()
12 | id: number;
13 |
14 | @ApiProperty()
15 | @IsNotEmpty()
16 | @Column({ length: 100, nullable: false })
17 | tipoPlano: string;
18 |
19 | @ApiProperty()
20 | @IsNotEmpty()
21 | @Column({nullable: false})
22 | velocidade: number; // Velocidade em MB/GB
23 |
24 | @ApiProperty()
25 | @IsNotEmpty()
26 | @Column({ length: 50, nullable: false })
27 | sla: string; // SLA do plano
28 |
29 | @ApiProperty()
30 | @IsNotEmpty()
31 | @Column({nullable: false})
32 | preco: number;
33 |
34 | @ApiProperty()
35 | @IsNotEmpty()
36 | @Column({ type: 'float', default: 0 })
37 | ranking: number; // Campo para armazenar o ranking
38 |
39 | @ApiProperty()
40 | @OneToMany(() => CoverageArea, (coverageArea) => coverageArea.offering)
41 | coverageArea: CoverageArea[]
42 |
43 | @ManyToOne(() => Provider, (provider) => provider.offering, {
44 | onDelete: "CASCADE"
45 | })
46 | provider: Provider
47 |
48 | }
--------------------------------------------------------------------------------
/src/offering/offering.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from "@nestjs/common";
2 | import { TypeOrmModule } from "@nestjs/typeorm";
3 | import { Offering } from "./entities/offering.entity";
4 | import { OfferingService } from "./services/offering.service";
5 | import { OfferingController } from "./controllers/offering.controller";
6 | import { ProviderModule } from "../provider/provider.module";
7 | import { ProviderService } from "../provider/services/provider.service";
8 |
9 |
10 | @Module({
11 | imports: [TypeOrmModule.forFeature([Offering]), ProviderModule],
12 | providers: [OfferingService, ProviderService],
13 | controllers: [OfferingController],
14 | exports: [TypeOrmModule]
15 | })
16 | export class OfferingModule {}
--------------------------------------------------------------------------------
/src/offering/services/offering.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
2 | import { Offering } from "../entities/offering.entity";
3 | import { InjectRepository } from "@nestjs/typeorm";
4 | import { DeleteResult, ILike, Repository } from "typeorm";
5 | import { ProviderService } from "../../provider/services/provider.service";
6 |
7 | @Injectable()
8 | export class OfferingService {
9 | constructor(
10 | @InjectRepository(Offering)
11 | private offeringRepository: Repository,
12 | private providerService:ProviderService
13 | ) { }
14 |
15 | async findAll(): Promise {
16 | return await this.offeringRepository.find({
17 | relations: {
18 | coverageArea: true,
19 | provider: true
20 | }
21 | });
22 | }
23 |
24 | async findById(id: number): Promise {
25 |
26 | let offering = await this.offeringRepository.findOne({
27 | where: {
28 | id
29 | },
30 | relations: {
31 | coverageArea: true,
32 | provider: true
33 | }
34 | });
35 |
36 | if (!offering)
37 | throw new HttpException('Serviço não encontrado!', HttpStatus.NOT_FOUND);
38 |
39 | return offering;
40 | }
41 |
42 | async findByTipoPlano(tipoPlano: string): Promise {
43 | return await this.offeringRepository.find({
44 | where: {
45 | tipoPlano: ILike(`%${tipoPlano}%`)
46 | },
47 | relations: {
48 | coverageArea: true,
49 | provider: true
50 | }
51 | })
52 | }
53 |
54 | async create(offering: Offering): Promise {
55 |
56 | if (offering.provider){
57 |
58 | let provider = await this.providerService.findById(offering.provider.id)
59 |
60 | if (!provider)
61 | throw new HttpException('Provedor não encontrado!', HttpStatus.NOT_FOUND);
62 |
63 | return await this.offeringRepository.save(offering)
64 | }
65 |
66 | return await this.offeringRepository.save(offering);
67 | }
68 |
69 | async update(offering: Offering): Promise {
70 |
71 | let findOffering = await this.findById(offering.id);
72 |
73 | if (!findOffering || !offering.id)
74 | throw new HttpException('Serviço não encontrado!', HttpStatus.NOT_FOUND);
75 |
76 | if (offering.provider){
77 |
78 | let provider = await this.providerService.findById(offering.provider.id)
79 |
80 | if (!provider)
81 | throw new HttpException('Provedor não encontrado!', HttpStatus.NOT_FOUND);
82 |
83 | return await this.offeringRepository.save(offering)
84 | }
85 |
86 | return await this.offeringRepository.save(offering);
87 | }
88 |
89 | async delete(id: number): Promise {
90 |
91 | let findOffering = await this.findById(id);
92 |
93 | if (!findOffering)
94 | throw new HttpException('Serviço não encontrado!', HttpStatus.NOT_FOUND);
95 |
96 | return await this.offeringRepository.delete(id);
97 |
98 | }
99 | }
--------------------------------------------------------------------------------
/src/provider/controllers/provider.controller.ts:
--------------------------------------------------------------------------------
1 | import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, ParseIntPipe, Post, Put, UseGuards } from "@nestjs/common";
2 | import { ProviderService } from "../services/provider.service";
3 | import { Provider } from './../entities/provider.entity';
4 | import { ApiBearerAuth, ApiTags } from "@nestjs/swagger";
5 | import { JwtAuthGuard } from "../../auth/guard/jwt-auth.guard";
6 |
7 | @ApiTags('Provider')
8 | @UseGuards(JwtAuthGuard)
9 | @ApiBearerAuth()
10 | @Controller("/provider")
11 | export class ProviderController {
12 | constructor(private readonly providerService: ProviderService) { }
13 |
14 | @Get()
15 | @HttpCode(HttpStatus.OK)
16 | findAll(): Promise {
17 | return this.providerService.findAll();
18 | }
19 |
20 | @Get('/:id')
21 | @HttpCode(HttpStatus.OK)
22 | findById(@Param('id', ParseIntPipe) id: number): Promise {
23 | return this.providerService.findById(id);
24 | }
25 |
26 | @Get('/fantasy_name/:fantasy_name')
27 | @HttpCode(HttpStatus.OK)
28 | findByName(@Param('fantasy_name') fantasy_name: string): Promise {
29 | return this.providerService.findByName(fantasy_name);
30 | }
31 |
32 | @Post()
33 | @HttpCode(HttpStatus.CREATED)
34 | create(@Body() provider: Provider): Promise {
35 | return this.providerService.create(provider);
36 | }
37 |
38 | @Put()
39 | @HttpCode(HttpStatus.OK)
40 | update(@Body() provider: Provider): Promise {
41 | return this.providerService.update(provider);
42 | }
43 |
44 | @Delete('/:id')
45 | @HttpCode(HttpStatus.NO_CONTENT)
46 | delete(@Param('id', ParseIntPipe) id: number){
47 | return this.providerService.delete(id);
48 | }
49 |
50 | }
--------------------------------------------------------------------------------
/src/provider/entities/provider.entity.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from "@nestjs/swagger"
2 | import { IsNotEmpty } from "class-validator"
3 | import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"
4 | import { Offering } from "../../offering/entities/offering.entity"
5 | import { Infrastructure } from "../../infrastructure/entities/infrastructure.entity"
6 | import { Request } from "../../request/entites/request.entity"
7 |
8 | @Entity({name: "tb_provider"})
9 | export class Provider {
10 | @ApiProperty()
11 | @PrimaryGeneratedColumn()
12 | id: number
13 |
14 | @ApiProperty()
15 | @IsNotEmpty()
16 | @Column({length: 100, nullable: false})
17 | cnpj: string
18 |
19 | @ApiProperty()
20 | @IsNotEmpty()
21 | @Column({length: 100, nullable: false})
22 | fantasy_name: string
23 |
24 | @ApiProperty()
25 | @IsNotEmpty()
26 | @Column({length: 100, nullable: false})
27 | corporate_name: string
28 |
29 | @ApiProperty()
30 | @IsNotEmpty()
31 | @Column({length: 100, nullable: false})
32 | headquarters_adress: string
33 |
34 | @ApiProperty()
35 | @IsNotEmpty()
36 | @Column({length: 100, nullable: false})
37 | legal_representative_contact: string
38 |
39 | @ApiProperty()
40 | @OneToMany(() => Offering, (offering) => offering.provider)
41 | offering: Offering[]
42 |
43 | @ApiProperty()
44 | @OneToMany(() => Infrastructure, (infrastructure) => infrastructure.provider)
45 | infrastructure: Infrastructure[]
46 |
47 | @ApiProperty()
48 | @OneToMany(() => Request, (request) => request.provider)
49 | request: Request[]
50 | }
--------------------------------------------------------------------------------
/src/provider/provider.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from "@nestjs/common";
2 | import { TypeOrmModule } from "@nestjs/typeorm";
3 | import { Provider } from "./entities/provider.entity";
4 | import { ProviderService } from "./services/provider.service";
5 | import { ProviderController } from "./controllers/provider.controller";
6 |
7 |
8 | @Module({
9 | imports: [TypeOrmModule.forFeature([Provider])],
10 | providers: [ProviderService],
11 | controllers: [ProviderController],
12 | exports: [TypeOrmModule]
13 | })
14 | export class ProviderModule {}
--------------------------------------------------------------------------------
/src/provider/services/provider.service.ts:
--------------------------------------------------------------------------------
1 | import { InjectRepository } from '@nestjs/typeorm';
2 | import { Provider } from './../entities/provider.entity';
3 | import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
4 | import { DeleteResult, ILike, Repository } from 'typeorm';
5 |
6 | @Injectable()
7 | export class ProviderService {
8 | constructor(
9 | @InjectRepository(Provider)
10 | private providerRepository: Repository
11 | ) { }
12 |
13 | async findAll(): Promise {
14 | return await this.providerRepository.find({
15 | relations: {
16 | offering: true,
17 | infrastructure: true,
18 | request: true
19 | }
20 | });
21 | }
22 |
23 | async findById(id: number): Promise {
24 |
25 | let provider = await this.providerRepository.findOne({
26 | where: {
27 | id
28 | },
29 | relations: {
30 | offering: true,
31 | infrastructure: true,
32 | request: true
33 | }
34 | });
35 |
36 | if (!provider)
37 | throw new HttpException('Provedor não encontrado!', HttpStatus.NOT_FOUND);
38 |
39 | return provider;
40 | }
41 |
42 | async findByName(fantasy_name: string): Promise {
43 | return await this.providerRepository.find({
44 | where: {
45 | fantasy_name: ILike(`%${fantasy_name}%`)
46 | },
47 | relations: {
48 | offering: true,
49 | infrastructure: true,
50 | request: true
51 | }
52 | })
53 | }
54 |
55 | async create(provider: Provider): Promise {
56 | return await this.providerRepository.save(provider);
57 | }
58 |
59 | async update(provider: Provider): Promise {
60 |
61 | let findProvider = await this.findById(provider.id);
62 |
63 | if (!findProvider || !provider.id)
64 | throw new HttpException('Provedor não encontrado!', HttpStatus.NOT_FOUND);
65 |
66 | return await this.providerRepository.save(provider);
67 | }
68 |
69 | async delete(id: number): Promise {
70 |
71 | let findProvider = await this.findById(id);
72 |
73 | if (!findProvider)
74 | throw new HttpException('Provedor não encontrado!', HttpStatus.NOT_FOUND);
75 |
76 | return await this.providerRepository.delete(id);
77 |
78 | }
79 | }
--------------------------------------------------------------------------------
/src/request/controllers/request.controller.ts:
--------------------------------------------------------------------------------
1 | import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, ParseIntPipe, Post, Put, UseGuards } from "@nestjs/common";
2 | import { ApiBearerAuth, ApiTags } from "@nestjs/swagger";
3 | import { JwtAuthGuard } from "../../auth/guard/jwt-auth.guard";
4 | import { RequestService } from "../services/request.service";
5 | import { Request } from "../entites/request.entity";
6 |
7 | @ApiTags('Request')
8 | @UseGuards(JwtAuthGuard)
9 | @Controller('/request')
10 | @ApiBearerAuth()
11 | export class RequestController {
12 | constructor(private readonly requestService: RequestService) {}
13 |
14 | @Get()
15 | @HttpCode(HttpStatus.OK)
16 | findAll(): Promise {
17 | return this.requestService.findAll();
18 | }
19 |
20 | @Get('/:id')
21 | @HttpCode(HttpStatus.OK)
22 | findById(@Param('id', ParseIntPipe) id: number): Promise {
23 | return this.requestService.findById(id);
24 | }
25 |
26 | @Get('status/:status')
27 | @HttpCode(HttpStatus.OK)
28 | findByStatus(@Param('status') status: string): Promise {
29 | return this.requestService.findByStatus(status);
30 | }
31 |
32 | @Post()
33 | @HttpCode(HttpStatus.CREATED)
34 | create(@Body() request: Request): Promise {
35 | return this.requestService.create(request)
36 | }
37 |
38 | @Put()
39 | @HttpCode(HttpStatus.OK)
40 | update(@Body() request: Request): Promise {
41 | return this.requestService.update(request)
42 | }
43 |
44 | @Delete('/:id')
45 | @HttpCode(HttpStatus.NO_CONTENT)
46 | delete(@Param('id', ParseIntPipe)id: number){
47 | return this.requestService.delete(id)
48 | }
49 | }
--------------------------------------------------------------------------------
/src/request/entites/request.entity.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from "@nestjs/swagger";
2 | import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
3 | import { Provider } from "../../provider/entities/provider.entity";
4 |
5 | @Entity({ name: 'tb_request' })
6 | export class Request {
7 |
8 | @ApiProperty()
9 | @PrimaryGeneratedColumn()
10 | id: number;
11 |
12 | @ApiProperty()
13 | @Column({ type: 'text' })
14 | descricao: string;
15 |
16 | @ApiProperty()
17 | @Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
18 | data_criacao: Date;
19 |
20 | @ApiProperty()
21 | @Column({
22 | type: 'enum',
23 | enum: ['pendente', 'aceita', 'recusada', 'concluída'],
24 | default: 'pendente',
25 | })
26 | status: string;
27 |
28 | @ApiProperty()
29 | @Column({ type: 'varchar', length: 255 })
30 | solicitante_email: string;
31 |
32 | @ApiProperty()
33 | @Column({ type: 'decimal', precision: 10, scale: 2, nullable: true })
34 | valor_proposto: number;
35 |
36 | // @ManyToOne(() => CoverageArea, (area) => area.demandas, {
37 | // onDelete: 'CASCADE',
38 | // })
39 | // area_cobertura: CoverageArea;
40 |
41 | // @ManyToOne(() => Offering, (offering) => offering.demandas, {
42 | // onDelete: 'CASCADE',
43 | // })
44 | // servico: Offering;
45 |
46 | @ApiProperty({type: ()=> Provider})
47 | @ManyToOne(() => Provider, (provider) => provider.request, {
48 | onDelete: 'CASCADE',
49 | })
50 | provider: Provider;
51 | }
--------------------------------------------------------------------------------
/src/request/request.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from "@nestjs/common";
2 | import { TypeOrmModule } from "@nestjs/typeorm";
3 | import { RequestService } from "./services/request.service";
4 | import { RequestController } from "./controllers/request.controller";
5 | import { ProviderModule } from "../provider/provider.module";
6 | import { ProviderService } from "../provider/services/provider.service";
7 | import { Request } from "./entites/request.entity";
8 |
9 | @Module({
10 | imports: [TypeOrmModule.forFeature([Request]), ProviderModule],
11 | providers: [RequestService, ProviderService],
12 | controllers: [RequestController],
13 | exports: [TypeOrmModule],
14 | })
15 |
16 | export class RequestModule {}
--------------------------------------------------------------------------------
/src/request/services/request.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
2 | import { InjectRepository } from "@nestjs/typeorm";
3 | import { DeleteResult, Repository } from "typeorm";
4 | import { ProviderService } from "../../provider/services/provider.service";
5 | import { Request } from "../entites/request.entity";
6 |
7 | @Injectable()
8 | export class RequestService {
9 | constructor(
10 | @InjectRepository(Request)
11 | private requestRepository: Repository,
12 | private providerService: ProviderService
13 | ) {}
14 |
15 | async findAll(): Promise {
16 | return await this.requestRepository.find({
17 | relations: {
18 | provider: true
19 | }
20 | });
21 | }
22 |
23 | async findById(id: number): Promise {
24 | let request = await this.requestRepository.findOne({
25 | where: {
26 | id,
27 | },
28 | relations: {
29 | provider: true
30 | }
31 | });
32 |
33 | if (!request)
34 | throw new HttpException('Demanda não encontrada!', HttpStatus.NOT_FOUND);
35 |
36 | return request;
37 | }
38 |
39 | async findByStatus(status: string): Promise {
40 | return this.requestRepository.find({
41 | where: {
42 | status,
43 | },
44 | relations: {
45 | provider: true
46 | }
47 | });
48 | }
49 |
50 | async create(request: Request): Promise {
51 |
52 | if (request.provider){
53 |
54 | let provider = await this.providerService.findById(request.provider.id)
55 |
56 | if (!provider)
57 | throw new HttpException('Provedor não encontrado!', HttpStatus.NOT_FOUND)
58 |
59 | return await this.requestRepository.save(request)
60 | }
61 |
62 | return await this.requestRepository.save(request)
63 | }
64 |
65 | async update(request: Request): Promise{
66 |
67 | let findRequest: Request = await this.findById(request.id);
68 |
69 | if (!findRequest || !request.id)
70 | throw new HttpException("Demanda não encotrada!", HttpStatus.NOT_FOUND)
71 |
72 | if (request.provider){
73 |
74 | let provider = await this.providerService.findById(request.provider.id)
75 |
76 | if (!provider)
77 | throw new HttpException("Provedor não encontrado!", HttpStatus.NOT_FOUND)
78 |
79 | return await this.requestRepository.save(request)
80 | }
81 |
82 | return await this.requestRepository.save(request)
83 | }
84 |
85 | async delete(id: number): Promise{
86 |
87 | let findRequest = await this.findById(id);
88 |
89 | if (!findRequest)
90 | throw new HttpException("Demanda não enontrada!", HttpStatus.NOT_FOUND);
91 |
92 | return await this.requestRepository.delete(id)
93 | }
94 | }
--------------------------------------------------------------------------------
/src/user/controllers/user.controller.ts:
--------------------------------------------------------------------------------
1 | import { Body, Controller, Get, HttpCode, HttpStatus, Param, ParseIntPipe, Post, Put, UseGuards } from "@nestjs/common";
2 | import { UserService } from "../services/user.service";
3 | import { User } from "../entities/user.entity";
4 | import { JwtAuthGuard } from "../../auth/guard/jwt-auth.guard";
5 | import { ApiBearerAuth, ApiTags } from "@nestjs/swagger";
6 |
7 | @ApiTags('User')
8 | @Controller("/user")
9 | @ApiBearerAuth()
10 | export class UserController{
11 |
12 | constructor(private readonly usuarioService: UserService){ }
13 | @UseGuards(JwtAuthGuard)
14 | @Get('/all')
15 | @HttpCode(HttpStatus.OK)
16 | findAll(): Promise{
17 | return this.usuarioService.findAll();
18 | }
19 |
20 | @UseGuards(JwtAuthGuard)
21 | @Get('/:id')
22 | @HttpCode(HttpStatus.OK)
23 | findById(@Param('id', ParseIntPipe) id: number): Promise{
24 | return this.usuarioService.findById(id)
25 | }
26 |
27 | @Post('/cadastrar')
28 | @HttpCode(HttpStatus.CREATED)
29 | async create(@Body() usuario: User): Promise{
30 | return this.usuarioService.create(usuario)
31 | }
32 |
33 | @UseGuards(JwtAuthGuard)
34 | @Put('/atualizar')
35 | @HttpCode(HttpStatus.OK)
36 | async update(@Body() usuario: User): Promise{
37 | return this.usuarioService.update(usuario)
38 | }
39 |
40 | }
--------------------------------------------------------------------------------
/src/user/entities/user.entity.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from "@nestjs/swagger"
2 | import { IsEmail, IsNotEmpty, MinLength } from "class-validator"
3 | import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"
4 |
5 | @Entity({name: "tb_users"})
6 | export class User {
7 |
8 | @ApiProperty()
9 | @PrimaryGeneratedColumn()
10 | id: number
11 |
12 | @ApiProperty()
13 | @IsNotEmpty()
14 | @Column({length: 255, nullable: false})
15 | nome: string
16 |
17 | @IsEmail()
18 | @IsNotEmpty()
19 | @ApiProperty({example: "email@email.com.br"})
20 | @Column({length: 255, nullable: false })
21 | usuario: string
22 |
23 | @ApiProperty()
24 | @MinLength(8)
25 | @IsNotEmpty()
26 | @Column({length: 255, nullable: false })
27 | senha: string
28 |
29 | @ApiProperty()
30 | @Column({length: 5000 })
31 | foto: string
32 |
33 | }
--------------------------------------------------------------------------------
/src/user/services/user.service.ts:
--------------------------------------------------------------------------------
1 | import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
2 | import { InjectRepository } from '@nestjs/typeorm';
3 | import { Repository } from 'typeorm';
4 | import { Bcrypt } from '../../auth/bcrypt/bcrypt';
5 | import { User } from '../entities/user.entity';
6 |
7 | @Injectable()
8 | export class UserService {
9 | constructor(
10 | @InjectRepository(User)
11 | private usuarioRepository: Repository,
12 | private bcrypt: Bcrypt
13 | ) { }
14 |
15 | async findByUsuario(usuario: string): Promise {
16 | return await this.usuarioRepository.findOne({
17 | where: {
18 | usuario: usuario
19 | }
20 | })
21 | }
22 |
23 | async findAll(): Promise {
24 | return await this.usuarioRepository.find(
25 | {
26 | relations:{
27 |
28 | }
29 | }
30 | );
31 |
32 | }
33 |
34 | async findById(id: number): Promise {
35 |
36 | let usuario = await this.usuarioRepository.findOne({
37 | where: {
38 | id
39 | },
40 | relations: {
41 |
42 | }
43 | });
44 |
45 | if (!usuario)
46 | throw new HttpException('Usuario não encontrado!', HttpStatus.NOT_FOUND);
47 |
48 | return usuario;
49 |
50 | }
51 |
52 | async create(usuario: User): Promise {
53 |
54 | let buscaUsuario = await this.findByUsuario(usuario.usuario);
55 |
56 | if (!buscaUsuario) {
57 | usuario.senha = await this.bcrypt.criptografarSenha(usuario.senha)
58 | return await this.usuarioRepository.save(usuario);
59 | }
60 |
61 | throw new HttpException("O Usuario ja existe!", HttpStatus.BAD_REQUEST);
62 |
63 | }
64 |
65 | async update(usuario: User): Promise {
66 |
67 | let updateUsuario: User = await this.findById(usuario.id);
68 | let buscaUsuario = await this.findByUsuario(usuario.usuario);
69 |
70 | if (!updateUsuario)
71 | throw new HttpException('Usuário não encontrado!', HttpStatus.NOT_FOUND);
72 |
73 | if (buscaUsuario && buscaUsuario.id !== usuario.id)
74 | throw new HttpException('Usuário (e-mail) já Cadastrado!', HttpStatus.BAD_REQUEST);
75 |
76 | usuario.senha = await this.bcrypt.criptografarSenha(usuario.senha)
77 | return await this.usuarioRepository.save(usuario);
78 |
79 | }
80 |
81 | }
--------------------------------------------------------------------------------
/src/user/user.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { TypeOrmModule } from '@nestjs/typeorm';
3 | import { User } from './entities/user.entity';
4 | import { UserService } from './services/user.service';
5 | import { Bcrypt } from '../auth/bcrypt/bcrypt';
6 | import { UserController } from './controllers/user.controller';
7 |
8 | @Module({
9 | imports: [TypeOrmModule.forFeature([User])],
10 | providers: [UserService, Bcrypt],
11 | controllers: [UserController],
12 | exports: [UserService],
13 | })
14 | export class UserModule {}
--------------------------------------------------------------------------------
/test/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { INestApplication } from '@nestjs/common';
3 | import * as request from 'supertest';
4 | import { AppModule } from './../src/app.module';
5 |
6 | describe('AppController (e2e)', () => {
7 | let app: INestApplication;
8 |
9 | beforeEach(async () => {
10 | const moduleFixture: TestingModule = await Test.createTestingModule({
11 | imports: [AppModule],
12 | }).compile();
13 |
14 | app = moduleFixture.createNestApplication();
15 | await app.init();
16 | });
17 |
18 | it('/ (GET)', () => {
19 | return request(app.getHttpServer())
20 | .get('/')
21 | .expect(200)
22 | .expect('Hello World!');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/test/jest-e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "moduleFileExtensions": ["js", "json", "ts"],
3 | "rootDir": ".",
4 | "testEnvironment": "node",
5 | "testRegex": ".e2e-spec.ts$",
6 | "transform": {
7 | "^.+\\.(t|j)s$": "ts-jest"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "target": "ES2021",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true,
14 | "skipLibCheck": true,
15 | "strictNullChecks": false,
16 | "noImplicitAny": false,
17 | "strictBindCallApply": false,
18 | "forceConsistentCasingInFileNames": false,
19 | "noFallthroughCasesInSwitch": false
20 | }
21 | }
22 |
--------------------------------------------------------------------------------