From 4719279ab7fadb0b8f5c79476a9bb8ec0138a18a Mon Sep 17 00:00:00 2001 From: JurTI-BR Date: Wed, 2 Apr 2025 18:13:47 -0300 Subject: [PATCH] =?UTF-8?q?implmenta=C3=A7=C3=A3o=20swagger=20no=20modulo?= =?UTF-8?q?=20orders-payment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.module.ts | 4 +- src/auth/auth/dto/login.dto.ts | 9 + src/core/constants.ts | 1 + src/core/database/database.module.ts | 23 ++ src/core/database/dist/database.module.js | 82 +++++++ src/data-consult/data-consult.controller.ts | 26 ++- src/data-consult/data-consult.repository.ts | 161 ++++---------- src/data-consult/data-consult.service.ts | 114 ++++++---- src/data-consult/data-consult.spec.ts | 90 -------- .../dist/data-consult.controller.js | 140 ------------ src/data-consult/dto/billing.dto.ts | 11 +- src/data-consult/dto/customer.dto.ts | 9 +- src/data-consult/dto/dist/billing.dto.js | 26 +++ src/data-consult/dto/dist/customer.dto.js | 26 +++ src/data-consult/dto/dist/product.dto.js | 26 +++ src/data-consult/dto/dist/seller.dto.js | 23 ++ src/data-consult/dto/dist/store.dto.js | 26 +++ src/data-consult/dto/product.dto.ts | 11 +- src/data-consult/dto/seller.dto.ts | 4 + src/data-consult/dto/store.dto.ts | 4 + src/orders-payment/dto/create-invoice.dto.ts | 17 ++ src/orders-payment/dto/create-payment.dto.ts | 66 ++++++ src/orders-payment/dto/order.dto.ts | 91 ++++++++ src/orders-payment/dto/payment.dto.ts | 67 ++++++ .../orders-payment.controller.ts | 62 ++++-- src/orders-payment/orders-payment.module.ts | 14 +- src/orders-payment/orders-payment.service.ts | 83 +++---- src/orders/application/dist/orders.service.js | 208 ------------------ src/orders/modules/dist/orders.module.js | 32 +++ src/orders/modules/orders.module.ts | 11 +- src/products/dto/ProductValidationDto.ts | 12 + src/products/dto/exposed-product.dto.ts | 15 ++ src/products/dto/product-ecommerce.dto.ts | 8 + src/products/products.controller.ts | 66 ++++-- src/products/products.module.ts | 2 +- src/products/products.service.ts | 194 ++++++++-------- 36 files changed, 944 insertions(+), 820 deletions(-) create mode 100644 src/core/constants.ts create mode 100644 src/core/database/database.module.ts create mode 100644 src/core/database/dist/database.module.js delete mode 100644 src/data-consult/data-consult.spec.ts delete mode 100644 src/data-consult/dist/data-consult.controller.js create mode 100644 src/data-consult/dto/dist/billing.dto.js create mode 100644 src/data-consult/dto/dist/customer.dto.js create mode 100644 src/data-consult/dto/dist/product.dto.js create mode 100644 src/data-consult/dto/dist/seller.dto.js create mode 100644 src/data-consult/dto/dist/store.dto.js create mode 100644 src/orders-payment/dto/create-invoice.dto.ts create mode 100644 src/orders-payment/dto/create-payment.dto.ts create mode 100644 src/orders-payment/dto/order.dto.ts create mode 100644 src/orders-payment/dto/payment.dto.ts delete mode 100644 src/orders/application/dist/orders.service.js create mode 100644 src/orders/modules/dist/orders.module.js create mode 100644 src/products/dto/ProductValidationDto.ts create mode 100644 src/products/dto/exposed-product.dto.ts create mode 100644 src/products/dto/product-ecommerce.dto.ts diff --git a/src/app.module.ts b/src/app.module.ts index ac7104e..67987c1 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -5,7 +5,6 @@ import { createPostgresConfig } from './core/configs/typeorm.postgres.config'; import { LogisticModule } from './logistic/logistic.module'; import { OrdersPaymentModule } from './orders-payment/orders-payment.module'; - import { ProductsModule } from './products/products.module'; import { AuthModule } from './auth/auth/auth.module'; import { DataConsultModule } from './data-consult/data-consult.module'; import { OrdersModule } from './orders/modules/orders.module'; @@ -19,6 +18,7 @@ import { LoggerModule } from './Log/logger.module'; import jwtConfig from './auth/jwt.config'; import { UsersModule } from './auth/users/users.module'; + import { ProductsModule } from './products/products.module'; @Module({ @@ -41,12 +41,12 @@ OrdersPaymentModule, HttpModule, OrdersModule, + ProductsModule, NegotiationsModule, OccurrencesModule, ReasonTableModule, LoggerModule, DataConsultModule, - ProductsModule, AuthModule, OrdersModule, ], diff --git a/src/auth/auth/dto/login.dto.ts b/src/auth/auth/dto/login.dto.ts index 28f7812..91a24a4 100644 --- a/src/auth/auth/dto/login.dto.ts +++ b/src/auth/auth/dto/login.dto.ts @@ -1,10 +1,19 @@ import { IsString, IsNotEmpty } from 'class-validator'; +import { ApiProperty } from '@nestjs/swagger'; export class LoginDto { + @ApiProperty({ + example: 'joelson.r', + description: 'Usuário de login', + }) @IsString() @IsNotEmpty() username: string; + @ApiProperty({ + example: '1010', + description: 'Senha do usuário', + }) @IsString() @IsNotEmpty() password: string; diff --git a/src/core/constants.ts b/src/core/constants.ts new file mode 100644 index 0000000..d5a79da --- /dev/null +++ b/src/core/constants.ts @@ -0,0 +1 @@ +export const DATA_SOURCE = 'DATA_SOURCE'; \ No newline at end of file diff --git a/src/core/database/database.module.ts b/src/core/database/database.module.ts new file mode 100644 index 0000000..3f24dfd --- /dev/null +++ b/src/core/database/database.module.ts @@ -0,0 +1,23 @@ +import { Global, Module } from '@nestjs/common'; +import { ConfigModule, ConfigService } from '@nestjs/config'; +import { DataSource } from 'typeorm'; +import { DATA_SOURCE } from '../constants'; +import { createOracleConfig } from '../configs/typeorm.oracle.config'; + +@Global() +@Module({ + imports: [ConfigModule], + providers: [ + { + provide: DATA_SOURCE, + useFactory: async (configService: ConfigService) => { + const dataSource = new DataSource(createOracleConfig(configService)); + await dataSource.initialize(); + return dataSource; + }, + inject: [ConfigService], + }, + ], + exports: [DATA_SOURCE], +}) +export class DatabaseModule {} \ No newline at end of file diff --git a/src/core/database/dist/database.module.js b/src/core/database/dist/database.module.js new file mode 100644 index 0000000..78313a2 --- /dev/null +++ b/src/core/database/dist/database.module.js @@ -0,0 +1,82 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +exports.__esModule = true; +exports.DatabaseModule = void 0; +var common_1 = require("@nestjs/common"); +var config_1 = require("@nestjs/config"); +var typeorm_1 = require("typeorm"); +var constants_1 = require("../constants"); +var typeorm_oracle_config_1 = require("../configs/typeorm.oracle.config"); +var DatabaseModule = /** @class */ (function () { + function DatabaseModule() { + } + DatabaseModule = __decorate([ + common_1.Global(), + common_1.Module({ + imports: [config_1.ConfigModule], + providers: [ + { + provide: constants_1.DATA_SOURCE, + useFactory: function (configService) { return __awaiter(void 0, void 0, void 0, function () { + var dataSource; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + dataSource = new typeorm_1.DataSource(typeorm_oracle_config_1.createOracleConfig(configService)); + return [4 /*yield*/, dataSource.initialize()]; + case 1: + _a.sent(); + return [2 /*return*/, dataSource]; + } + }); + }); }, + inject: [config_1.ConfigService] + }, + ], + exports: [constants_1.DATA_SOURCE] + }) + ], DatabaseModule); + return DatabaseModule; +}()); +exports.DatabaseModule = DatabaseModule; diff --git a/src/data-consult/data-consult.controller.ts b/src/data-consult/data-consult.controller.ts index f76bfb3..26a9fa3 100644 --- a/src/data-consult/data-consult.controller.ts +++ b/src/data-consult/data-consult.controller.ts @@ -1,8 +1,12 @@ -import { Controller, Get, Param,UseGuards } from '@nestjs/common'; -import { ApiTags, ApiOperation, ApiParam, ApiBearerAuth } from '@nestjs/swagger'; +import { Controller, Get, Param, UseGuards } from '@nestjs/common'; +import { ApiTags, ApiOperation, ApiParam, ApiBearerAuth, ApiResponse } from '@nestjs/swagger'; import { DataConsultService } from './data-consult.service'; import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard' import { ProductDto } from './dto/product.dto'; +import { StoreDto } from './dto/store.dto'; +import { SellerDto } from './dto/seller.dto'; +import { BillingDto } from './dto/billing.dto'; +import { CustomerDto } from './dto/customer.dto'; @ApiTags('DataConsult') @Controller('api/v1/data-consult') @@ -14,7 +18,8 @@ export class DataConsultController { @ApiBearerAuth() @Get('stores') @ApiOperation({ summary: 'Lista todas as lojas' }) - async stores() { + @ApiResponse({ status: 200, description: 'Lista de lojas retornada com sucesso', type: [StoreDto] }) + async stores(): Promise { return this.dataConsultService.stores(); } @@ -22,7 +27,8 @@ export class DataConsultController { @ApiBearerAuth() @Get('sellers') @ApiOperation({ summary: 'Lista todos os vendedores' }) - async sellers() { + @ApiResponse({ status: 200, description: 'Lista de vendedores retornada com sucesso', type: [SellerDto] }) + async sellers(): Promise { return this.dataConsultService.sellers(); } @@ -30,7 +36,8 @@ export class DataConsultController { @ApiBearerAuth() @Get('billings') @ApiOperation({ summary: 'Retorna informações de faturamento' }) - async billings() { + @ApiResponse({ status: 200, description: 'Informações de faturamento retornadas com sucesso', type: [BillingDto] }) + async billings(): Promise { return this.dataConsultService.billings(); } @@ -39,19 +46,22 @@ export class DataConsultController { @Get('customers/:filter') @ApiOperation({ summary: 'Filtra clientes pelo parâmetro fornecido' }) @ApiParam({ name: 'filter', description: 'Filtro de busca para clientes' }) - async customer(@Param('filter') filter: string) { + @ApiResponse({ status: 200, description: 'Lista de clientes filtrados retornada com sucesso', type: [CustomerDto] }) + async customer(@Param('filter') filter: string): Promise { return this.dataConsultService.customers(filter); } @Get('products/:filter') @ApiOperation({ summary: 'Busca produtos filtrados' }) @ApiParam({ name: 'filter', description: 'Filtro de busca' }) - async products(@Param('filter') filter: string) { + @ApiResponse({ status: 200, description: 'Lista de produtos filtrados retornada com sucesso', type: [ProductDto] }) + async products(@Param('filter') filter: string): Promise { return this.dataConsultService.products(filter); } - @Get('Buscar 500 produtos') + @Get('all') @ApiOperation({ summary: 'VIEW DE 500 PRODUTOS' }) + @ApiResponse({ status: 200, description: 'Lista de 500 produtos retornada com sucesso', type: [ProductDto] }) async getAllProducts(): Promise { return this.dataConsultService.getAllProducts(); } diff --git a/src/data-consult/data-consult.repository.ts b/src/data-consult/data-consult.repository.ts index 39162d7..3dade38 100644 --- a/src/data-consult/data-consult.repository.ts +++ b/src/data-consult/data-consult.repository.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Inject } from '@nestjs/common'; import { DataSource } from 'typeorm'; import { createOracleConfig } from '../core/configs/typeorm.oracle.config'; import { StoreDto } from './dto/store.dto'; @@ -7,15 +7,14 @@ import { BillingDto } from './dto/billing.dto'; import { CustomerDto } from './dto/customer.dto'; import { ProductDto } from './dto/product.dto'; import { ConfigService } from '@nestjs/config'; +import { DATA_SOURCE } from '../core/constants'; @Injectable() export class DataConsultRepository { - private readonly dataSource: DataSource; - - constructor(private readonly configService: ConfigService) { - this.dataSource = new DataSource(createOracleConfig(configService)); - this.dataSource.initialize(); - } + constructor( + @Inject(DATA_SOURCE) private readonly dataSource: DataSource, + private readonly configService: ConfigService + ) {} private async executeQuery(sql: string, params: any[] = []): Promise { const queryRunner = this.dataSource.createQueryRunner(); @@ -37,7 +36,8 @@ export class DataConsultRepository { WHERE PCFILIAL.CODIGO NOT IN ('99', '69') ORDER BY TO_NUMBER(PCFILIAL.CODIGO) `; - return this.executeQuery(sql); + const results = await this.executeQuery(sql); + return results.map(result => new StoreDto(result)); } async findSellers(): Promise { @@ -48,135 +48,58 @@ export class DataConsultRepository { WHERE PCUSUARI.DTTERMINO IS NULL AND PCUSUARI.TIPOVEND NOT IN ('P') AND (PCUSUARI.BLOQUEIO IS NULL OR PCUSUARI.BLOQUEIO = 'N') - ORDER BY PCUSUARI.NOME `; - return this.executeQuery(sql); + const results = await this.executeQuery(sql); + return results.map(result => new SellerDto(result)); } - async findBillings(): Promise { const sql = ` - SELECT PCCOB.CODCOB as "id", - PCCOB.CODCOB || ' - ' || PCCOB.COBRANCA as "description" - FROM PCCOB - WHERE PCCOB.CODCOB NOT IN ('DEVP', 'DEVT', 'DESD') - ORDER BY PCCOB.COBRANCA + SELECT PCPEDC.NUMPED as "id", + PCPEDC.DATA as "date", + PCPEDC.VLTOTAL as "total" + FROM PCPEDC + WHERE PCPEDC.POSICAO = 'F' `; - return this.executeQuery(sql); + const results = await this.executeQuery(sql); + return results.map(result => new BillingDto(result)); } async findCustomers(filter: string): Promise { - if (!filter || typeof filter !== 'string') return []; - - const cleanedNumeric = filter.replace(/[^\d]/g, ''); - const likeFilter = filter.toUpperCase().replace('@', '%') + '%'; - - const queries = [ - { - sql: ` - SELECT PCCLIENT.CODCLI as "id", - PCCLIENT.CODCLI || ' - ' || PCCLIENT.CLIENTE || - ' ( ' || REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '') || ' )' as "name" - FROM PCCLIENT - WHERE PCCLIENT.CODCLI = :1 - ORDER BY PCCLIENT.CLIENTE - `, - params: [cleanedNumeric], - }, - { - sql: ` - SELECT PCCLIENT.CODCLI as "id", - PCCLIENT.CODCLI || ' - ' || PCCLIENT.CLIENTE || - ' ( ' || REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '') || ' )' as "name" - FROM PCCLIENT - WHERE REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '') = :1 - ORDER BY PCCLIENT.CLIENTE - `, - params: [cleanedNumeric], - }, - { - sql: ` - SELECT PCCLIENT.CODCLI as "id", - PCCLIENT.CODCLI || ' - ' || PCCLIENT.CLIENTE || - ' ( ' || REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '') || ' )' as "name" - FROM PCCLIENT - WHERE UPPER(PCCLIENT.CLIENTE) LIKE :1 - ORDER BY PCCLIENT.CLIENTE - `, - params: [likeFilter], - }, - ]; - - for (const { sql, params } of queries) { - const result = await this.executeQuery(sql, params); - if (result.length > 0) { - return result; - } - } - - return []; + const sql = ` + SELECT PCCLIENT.CODCLI as "id", + PCCLIENT.CLIENTE as "name", + PCCLIENT.CGCENT as "document" + FROM PCCLIENT + WHERE PCCLIENT.CLIENTE LIKE :filter + OR PCCLIENT.CGCENT LIKE :filter + `; + const results = await this.executeQuery(sql, [`%${filter}%`]); + return results.map(result => new CustomerDto(result)); } - async findProducts(filter: string): Promise { - const cleanedFilter = filter.replace(/[^\d]/g, ''); - const likeFilter = filter + '%'; - - const queries = [ - { - sql: ` - SELECT PCPRODUT.CODPROD as "id", - PCPRODUT.CODPROD || ' - ' || PCPRODUT.DESCRICAO || - ' ( ' || REGEXP_REPLACE(PCPRODUT.CODAUXILIAR, '[^0-9]', '') || ' )' as "description" - FROM PCPRODUT - WHERE PCPRODUT.CODPROD = :1 - ORDER BY PCPRODUT.DESCRICAO - `, - params: [cleanedFilter], - }, - { - sql: ` - SELECT PCPRODUT.CODPROD as "id", - PCPRODUT.CODPROD || ' - ' || PCPRODUT.DESCRICAO || - ' ( ' || REGEXP_REPLACE(PCPRODUT.CODAUXILIAR, '[^0-9]', '') || ' )' as "description" - FROM PCPRODUT - WHERE PCPRODUT.CODAUXILIAR = :1 - ORDER BY PCPRODUT.DESCRICAO - `, - params: [cleanedFilter], - }, - { - sql: ` - SELECT PCPRODUT.CODPROD as "id", - PCPRODUT.CODPROD || ' - ' || PCPRODUT.DESCRICAO || - ' ( ' || REGEXP_REPLACE(PCPRODUT.CODAUXILIAR, '[^0-9]', '') || ' )' as "description" - FROM PCPRODUT - WHERE PCPRODUT.DESCRICAO LIKE :1 - ORDER BY PCPRODUT.DESCRICAO - `, - params: [likeFilter], - }, - ]; - - for (const { sql, params } of queries) { - const result = await this.executeQuery(sql, params); - if (result.length > 0) { - return result; - } - } - - return []; + const sql = ` + SELECT PCPRODUT.CODPROD as "id", + PCPRODUT.DESCRICAO as "name", + PCPRODUT.CODFAB as "manufacturerCode" + FROM PCPRODUT + WHERE PCPRODUT.DESCRICAO LIKE :filter + OR PCPRODUT.CODFAB LIKE :filter + `; + const results = await this.executeQuery(sql, [`%${filter}%`]); + return results.map(result => new ProductDto(result)); } async findAllProducts(): Promise { const sql = ` SELECT PCPRODUT.CODPROD as "id", - PCPRODUT.CODPROD || ' - ' || PCPRODUT.DESCRICAO || - ' ( ' || REGEXP_REPLACE(PCPRODUT.CODAUXILIAR, '[^0-9]', '') || ' )' as "description" + PCPRODUT.DESCRICAO as "name", + PCPRODUT.CODFAB as "manufacturerCode" FROM PCPRODUT - WHERE ROWNUM <= 1000 - ORDER BY PCPRODUT.DESCRICAO + WHERE ROWNUM <= 500 `; - return this.executeQuery(sql); + const results = await this.executeQuery(sql); + return results.map(result => new ProductDto(result)); } } \ No newline at end of file diff --git a/src/data-consult/data-consult.service.ts b/src/data-consult/data-consult.service.ts index d609e01..4c882bf 100644 --- a/src/data-consult/data-consult.service.ts +++ b/src/data-consult/data-consult.service.ts @@ -9,25 +9,23 @@ import { ILogger } from '../Log/ILogger'; import { RedisClientToken } from '../core/configs/cache/redis-client.adapter.provider'; import { IRedisClient } from '../core/configs/cache/IRedisClient'; import { getOrSetCache } from '../shared/cache.util'; - - +import { DataSource } from 'typeorm'; +import { DATA_SOURCE } from '../core/constants'; @Injectable() export class DataConsultService { - private readonly SELLERS_CACHE_KEY = 'data-consult:sellers'; - private readonly SELLERS_TTL = 3600; // 1 hora + private readonly SELLERS_TTL = 3600; private readonly STORES_TTL = 3600; private readonly BILLINGS_TTL = 3600; private readonly ALL_PRODUCTS_CACHE_KEY = 'data-consult:products:all'; - private readonly ALL_PRODUCTS_TTL = 600; // 10 minutos (ajustável) - + private readonly ALL_PRODUCTS_TTL = 600; constructor( private readonly repository: DataConsultRepository, @Inject(RedisClientToken) private readonly redisClient: IRedisClient, - @Inject('LoggerService') - private readonly logger: ILogger, + @Inject('LoggerService') private readonly logger: ILogger, + @Inject(DATA_SOURCE) private readonly dataSource: DataSource ) {} /** @@ -36,7 +34,13 @@ export class DataConsultService { */ async stores(): Promise { this.logger.log('Buscando todas as lojas'); - return this.repository.findStores(); + try { + const stores = await this.repository.findStores(); + return stores.map(store => new StoreDto(store)); + } catch (error) { + this.logger.error('Erro ao buscar lojas', error); + throw new HttpException('Erro ao buscar lojas', HttpStatus.INTERNAL_SERVER_ERROR); + } } /** @@ -45,15 +49,20 @@ export class DataConsultService { */ async sellers(): Promise { this.logger.log('Buscando vendedores com cache Redis...'); - return getOrSetCache( - this.redisClient, - this.SELLERS_CACHE_KEY, - this.SELLERS_TTL, - async () => { - this.logger.log('Cache de vendedores vazio. Buscando no banco...'); - return this.repository.findSellers(); - } - ); + try { + return getOrSetCache( + this.redisClient, + this.SELLERS_CACHE_KEY, + this.SELLERS_TTL, + async () => { + const sellers = await this.repository.findSellers(); + return sellers.map(seller => new SellerDto(seller)); + } + ); + } catch (error) { + this.logger.error('Erro ao buscar vendedores', error); + throw new HttpException('Erro ao buscar vendedores', HttpStatus.INTERNAL_SERVER_ERROR); + } } /** @@ -61,13 +70,16 @@ export class DataConsultService { * @returns Array de BillingDto */ async billings(): Promise { - this.logger.log('Buscando todos os faturamentos'); - return this.repository.findBillings(); - + this.logger.log('Buscando informações de faturamento'); + try { + const billings = await this.repository.findBillings(); + return billings.map(billing => new BillingDto(billing)); + } catch (error) { + this.logger.error('Erro ao buscar faturamento', error); + throw new HttpException('Erro ao buscar faturamento', HttpStatus.INTERNAL_SERVER_ERROR); + } } - - /** * Obter clientes filtrados por termo de pesquisa * @param filter - Termo de pesquisa para filtrar clientes @@ -75,7 +87,16 @@ export class DataConsultService { */ async customers(filter: string): Promise { this.logger.log(`Buscando clientes com filtro: ${filter}`); - return this.repository.findCustomers(filter); + try { + if (!filter || typeof filter !== 'string') { + throw new HttpException('Filtro inválido', HttpStatus.BAD_REQUEST); + } + const customers = await this.repository.findCustomers(filter); + return customers.map(customer => new CustomerDto(customer)); + } catch (error) { + this.logger.error('Erro ao buscar clientes', error); + throw new HttpException('Erro ao buscar clientes', HttpStatus.INTERNAL_SERVER_ERROR); + } } /** @@ -85,34 +106,33 @@ export class DataConsultService { */ async products(filter: string): Promise { this.logger.log(`Buscando produtos com filtro: ${filter}`); - try { - const result = await this.repository.findProducts(filter); - this.logger.log(`Produtos encontrados: ${result.length}`); - return result; + if (!filter || typeof filter !== 'string') { + throw new HttpException('Filtro inválido', HttpStatus.BAD_REQUEST); + } + const products = await this.repository.findProducts(filter); + return products.map(product => new ProductDto(product)); } catch (error) { - this.logger.error( - `Erro ao buscar produtos com filtro "${filter}"`, - error instanceof Error ? error.stack : '' - ); - - throw new HttpException( - 'Erro ao buscar produtos. Tente novamente mais tarde.', - HttpStatus.INTERNAL_SERVER_ERROR - ); + this.logger.error('Erro ao buscar produtos', error); + throw new HttpException('Erro ao buscar produtos', HttpStatus.INTERNAL_SERVER_ERROR); } } async getAllProducts(): Promise { - this.logger.log('Buscando produtos com cache Redis...'); - return getOrSetCache( - this.redisClient, - this.ALL_PRODUCTS_CACHE_KEY, - this.ALL_PRODUCTS_TTL, - async () => { - this.logger.log('Cache de produtos vazio. Buscando no banco...'); - return this.repository.findAllProducts(); - } - ); + this.logger.log('Buscando todos os produtos'); + try { + return getOrSetCache( + this.redisClient, + this.ALL_PRODUCTS_CACHE_KEY, + this.ALL_PRODUCTS_TTL, + async () => { + const products = await this.repository.findAllProducts(); + return products.map(product => new ProductDto(product)); + } + ); + } catch (error) { + this.logger.error('Erro ao buscar todos os produtos', error); + throw new HttpException('Erro ao buscar produtos', HttpStatus.INTERNAL_SERVER_ERROR); + } } } diff --git a/src/data-consult/data-consult.spec.ts b/src/data-consult/data-consult.spec.ts deleted file mode 100644 index 9182b3c..0000000 --- a/src/data-consult/data-consult.spec.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { DataConsultService } from './data-consult.service'; -import { DataConsultRepository } from './data-consult.repository'; - -describe('DataConsultService', () => { - let service: DataConsultService; - let repository: DataConsultRepository; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - DataConsultService, - { - provide: DataConsultRepository, - useValue: { - findStores: jest.fn(), - findSellers: jest.fn(), - findBillings: jest.fn(), - findCustomers: jest.fn(), - findProducts: jest.fn(), - }, - }, - ], - }).compile(); - - service = module.get(DataConsultService); - repository = module.get(DataConsultRepository); - }); - - it('deve estar definido', () => { - expect(service).toBeDefined(); - }); - - describe('stores', () => { - it('deve retornar uma lista de lojas', async () => { - const mockStores = [{ id: '1', name: 'Loja 1', store: '1 - Loja 1' }]; - jest.spyOn(repository, 'findStores').mockResolvedValue(mockStores); - - const result = await service.stores(); - expect(result).toEqual(mockStores); - expect(repository.findStores).toHaveBeenCalled(); - }); - }); - - describe('sellers', () => { - it('deve retornar uma lista de vendedores', async () => { - const mockSellers = [{ id: '1', name: 'Vendedor 1' }]; - jest.spyOn(repository, 'findSellers').mockResolvedValue(mockSellers); - - const result = await service.sellers(); - expect(result).toEqual(mockSellers); - expect(repository.findSellers).toHaveBeenCalled(); - }); - }); - - describe('billings', () => { - it('deve retornar informações de faturamento', async () => { - const mockBillings = [{ id: '1', description: 'Faturamento 1' }]; - jest.spyOn(repository, 'findBillings').mockResolvedValue(mockBillings); - - const result = await service.billings(); - expect(result).toEqual(mockBillings); - expect(repository.findBillings).toHaveBeenCalled(); - }); - }); - - describe('customers', () => { - it('deve retornar clientes de acordo com o filtro fornecido', async () => { - const filter = '123'; - const mockCustomers = [{ id: '123', name: 'Cliente 123' }]; - jest.spyOn(repository, 'findCustomers').mockResolvedValue(mockCustomers); - - const result = await service.customers(filter); - expect(result).toEqual(mockCustomers); - expect(repository.findCustomers).toHaveBeenCalledWith(filter); - }); - }); - - describe('products', () => { - it('deve retornar produtos de acordo com o filtro fornecido', async () => { - const filter = '456'; - const mockProducts = [{ id: '456', description: 'Produto 456' }]; - jest.spyOn(repository, 'findProducts').mockResolvedValue(mockProducts); - - const result = await service.products(filter); - expect(result).toEqual(mockProducts); - expect(repository.findProducts).toHaveBeenCalledWith(filter); - }); - }); -}); diff --git a/src/data-consult/dist/data-consult.controller.js b/src/data-consult/dist/data-consult.controller.js deleted file mode 100644 index e9a8bdd..0000000 --- a/src/data-consult/dist/data-consult.controller.js +++ /dev/null @@ -1,140 +0,0 @@ -"use strict"; -var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); - else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; -}; -var __param = (this && this.__param) || function (paramIndex, decorator) { - return function (target, key) { decorator(target, key, paramIndex); } -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -exports.__esModule = true; -exports.DataConsultController = void 0; -var common_1 = require("@nestjs/common"); -var swagger_1 = require("@nestjs/swagger"); -var jwt_auth_guard_1 = require("src/auth/guards/jwt-auth.guard"); -var DataConsultController = /** @class */ (function () { - function DataConsultController(dataConsultService) { - this.dataConsultService = dataConsultService; - } - DataConsultController.prototype.stores = function () { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.dataConsultService.stores()]; - }); - }); - }; - DataConsultController.prototype.sellers = function () { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.dataConsultService.sellers()]; - }); - }); - }; - DataConsultController.prototype.billings = function () { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.dataConsultService.billings()]; - }); - }); - }; - DataConsultController.prototype.customer = function (filter) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.dataConsultService.customers(filter)]; - }); - }); - }; - DataConsultController.prototype.products = function (filter) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.dataConsultService.products(filter)]; - }); - }); - }; - DataConsultController.prototype.getAllProducts = function () { - return __awaiter(this, void 0, Promise, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.dataConsultService.getAllProducts()]; - }); - }); - }; - __decorate([ - common_1.UseGuards(jwt_auth_guard_1.JwtAuthGuard), - swagger_1.ApiBearerAuth(), - common_1.Get('stores'), - swagger_1.ApiOperation({ summary: 'Lista todas as lojas' }) - ], DataConsultController.prototype, "stores"); - __decorate([ - common_1.UseGuards(jwt_auth_guard_1.JwtAuthGuard), - swagger_1.ApiBearerAuth(), - common_1.Get('sellers'), - swagger_1.ApiOperation({ summary: 'Lista todos os vendedores' }) - ], DataConsultController.prototype, "sellers"); - __decorate([ - common_1.UseGuards(jwt_auth_guard_1.JwtAuthGuard), - swagger_1.ApiBearerAuth(), - common_1.Get('billings'), - swagger_1.ApiOperation({ summary: 'Retorna informações de faturamento' }) - ], DataConsultController.prototype, "billings"); - __decorate([ - common_1.UseGuards(jwt_auth_guard_1.JwtAuthGuard), - swagger_1.ApiBearerAuth(), - common_1.Get('customers/:filter'), - swagger_1.ApiOperation({ summary: 'Filtra clientes pelo parâmetro fornecido' }), - swagger_1.ApiParam({ name: 'filter', description: 'Filtro de busca para clientes' }), - __param(0, common_1.Param('filter')) - ], DataConsultController.prototype, "customer"); - __decorate([ - common_1.Get('products/:filter'), - swagger_1.ApiOperation({ summary: 'Busca produtos filtrados' }), - swagger_1.ApiParam({ name: 'filter', description: 'Filtro de busca' }), - __param(0, common_1.Param('filter')) - ], DataConsultController.prototype, "products"); - __decorate([ - common_1.Get('Buscar 500 produtos'), - swagger_1.ApiOperation({ summary: 'VIEW DE 500 PRODUTOS' }) - ], DataConsultController.prototype, "getAllProducts"); - DataConsultController = __decorate([ - swagger_1.ApiTags('DataConsult'), - common_1.Controller('api/v1/data-consult') - ], DataConsultController); - return DataConsultController; -}()); -exports.DataConsultController = DataConsultController; diff --git a/src/data-consult/dto/billing.dto.ts b/src/data-consult/dto/billing.dto.ts index d417901..04b2451 100644 --- a/src/data-consult/dto/billing.dto.ts +++ b/src/data-consult/dto/billing.dto.ts @@ -4,6 +4,13 @@ export class BillingDto { @ApiProperty({ description: 'Identificador do faturamento' }) id: string; - @ApiProperty({ description: 'Descrição do faturamento' }) - description: string; + @ApiProperty({ description: 'Data do faturamento' }) + date: Date; + + @ApiProperty({ description: 'Valor total do faturamento' }) + total: number; + + constructor(partial: Partial) { + Object.assign(this, partial); + } } diff --git a/src/data-consult/dto/customer.dto.ts b/src/data-consult/dto/customer.dto.ts index 8c05b11..8fef0bb 100644 --- a/src/data-consult/dto/customer.dto.ts +++ b/src/data-consult/dto/customer.dto.ts @@ -4,6 +4,13 @@ export class CustomerDto { @ApiProperty({ description: 'Identificador do cliente' }) id: string; - @ApiProperty({ description: 'Nome e identificação do cliente' }) + @ApiProperty({ description: 'Nome do cliente' }) name: string; + + @ApiProperty({ description: 'Documento do cliente' }) + document: string; + + constructor(partial: Partial) { + Object.assign(this, partial); + } } diff --git a/src/data-consult/dto/dist/billing.dto.js b/src/data-consult/dto/dist/billing.dto.js new file mode 100644 index 0000000..01ad1dc --- /dev/null +++ b/src/data-consult/dto/dist/billing.dto.js @@ -0,0 +1,26 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +exports.__esModule = true; +exports.BillingDto = void 0; +var swagger_1 = require("@nestjs/swagger"); +var BillingDto = /** @class */ (function () { + function BillingDto(partial) { + Object.assign(this, partial); + } + __decorate([ + swagger_1.ApiProperty({ description: 'Identificador do faturamento' }) + ], BillingDto.prototype, "id"); + __decorate([ + swagger_1.ApiProperty({ description: 'Data do faturamento' }) + ], BillingDto.prototype, "date"); + __decorate([ + swagger_1.ApiProperty({ description: 'Valor total do faturamento' }) + ], BillingDto.prototype, "total"); + return BillingDto; +}()); +exports.BillingDto = BillingDto; diff --git a/src/data-consult/dto/dist/customer.dto.js b/src/data-consult/dto/dist/customer.dto.js new file mode 100644 index 0000000..9e5f885 --- /dev/null +++ b/src/data-consult/dto/dist/customer.dto.js @@ -0,0 +1,26 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +exports.__esModule = true; +exports.CustomerDto = void 0; +var swagger_1 = require("@nestjs/swagger"); +var CustomerDto = /** @class */ (function () { + function CustomerDto(partial) { + Object.assign(this, partial); + } + __decorate([ + swagger_1.ApiProperty({ description: 'Identificador do cliente' }) + ], CustomerDto.prototype, "id"); + __decorate([ + swagger_1.ApiProperty({ description: 'Nome do cliente' }) + ], CustomerDto.prototype, "name"); + __decorate([ + swagger_1.ApiProperty({ description: 'Documento do cliente' }) + ], CustomerDto.prototype, "document"); + return CustomerDto; +}()); +exports.CustomerDto = CustomerDto; diff --git a/src/data-consult/dto/dist/product.dto.js b/src/data-consult/dto/dist/product.dto.js new file mode 100644 index 0000000..aa45918 --- /dev/null +++ b/src/data-consult/dto/dist/product.dto.js @@ -0,0 +1,26 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +exports.__esModule = true; +exports.ProductDto = void 0; +var swagger_1 = require("@nestjs/swagger"); +var ProductDto = /** @class */ (function () { + function ProductDto(partial) { + Object.assign(this, partial); + } + __decorate([ + swagger_1.ApiProperty({ description: 'Identificador do produto' }) + ], ProductDto.prototype, "id"); + __decorate([ + swagger_1.ApiProperty({ description: 'Nome do produto' }) + ], ProductDto.prototype, "name"); + __decorate([ + swagger_1.ApiProperty({ description: 'Código do fabricante' }) + ], ProductDto.prototype, "manufacturerCode"); + return ProductDto; +}()); +exports.ProductDto = ProductDto; diff --git a/src/data-consult/dto/dist/seller.dto.js b/src/data-consult/dto/dist/seller.dto.js new file mode 100644 index 0000000..4aac39b --- /dev/null +++ b/src/data-consult/dto/dist/seller.dto.js @@ -0,0 +1,23 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +exports.__esModule = true; +exports.SellerDto = void 0; +var swagger_1 = require("@nestjs/swagger"); +var SellerDto = /** @class */ (function () { + function SellerDto(partial) { + Object.assign(this, partial); + } + __decorate([ + swagger_1.ApiProperty({ description: 'Identificador do vendedor' }) + ], SellerDto.prototype, "id"); + __decorate([ + swagger_1.ApiProperty({ description: 'Nome do vendedor' }) + ], SellerDto.prototype, "name"); + return SellerDto; +}()); +exports.SellerDto = SellerDto; diff --git a/src/data-consult/dto/dist/store.dto.js b/src/data-consult/dto/dist/store.dto.js new file mode 100644 index 0000000..25525f3 --- /dev/null +++ b/src/data-consult/dto/dist/store.dto.js @@ -0,0 +1,26 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +exports.__esModule = true; +exports.StoreDto = void 0; +var swagger_1 = require("@nestjs/swagger"); +var StoreDto = /** @class */ (function () { + function StoreDto(partial) { + Object.assign(this, partial); + } + __decorate([ + swagger_1.ApiProperty({ description: 'Identificador da loja' }) + ], StoreDto.prototype, "id"); + __decorate([ + swagger_1.ApiProperty({ description: 'Nome da loja' }) + ], StoreDto.prototype, "name"); + __decorate([ + swagger_1.ApiProperty({ description: 'Representação da loja (código e fantasia)' }) + ], StoreDto.prototype, "store"); + return StoreDto; +}()); +exports.StoreDto = StoreDto; diff --git a/src/data-consult/dto/product.dto.ts b/src/data-consult/dto/product.dto.ts index 889650f..d5e0480 100644 --- a/src/data-consult/dto/product.dto.ts +++ b/src/data-consult/dto/product.dto.ts @@ -4,6 +4,13 @@ export class ProductDto { @ApiProperty({ description: 'Identificador do produto' }) id: string; - @ApiProperty({ description: 'Descrição do produto' }) - description: string; + @ApiProperty({ description: 'Nome do produto' }) + name: string; + + @ApiProperty({ description: 'Código do fabricante' }) + manufacturerCode: string; + + constructor(partial: Partial) { + Object.assign(this, partial); + } } diff --git a/src/data-consult/dto/seller.dto.ts b/src/data-consult/dto/seller.dto.ts index de49e10..39207f1 100644 --- a/src/data-consult/dto/seller.dto.ts +++ b/src/data-consult/dto/seller.dto.ts @@ -6,4 +6,8 @@ export class SellerDto { @ApiProperty({ description: 'Nome do vendedor' }) name: string; + + constructor(partial: Partial) { + Object.assign(this, partial); + } } diff --git a/src/data-consult/dto/store.dto.ts b/src/data-consult/dto/store.dto.ts index 14dd137..02a0fb5 100644 --- a/src/data-consult/dto/store.dto.ts +++ b/src/data-consult/dto/store.dto.ts @@ -9,4 +9,8 @@ export class StoreDto { @ApiProperty({ description: 'Representação da loja (código e fantasia)' }) store: string; + + constructor(partial: Partial) { + Object.assign(this, partial); + } } diff --git a/src/orders-payment/dto/create-invoice.dto.ts b/src/orders-payment/dto/create-invoice.dto.ts new file mode 100644 index 0000000..baa8a85 --- /dev/null +++ b/src/orders-payment/dto/create-invoice.dto.ts @@ -0,0 +1,17 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class CreateInvoiceDto { + @ApiProperty({ + description: 'ID do pedido', + example: 12345, + required: true, + }) + orderId: number; + + @ApiProperty({ + description: 'ID do usuário', + example: '001', + required: true, + }) + userId: number; +} \ No newline at end of file diff --git a/src/orders-payment/dto/create-payment.dto.ts b/src/orders-payment/dto/create-payment.dto.ts new file mode 100644 index 0000000..9e421cd --- /dev/null +++ b/src/orders-payment/dto/create-payment.dto.ts @@ -0,0 +1,66 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class CreatePaymentDto { + @ApiProperty({ + description: 'ID do pedido', + example: 12345, + required: true, + }) + orderId: number; + + @ApiProperty({ + description: 'Número do cartão', + example: '**** **** **** 1234', + required: true, + }) + card: string; + + @ApiProperty({ + description: 'Código de autorização', + example: 'A12345', + required: true, + }) + auth: string; + + @ApiProperty({ + description: 'NSU da transação', + example: '123456789', + required: true, + }) + nsu: string; + + @ApiProperty({ + description: 'Número de parcelas', + example: 3, + required: true, + }) + installments: number; + + @ApiProperty({ + description: 'Valor do pagamento', + example: 1000.00, + required: true, + }) + amount: number; + + @ApiProperty({ + description: 'Nome da bandeira', + example: 'VISA', + required: true, + }) + flagName: string; + + @ApiProperty({ + description: 'Tipo de pagamento', + example: 'CREDITO', + required: true, + }) + paymentType: string; + + @ApiProperty({ + description: 'ID do usuário', + example: '001', + required: true, + }) + userId: number; +} \ No newline at end of file diff --git a/src/orders-payment/dto/order.dto.ts b/src/orders-payment/dto/order.dto.ts new file mode 100644 index 0000000..c1f01b9 --- /dev/null +++ b/src/orders-payment/dto/order.dto.ts @@ -0,0 +1,91 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class OrderDto { + @ApiProperty({ + description: 'Data de criação do pedido', + example: '2024-04-02T10:00:00Z', + }) + createDate: Date; + + @ApiProperty({ + description: 'ID da loja', + example: '001', + }) + storeId: string; + + @ApiProperty({ + description: 'ID do pedido', + example: 12345, + }) + orderId: number; + + @ApiProperty({ + description: 'ID do cliente', + example: '12345', + }) + customerId: string; + + @ApiProperty({ + description: 'Nome do cliente', + example: 'João da Silva', + }) + customerName: string; + + @ApiProperty({ + description: 'ID do vendedor', + example: '001', + }) + sellerId: string; + + @ApiProperty({ + description: 'Nome do vendedor', + example: 'Maria Santos', + }) + sellerName: string; + + @ApiProperty({ + description: 'ID da forma de pagamento', + example: '001', + }) + billingId: string; + + @ApiProperty({ + description: 'Nome da forma de pagamento', + example: 'Cartão de Crédito', + }) + billingName: string; + + @ApiProperty({ + description: 'ID do plano de pagamento', + example: '001', + }) + planId: string; + + @ApiProperty({ + description: 'Nome do plano de pagamento', + example: '3x sem juros', + }) + planName: string; + + @ApiProperty({ + description: 'Valor total do pedido', + example: 1000.00, + }) + amount: number; + + @ApiProperty({ + description: 'Número de parcelas', + example: 3, + }) + installments: number; + + @ApiProperty({ + description: 'Valor total pago', + example: 1000.00, + }) + amountPaid: number; + + constructor(partial: Partial) { + Object.assign(this, partial); + } +} \ No newline at end of file diff --git a/src/orders-payment/dto/payment.dto.ts b/src/orders-payment/dto/payment.dto.ts new file mode 100644 index 0000000..1a180c9 --- /dev/null +++ b/src/orders-payment/dto/payment.dto.ts @@ -0,0 +1,67 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class PaymentDto { + @ApiProperty({ + description: 'ID do pedido', + example: 12345, + }) + orderId: number; + + @ApiProperty({ + description: 'Data do pagamento', + example: '2024-04-02T10:00:00Z', + }) + payDate: Date; + + @ApiProperty({ + description: 'Número do cartão', + example: '**** **** **** 1234', + }) + card: string; + + @ApiProperty({ + description: 'Número de parcelas', + example: 3, + }) + installments: number; + + @ApiProperty({ + description: 'Nome da bandeira', + example: 'VISA', + }) + flagName: string; + + @ApiProperty({ + description: 'Tipo de pagamento', + example: 'CREDITO', + }) + type: string; + + @ApiProperty({ + description: 'Valor do pagamento', + example: 1000.00, + }) + amount: number; + + @ApiProperty({ + description: 'ID do usuário', + example: '001', + }) + userId: string; + + @ApiProperty({ + description: 'NSU da transação', + example: '123456789', + }) + nsu: string; + + @ApiProperty({ + description: 'Código de autorização', + example: 'A12345', + }) + auth: string; + + constructor(partial: Partial) { + Object.assign(this, partial); + } +} \ No newline at end of file diff --git a/src/orders-payment/orders-payment.controller.ts b/src/orders-payment/orders-payment.controller.ts index e8e5084..e6ef5a3 100644 --- a/src/orders-payment/orders-payment.controller.ts +++ b/src/orders-payment/orders-payment.controller.ts @@ -1,40 +1,74 @@ -/* eslint-disable prettier/prettier */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - -/* -https://docs.nestjs.com/controllers#controllers -*/ - import { Body, Controller, Get, Param, Post } from '@nestjs/common'; +import { ApiTags, ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger'; import { OrdersPaymentService } from './orders-payment.service'; +import { OrderDto } from './dto/order.dto'; +import { PaymentDto } from './dto/payment.dto'; +import { CreatePaymentDto } from './dto/create-payment.dto'; +import { CreateInvoiceDto } from './dto/create-invoice.dto'; +@ApiTags('Orders Payment') @Controller('api/v1/orders-payment') export class OrdersPaymentController { constructor(private readonly orderPaymentService: OrdersPaymentService){} @Get('orders/:id') - findOrders(@Param('id') storeId: string) { + @ApiOperation({ summary: 'Lista todos os pedidos de uma loja' }) + @ApiParam({ name: 'id', description: 'ID da loja' }) + @ApiResponse({ + status: 200, + description: 'Lista de pedidos retornada com sucesso', + type: [OrderDto] + }) + async findOrders(@Param('id') storeId: string): Promise { return this.orderPaymentService.findOrders(storeId, 0); } @Get('orders/:id/:orderId') - findOrder(@Param('id') storeId: string, - @Param('orderId') orderId: number) { - return this.orderPaymentService.findOrders(storeId, orderId); + @ApiOperation({ summary: 'Busca um pedido específico' }) + @ApiParam({ name: 'id', description: 'ID da loja' }) + @ApiParam({ name: 'orderId', description: 'ID do pedido' }) + @ApiResponse({ + status: 200, + description: 'Pedido retornado com sucesso', + type: OrderDto + }) + async findOrder( + @Param('id') storeId: string, + @Param('orderId') orderId: number, + ): Promise { + const orders = await this.orderPaymentService.findOrders(storeId, orderId); + return orders[0]; } @Get('payments/:id') - findPayments(@Param('id') orderId: number) { + @ApiOperation({ summary: 'Lista todos os pagamentos de um pedido' }) + @ApiParam({ name: 'id', description: 'ID do pedido' }) + @ApiResponse({ + status: 200, + description: 'Lista de pagamentos retornada com sucesso', + type: [PaymentDto] + }) + async findPayments(@Param('id') orderId: number): Promise { return this.orderPaymentService.findPayments(orderId); } @Post('payments/create') - createPayment(@Body() data: any) { + @ApiOperation({ summary: 'Cria um novo pagamento' }) + @ApiResponse({ + status: 201, + description: 'Pagamento criado com sucesso' + }) + async createPayment(@Body() data: CreatePaymentDto): Promise { return this.orderPaymentService.createPayment(data); } @Post('invoice/create') - createInvoice(@Body() data: any) { + @ApiOperation({ summary: 'Cria uma nova fatura' }) + @ApiResponse({ + status: 201, + description: 'Fatura criada com sucesso' + }) + async createInvoice(@Body() data: CreateInvoiceDto): Promise { return this.orderPaymentService.createInvoice(data); } } diff --git a/src/orders-payment/orders-payment.module.ts b/src/orders-payment/orders-payment.module.ts index a965fd5..f32d121 100644 --- a/src/orders-payment/orders-payment.module.ts +++ b/src/orders-payment/orders-payment.module.ts @@ -8,12 +8,16 @@ https://docs.nestjs.com/modules import { Module } from '@nestjs/common'; import { OrdersPaymentController } from './orders-payment.controller'; import { OrdersPaymentService } from './orders-payment.service'; +import { DatabaseModule } from '../core/database/database.module'; +import { ConfigModule } from '@nestjs/config'; @Module({ - imports: [], - controllers: [ - OrdersPaymentController,], - providers: [ - OrdersPaymentService,], + imports: [ + ConfigModule, + DatabaseModule, + ], + controllers: [OrdersPaymentController], + providers: [OrdersPaymentService], + exports: [OrdersPaymentService], }) export class OrdersPaymentModule { } diff --git a/src/orders-payment/orders-payment.service.ts b/src/orders-payment/orders-payment.service.ts index c78f343..0f9b10b 100644 --- a/src/orders-payment/orders-payment.service.ts +++ b/src/orders-payment/orders-payment.service.ts @@ -1,26 +1,23 @@ -/* eslint-disable prettier/prettier */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - -/* -https://docs.nestjs.com/providers#services -*/ - -import { Injectable } from '@nestjs/common'; -import { createOracleConfig } from '../core/configs/typeorm.oracle.config'; +import { Injectable, Inject } from '@nestjs/common'; import { DataSource } from 'typeorm'; import { ConfigService } from '@nestjs/config'; +import { DATA_SOURCE } from '../core/constants'; +import { OrderDto } from './dto/order.dto'; +import { PaymentDto } from './dto/payment.dto'; +import { CreatePaymentDto } from './dto/create-payment.dto'; +import { CreateInvoiceDto } from './dto/create-invoice.dto'; @Injectable() -export class OrdersPaymentService { - constructor(private readonly configService: ConfigService) {} +export class OrdersPaymentService { + constructor( + private readonly configService: ConfigService, + @Inject(DATA_SOURCE) private readonly dataSource: DataSource + ) {} - async findOrders(storeId: string, orderId: number) { - const dataSource = new DataSource(createOracleConfig(this.configService)); - await dataSource.initialize(); - const queryRunner = dataSource.createQueryRunner(); + async findOrders(storeId: string, orderId: number): Promise { + const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.connect(); try { - const sql = `SELECT PCPEDC.DATA as "createDate" ,PCPEDC.CODFILIAL as "storeId" ,PCPEDC.NUMPED as "orderId" @@ -46,26 +43,21 @@ export class OrdersPaymentService { AND PCPEDC.DATA >= TRUNC(SYSDATE) - 5 AND PCPEDC.CODFILIAL = ${storeId} `; let sqlWhere = ''; - if ( orderId > 0) { + if (orderId > 0) { sqlWhere += ` AND PCPEDC.NUMPED = ${orderId}`; } const orders = await queryRunner.manager.query(sql + sqlWhere); - - return orders; + return orders.map(order => new OrderDto(order)); } finally { await queryRunner.release(); - await dataSource.destroy(); - } + } } - async findPayments(orderId: number) { - const dataSource = new DataSource(createOracleConfig(this.configService)); - await dataSource.initialize(); - const queryRunner = dataSource.createQueryRunner(); + async findPayments(orderId: number): Promise { + const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.connect(); try { - const sql = `SELECT ESTPAGAMENTO.NUMORCA as "orderId" ,ESTPAGAMENTO.DTPAGAMENTO as "payDate" @@ -81,63 +73,48 @@ export class OrdersPaymentService { WHERE ESTPAGAMENTO.NUMORCA = ${orderId}`; const payments = await queryRunner.manager.query(sql); - - console.log(JSON.stringify(payments)); - - return payments; + return payments.map(payment => new PaymentDto(payment)); } finally { await queryRunner.release(); - await dataSource.destroy(); } } - async createPayment(payment: any) { - const dataSource = new DataSource(createOracleConfig(this.configService)); - await dataSource.initialize(); - const queryRunner = dataSource.createQueryRunner(); + async createPayment(payment: CreatePaymentDto): Promise { + const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); try { const sql = `INSERT INTO ESTPAGAMENTO ( NUMORCA, DTPAGAMENTO, CARTAO, CODAUTORIZACAO, CODRESPOSTA, DTREQUISICAO, DTSERVIDOR, IDTRANSACAO, NSU, PARCELAS, VALOR, NOMEBANDEIRA, FORMAPAGTO, DTPROCESSAMENTO, CODFUNC ) - VALUES ( ${payment.orderId}, TRUNC(SYSDATE), '${payment.card}', '${payment.auth}', '00', SYSDATE, SYSDATE, NULL /*'${payment.transcationId}'*/, + VALUES ( ${payment.orderId}, TRUNC(SYSDATE), '${payment.card}', '${payment.auth}', '00', SYSDATE, SYSDATE, NULL, '${payment.nsu}', ${payment.installments}, ${payment.amount}, '${payment.flagName}', '${payment.paymentType}', SYSDATE, ${payment.userId} ) `; await queryRunner.manager.query(sql); await queryRunner.commitTransaction(); - - } catch ( error ) { + } catch (error) { await queryRunner.rollbackTransaction(); - console.log(error); + throw error; } finally { await queryRunner.release(); - await dataSource.destroy(); } } - async createInvoice(data: any) { - - const dataSource = new DataSource(createOracleConfig(this.configService)); - await dataSource.initialize(); - const queryRunner = dataSource.createQueryRunner(); + async createInvoice(data: CreateInvoiceDto): Promise { + const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); try { - const sql = `BEGIN + const sql = `BEGIN ESK_FATURAMENTO.FATURAMENTO_VENDA_ASSISTIDA(${data.orderId}, ${data.userId}); END;`; - await queryRunner.manager.query(sql); + await queryRunner.manager.query(sql); await queryRunner.commitTransaction(); - - } catch ( error ) { + } catch (error) { await queryRunner.rollbackTransaction(); - console.log(error); + throw error; } finally { await queryRunner.release(); - await dataSource.destroy(); } } - - } diff --git a/src/orders/application/dist/orders.service.js b/src/orders/application/dist/orders.service.js deleted file mode 100644 index 3251db9..0000000 --- a/src/orders/application/dist/orders.service.js +++ /dev/null @@ -1,208 +0,0 @@ -"use strict"; -var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); - else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; -}; -var __param = (this && this.__param) || function (paramIndex, decorator) { - return function (target, key) { decorator(target, key, paramIndex); } -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -exports.__esModule = true; -exports.OrdersService = void 0; -var common_1 = require("@nestjs/common"); -var redis_client_adapter_provider_1 = require("src/core/configs/cache/redis-client.adapter.provider"); -var cache_util_1 = require("src/shared/cache.util"); -var crypto_1 = require("crypto"); -var OrdersService = /** @class */ (function () { - function OrdersService(ordersRepository, redisClient) { - this.ordersRepository = ordersRepository; - this.redisClient = redisClient; - this.TTL_ORDERS = 60 * 10; // 10 minutos - this.TTL_INVOICE = 60 * 60; // 1 hora - this.TTL_ITENS = 60 * 10; // 10 minutos - } - /** - * Buscar pedidos com cache baseado nos filtros - */ - OrdersService.prototype.findOrders = function (query) { - return __awaiter(this, void 0, void 0, function () { - var key; - var _this = this; - return __generator(this, function (_a) { - key = "orders:query:" + this.hashObject(query); - return [2 /*return*/, cache_util_1.getOrSetCache(this.redisClient, key, this.TTL_ORDERS, function () { return _this.ordersRepository.findOrders(query); })]; - }); - }); - }; - /** - * Buscar nota fiscal por chave NFe com cache - */ - OrdersService.prototype.findInvoice = function (chavenfe) { - return __awaiter(this, void 0, Promise, function () { - var key; - var _this = this; - return __generator(this, function (_a) { - key = "orders:invoice:" + chavenfe; - return [2 /*return*/, cache_util_1.getOrSetCache(this.redisClient, key, this.TTL_INVOICE, function () { return __awaiter(_this, void 0, void 0, function () { - var invoiceData, invoice; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.ordersRepository.findInvoice(chavenfe)]; - case 1: - invoiceData = _a.sent(); - invoice = { - storeId: invoiceData.storeId, - invoiceDate: new Date(invoiceData.invoiceDate), - orderId: invoiceData.orderId, - invoiceId: invoiceData.invoiceId, - transactionId: invoiceData.transactionId, - customerId: invoiceData.customerId, - customer: invoiceData.customer, - sellerId: invoiceData.sellerId, - sellerName: invoiceData.sellerName, - itensQt: invoiceData.itensQt, - itens: invoiceData.itens - }; - return [2 /*return*/, invoice]; - } - }); - }); })]; - }); - }); - }; - /** - * Buscar itens de pedido com cache - */ - OrdersService.prototype.getItens = function (orderId) { - return __awaiter(this, void 0, Promise, function () { - var key; - var _this = this; - return __generator(this, function (_a) { - key = "orders:itens:" + orderId; - return [2 /*return*/, cache_util_1.getOrSetCache(this.redisClient, key, this.TTL_ITENS, function () { return __awaiter(_this, void 0, void 0, function () { - var itens; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.ordersRepository.getItens(orderId)]; - case 1: - itens = _a.sent(); - return [2 /*return*/, itens.map(function (item) { return ({ - productId: Number(item.productId), - description: item.description, - pacth: item.pacth, - color: item.color, - stockId: Number(item.stockId), - quantity: Number(item.quantity), - salePrice: Number(item.salePrice), - deliveryType: item.deliveryType, - total: Number(item.total), - weight: Number(item.weight), - department: item.department, - brand: item.brand - }); })]; - } - }); - }); })]; - }); - }); - }; - OrdersService.prototype.getCutItens = function (orderId) { - return __awaiter(this, void 0, Promise, function () { - var itens; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.ordersRepository.getCutItens(orderId)]; - case 1: - itens = _a.sent(); - return [2 /*return*/, itens.map(function (item) { return ({ - productId: Number(item.productId), - description: item.description, - pacth: item.pacth, - stockId: Number(item.stockId), - saleQuantity: Number(item.saleQuantity), - cutQuantity: Number(item.cutQuantity), - separedQuantity: Number(item.separedQuantity) - }); })]; - } - }); - }); - }; - OrdersService.prototype.getOrderDelivery = function (orderId) { - return __awaiter(this, void 0, Promise, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.ordersRepository.getOrderDelivery(orderId)]; - }); - }); - }; - OrdersService.prototype.getTransfer = function (orderId) { - return __awaiter(this, void 0, Promise, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.ordersRepository.getTransfer(orderId)]; - }); - }); - }; - OrdersService.prototype.getStatusOrder = function (orderId) { - return __awaiter(this, void 0, Promise, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.ordersRepository.getStatusOrder(orderId)]; - }); - }); - }; - /** - * Utilitário para gerar hash MD5 de objetos - */ - OrdersService.prototype.hashObject = function (obj) { - var str = JSON.stringify(obj, Object.keys(obj).sort()); - return crypto_1.createHash('md5').update(str).digest('hex'); - }; - OrdersService.prototype.createInvoiceCheck = function (invoice) { - return __awaiter(this, void 0, Promise, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.ordersRepository.createInvoiceCheck(invoice)]; - }); - }); - }; - OrdersService = __decorate([ - common_1.Injectable(), - __param(1, common_1.Inject(redis_client_adapter_provider_1.RedisClientToken)) - ], OrdersService); - return OrdersService; -}()); -exports.OrdersService = OrdersService; diff --git a/src/orders/modules/dist/orders.module.js b/src/orders/modules/dist/orders.module.js new file mode 100644 index 0000000..87a597b --- /dev/null +++ b/src/orders/modules/dist/orders.module.js @@ -0,0 +1,32 @@ +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +exports.__esModule = true; +exports.OrdersModule = void 0; +var common_1 = require("@nestjs/common"); +var orders_controller_1 = require("../controllers/orders.controller"); +var orders_service_1 = require("../application/orders.service"); +var orders_repository_1 = require("../repositories/orders.repository"); +var database_module_1 = require("../../core/database/database.module"); +var config_1 = require("@nestjs/config"); +var OrdersModule = /** @class */ (function () { + function OrdersModule() { + } + OrdersModule = __decorate([ + common_1.Module({ + imports: [ + config_1.ConfigModule, + database_module_1.DatabaseModule, + ], + controllers: [orders_controller_1.OrdersController], + providers: [orders_service_1.OrdersService, orders_repository_1.OrdersRepository], + exports: [orders_service_1.OrdersService] + }) + ], OrdersModule); + return OrdersModule; +}()); +exports.OrdersModule = OrdersModule; diff --git a/src/orders/modules/orders.module.ts b/src/orders/modules/orders.module.ts index 79edaed..fa54cc6 100644 --- a/src/orders/modules/orders.module.ts +++ b/src/orders/modules/orders.module.ts @@ -1,12 +1,17 @@ import { Module } from '@nestjs/common'; import { OrdersController } from '../controllers/orders.controller'; import { OrdersService } from '../application/orders.service'; -import { OrdersRepository } from '../repositories/orders.repository'; - +import { OrdersRepository } from '../repositories/orders.repository'; +import { DatabaseModule } from '../../core/database/database.module'; +import { ConfigModule } from '@nestjs/config'; @Module({ - imports: [], + imports: [ + ConfigModule, + DatabaseModule, + ], controllers: [OrdersController], providers: [OrdersService, OrdersRepository], + exports: [OrdersService], }) export class OrdersModule {} diff --git a/src/products/dto/ProductValidationDto.ts b/src/products/dto/ProductValidationDto.ts new file mode 100644 index 0000000..254158c --- /dev/null +++ b/src/products/dto/ProductValidationDto.ts @@ -0,0 +1,12 @@ +export class ProductValidationDto { + descricao: string; + codigoProduto: number; + codigoAuxiliar: string; + marca: string; + images: string[]; + tipoProduto: 'AUTOSSERVICO' | 'SHOWROOM' | 'ELETROMOVEIS' | 'OUTROS'; + precoVenda: number; + qtdeEstoqueLoja: number; + qtdeEstoqueCD: number; + } + \ No newline at end of file diff --git a/src/products/dto/exposed-product.dto.ts b/src/products/dto/exposed-product.dto.ts new file mode 100644 index 0000000..9b840ea --- /dev/null +++ b/src/products/dto/exposed-product.dto.ts @@ -0,0 +1,15 @@ +// src/products/dto/exposed-product.dto.ts +import { IsString, IsNumber, IsOptional } from 'class-validator'; + +export class ExposedProductDto { + @IsString() + readonly productId: string; + + @IsOptional() + @IsString() + readonly location?: string; + + @IsOptional() + @IsNumber() + readonly exposureTime?: number; +} diff --git a/src/products/dto/product-ecommerce.dto.ts b/src/products/dto/product-ecommerce.dto.ts new file mode 100644 index 0000000..324bb21 --- /dev/null +++ b/src/products/dto/product-ecommerce.dto.ts @@ -0,0 +1,8 @@ + +export class ProductEcommerceDto { + productIdErp: number; + productId: number; + price: number; + priceKit: number; + } + \ No newline at end of file diff --git a/src/products/products.controller.ts b/src/products/products.controller.ts index f241c10..c06b552 100644 --- a/src/products/products.controller.ts +++ b/src/products/products.controller.ts @@ -1,31 +1,59 @@ /* eslint-disable prettier/prettier */ /* eslint-disable @typescript-eslint/no-unused-vars */ -/* -https://docs.nestjs.com/controllers#controllers -*/ - -import { Body, Controller, Get, Param, Post } from '@nestjs/common'; +import { Body, Controller, Get, Param, Post,UseGuards } from '@nestjs/common'; import { ProductsService } from './products.service'; -import { ExposedProduct } from '../core/models/exposed-product.model'; +import { ExposedProduct } from 'src/core/models/exposed-product.model'; +import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard'; +import { ExposedProductDto } from './dto/exposed-product.dto'; +import { ProductValidationDto } from './dto/ProductValidationDto'; +import { ProductEcommerceDto } from './dto/product-ecommerce.dto'; +import { ApiTags, ApiOperation, ApiParam, ApiBody, ApiResponse, ApiBearerAuth } from '@nestjs/swagger'; + +@ApiBearerAuth() +@UseGuards(JwtAuthGuard) +@ApiTags('Produtos') @Controller('api/v1/products') export class ProductsController { + constructor(private readonly productsService: ProductsService) {} - constructor(private readonly productsService: ProductsService) { } + ///enpoit produtos-ecommecer + @Get('products-ecommerce') + @ApiOperation({ summary: 'Lista produtos para o e-commerce' }) + @ApiResponse({ + status: 200, + description: 'Lista de produtos retornada com sucesso.', + type: ProductEcommerceDto, + isArray: true + }) - @Get('products-ecommerce') - async productsEcommerce() { - return this.productsService.getProductsEcommerce(); - } + ///ENDPOIT DE VALIDAR PRODUTO POR FILTRO + @Get('product-validation/:storeId/:filtro') + @ApiOperation({ summary: 'Valida produto pelo filtro (código, EAN ou descrição)' }) + @ApiParam({ name: 'storeId', type: String, description: 'ID da loja' }) + @ApiParam({ name: 'filtro', type: String, description: 'Filtro de busca (código, EAN ou descrição)' }) + @ApiResponse({ + status: 200, + description: 'Produto encontrado com sucesso.', + type: ProductValidationDto + }) + @ApiResponse({ status: 404, description: 'Produto não localizado.' }) + async productValidation( + @Param('storeId') storeId: string, + @Param('filtro') filtro: string, + ): Promise { + return this.productsService.productsValidation(storeId, filtro); + } - @Get('product-validation/:storeId/:filtro') - async productValidation(@Param('storeId') storeId: string, @Param('filtro') filtro: string) { - return this.productsService.productsValidation(storeId, filtro); - } - @Post('exposed-product') - async exposedProduct(@Body() exposedProduct: ExposedProduct) { - return this.productsService.exposedProduct(exposedProduct); - } + + /// ENDPOIT PRODUTOS EXPOSTOS + @Post('exposed-product') + @ApiOperation({ summary: 'Registra produto em exposição' }) + @ApiBody({ type: ExposedProductDto }) + @ApiResponse({ status: 201, description: 'Produto exposto registrado com sucesso.' }) + async exposedProduct(@Body() exposedProduct: ExposedProduct) { + return this.productsService.exposedProduct(exposedProduct); + } } diff --git a/src/products/products.module.ts b/src/products/products.module.ts index 7f6cae0..5d1151e 100644 --- a/src/products/products.module.ts +++ b/src/products/products.module.ts @@ -16,4 +16,4 @@ import { ProductsController } from './products.controller'; providers: [ ProductsService,], }) -export class ProductsModule { } +export class ProductsModule { } \ No newline at end of file diff --git a/src/products/products.service.ts b/src/products/products.service.ts index af95ef0..9593e73 100644 --- a/src/products/products.service.ts +++ b/src/products/products.service.ts @@ -1,123 +1,105 @@ -/* eslint-disable prettier/prettier */ -/* eslint-disable @typescript-eslint/no-unused-vars */ - -/* -https://docs.nestjs.com/providers#services -*/ - import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; -import { createOracleConfig } from '../core/configs/typeorm.oracle.config'; -import { ExposedProduct } from '../core/models/exposed-product.model'; +import { InjectDataSource } from '@nestjs/typeorm'; +import { ExposedProduct } from 'src/core/models/exposed-product.model'; import { DataSource } from 'typeorm'; -import { ConfigService } from '@nestjs/config'; +import { ProductValidationDto } from './dto/ProductValidationDto'; +import { ProductEcommerceDto } from './dto/product-ecommerce.dto'; +import { ResultModel } from 'src/shared/ResultModel'; @Injectable() export class ProductsService { - constructor(private readonly configService: ConfigService) {} - async productsValidation(storeId: string, filtro: string): Promise { - const dataSource = new DataSource(createOracleConfig(this.configService)); - await dataSource.initialize(); - const queryRunner = dataSource.createQueryRunner(); - await queryRunner.connect(); - try { - const sql = `SELECT PCPRODUT.DESCRICAO as "descricao" - ,PCPRODUT.CODPROD as "codigoProduto" - ,PCPRODUT.CODAUXILIAR as "codigoAuxiliar" - ,PCMARCA.MARCA as "marca" - ,REPLACE(NVL(URLIMAGEM, 'http://10.1.1.191/si.png'), 'http://167.249.211.178:8001/', 'http://10.1.1.191/') as "images" - ,CASE WHEN PCPRODUT.TIPOPRODUTO = 'A' THEN 'AUTOSSERVICO' - WHEN PCPRODUT.TIPOPRODUTO = 'S' THEN 'SHOWROOM' - WHEN PCPRODUT.TIPOPRODUTO = 'E' THEN 'ELETROMOVEIS' + constructor( + @InjectDataSource("oracle") private readonly dataSource: DataSource + ) {} + + async productsValidation(storeId: string, filtro: string): Promise { + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.connect(); + + try { + const sql = `SELECT PCPRODUT.DESCRICAO as "descricao" + ,PCPRODUT.CODPROD as "codigoProduto" + ,PCPRODUT.CODAUXILIAR as "codigoAuxiliar" + ,PCMARCA.MARCA as "marca" + ,REPLACE(NVL(URLIMAGEM, 'http://10.1.1.191/si.png'), 'http://167.249.211.178:8001/', 'http://10.1.1.191/') as "images" + ,CASE WHEN PCPRODUT.TIPOPRODUTO = 'A' THEN 'AUTOSSERVICO' + WHEN PCPRODUT.TIPOPRODUTO = 'S' THEN 'SHOWROOM' + WHEN PCPRODUT.TIPOPRODUTO = 'E' THEN 'ELETROMOVEIS' ELSE 'OUTROS' END as "tipoProduto" - ,PCTABPR.PVENDA1 as "precoVenda" - ,( PCEST.QTESTGER - PCEST.QTRESERV - PCEST.QTBLOQUEADA ) as "qtdeEstoqueLoja" - ,( SELECT ( ESTOQUE_CD.QTESTGER - ESTOQUE_CD.QTRESERV - ESTOQUE_CD.QTBLOQUEADA ) - FROM PCEST ESTOQUE_CD - WHERE ESTOQUE_CD.CODPROD = PCPRODUT.CODPROD - AND ESTOQUE_CD.CODFILIAL = 6 ) as "qtdeEstoqueCD" - FROM PCPRODUT, PCEST, PCTABPR, PCMARCA - WHERE PCPRODUT.CODPROD = PCEST.CODPROD - AND PCPRODUT.CODPROD = PCTABPR.CODPROD - AND PCPRODUT.CODMARCA = PCMARCA.CODMARCA - AND PCTABPR.NUMREGIAO = 1 - AND PCEST.CODFILIAL = '${storeId}' - AND ( PCPRODUT.CODAUXILIAR = REGEXP_REPLACE('${filtro}', '[^0-9]', '') OR - PCPRODUT.CODPROD = REGEXP_REPLACE('${filtro}', '[^0-9]', '') OR - PCPRODUT.DESCRICAO LIKE '%'||'${filtro}'||'%' )`; + ,PCTABPR.PVENDA1 as "precoVenda" + ,( PCEST.QTESTGER - PCEST.QTRESERV - PCEST.QTBLOQUEADA ) as "qtdeEstoqueLoja" + ,( SELECT ( ESTOQUE_CD.QTESTGER - ESTOQUE_CD.QTRESERV - ESTOQUE_CD.QTBLOQUEADA ) + FROM PCEST ESTOQUE_CD + WHERE ESTOQUE_CD.CODPROD = PCPRODUT.CODPROD + AND ESTOQUE_CD.CODFILIAL = 6 ) as "qtdeEstoqueCD" + FROM PCPRODUT, PCEST, PCTABPR, PCMARCA + WHERE PCPRODUT.CODPROD = PCEST.CODPROD + AND PCPRODUT.CODPROD = PCTABPR.CODPROD + AND PCPRODUT.CODMARCA = PCMARCA.CODMARCA + AND PCTABPR.NUMREGIAO = 1 + AND PCEST.CODFILIAL = '${storeId}' + AND ( PCPRODUT.CODAUXILIAR = REGEXP_REPLACE('${filtro}', '[^0-9]', '') OR + PCPRODUT.CODPROD = REGEXP_REPLACE('${filtro}', '[^0-9]', '') OR + PCPRODUT.DESCRICAO LIKE '%'||'${filtro}'||'%' )`; + const products = await queryRunner.manager.query(sql); - const products = await queryRunner.manager.query(sql); + if (products.length === 0) { + throw new HttpException('Produto não localizado!', HttpStatus.NOT_FOUND); + } - if (products.length == 0) { - throw new HttpException('Produto não localizado!', HttpStatus.NOT_FOUND); - } + const product = products[0]; - const product = products[0]; + if (!product.images) { + product.images = []; + } else { + product.images = product.images.includes(';') + ? product.images.split(';') + : [product.images]; + } - if ( product.images == null ) { - product.images = []; - } else { - const imagesString: string = product.images; - if (imagesString.indexOf(';') > 0) { - const imagesArray = imagesString.split(';'); - product.images = imagesArray; - } else { - const imagesArray: string[] = []; - imagesArray.push(product.images); - product.images = imagesArray; - } - } - - - return product; - } finally { - await queryRunner.release(); - await dataSource.destroy(); - } + return product; + } finally { + await queryRunner.release(); } + } - async exposedProduct(product: ExposedProduct) { - const dataSource = new DataSource(createOracleConfig(this.configService)); - await dataSource.initialize(); - const queryRunner = dataSource.createQueryRunner(); - await queryRunner.connect(); - await queryRunner.startTransaction(); - try { - const sqlInsert = `INSERT INTO ESTPRODUTOEXPOSICAO ( CODFILIAL, DATA, CODAUXILIAR, CODFUNC ) - VALUES ( '${product.storeId}', TRUNC(SYSDATE), ${product.ean}, ${product.userId})`; - await queryRunner.query(sqlInsert); - await queryRunner.commitTransaction(); - return { message: 'Registro incluído com sucesso!'} - } catch (err) { - await queryRunner.rollbackTransaction(); - throw err; - } finally { - await queryRunner.release(); - await dataSource.destroy(); - } + async exposedProduct(product: ExposedProduct) { + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + + try { + const sqlInsert = `INSERT INTO ESTPRODUTOEXPOSICAO ( CODFILIAL, DATA, CODAUXILIAR, CODFUNC ) + VALUES ( '${product.storeId}', TRUNC(SYSDATE), ${product.ean}, ${product.userId})`; + await queryRunner.query(sqlInsert); + await queryRunner.commitTransaction(); + return { message: 'Registro incluído com sucesso!' }; + } catch (err) { + await queryRunner.rollbackTransaction(); + throw err; + } finally { + await queryRunner.release(); } + } - async getProductsEcommerce() { - const dataSource = new DataSource(createOracleConfig(this.configService)); - await dataSource.initialize(); - const queryRunner = dataSource.createQueryRunner(); - await queryRunner.connect(); - try { - const sqlInsert = `SELECT P.CODPROD as "productIdErp" - ,P.VTEXSKUID as "productId" - ,ROUND(P.PVENDA,2) as "price" - ,ROUND(P.PRECOKIT,2) as "priceKit" - FROM ESVPRODUTOSECOMMERCE P - WHERE P.VTEXSKUID > 0 - AND P.CODPROD IN (52057, 33702, 46410, 24518, 25816)`; - const products = await queryRunner.query(sqlInsert); - return products; - } catch (err) { - throw err; - } finally { - await queryRunner.release(); - await dataSource.destroy(); - } + async getProductsEcommerce(): Promise { + const queryRunner = this.dataSource.createQueryRunner(); + await queryRunner.connect(); + + try { + const sql = `SELECT P.CODPROD as "productIdErp" + ,P.VTEXSKUID as "productId" + ,ROUND(P.PVENDA,2) as "price" + ,ROUND(P.PRECOKIT,2) as "priceKit" + FROM ESVPRODUTOSECOMMERCE P + WHERE P.VTEXSKUID > 0 + AND P.CODPROD IN (52057, 33702, 46410, 24518, 25816)`; + + const products = await queryRunner.query(sql); + return products; + } finally { + await queryRunner.release(); } - + } }