first
This commit is contained in:
21
src/data-consult/clientes.controller.ts
Normal file
21
src/data-consult/clientes.controller.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
|
||||
import { ApiTags, ApiOperation, ApiParam, ApiBearerAuth, ApiResponse } from '@nestjs/swagger';
|
||||
import { Controller, Get, Param } from '@nestjs/common';
|
||||
import { clientesService } from './clientes.service';
|
||||
|
||||
@ApiTags('clientes')
|
||||
@Controller('api/v1/')
|
||||
export class clientesController {
|
||||
|
||||
constructor(private readonly clientesService: clientesService) {}
|
||||
|
||||
|
||||
@Get('clientes/:filter')
|
||||
async customer(@Param('filter') filter: string) {
|
||||
return this.clientesService.customers(filter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
19
src/data-consult/clientes.module.ts
Normal file
19
src/data-consult/clientes.module.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
/* eslint-disable prettier/prettier */
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { clientesService } from './clientes.service';
|
||||
import { clientesController } from './clientes.controller';
|
||||
|
||||
/*
|
||||
https://docs.nestjs.com/modules
|
||||
*/
|
||||
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
controllers: [
|
||||
clientesController,],
|
||||
providers: [
|
||||
clientesService,],
|
||||
})
|
||||
export class clientes { }
|
||||
154
src/data-consult/clientes.service.ts
Normal file
154
src/data-consult/clientes.service.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
import { Injectable, Inject } from '@nestjs/common';
|
||||
import { QueryRunner, DataSource } from 'typeorm';
|
||||
import { DATA_SOURCE } from '../core/constants';
|
||||
import { RedisClientToken } from '../core/configs/cache/redis-client.adapter.provider';
|
||||
import { IRedisClient } from '../core/configs/cache/IRedisClient';
|
||||
import { getOrSetCache } from '../shared/cache.util';
|
||||
|
||||
@Injectable()
|
||||
export class clientesService {
|
||||
private readonly CUSTOMERS_TTL = 60 * 60 * 12; // 12 horas
|
||||
private readonly CUSTOMERS_CACHE_KEY = 'clientes:search';
|
||||
|
||||
constructor(
|
||||
@Inject(DATA_SOURCE)
|
||||
private readonly dataSource: DataSource,
|
||||
@Inject(RedisClientToken)
|
||||
private readonly redisClient: IRedisClient,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Buscar clientes com cache otimizado
|
||||
* @param filter - Filtro de busca (código, CPF/CNPJ ou nome)
|
||||
* @returns Array de clientes encontrados
|
||||
*/
|
||||
async customers(filter: string) {
|
||||
const cacheKey = `${this.CUSTOMERS_CACHE_KEY}:${filter}`;
|
||||
|
||||
return getOrSetCache(
|
||||
this.redisClient,
|
||||
cacheKey,
|
||||
this.CUSTOMERS_TTL,
|
||||
async () => {
|
||||
const queryRunner: QueryRunner = this.dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
|
||||
try {
|
||||
// Primeira tentativa: busca por código do cliente
|
||||
let sql = `SELECT PCCLIENT.CODCLI as "id"
|
||||
,PCCLIENT.CODCLI || ' - '|| PCCLIENT.CLIENTE||
|
||||
' ( '||REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '')||' )' as "name"
|
||||
,PCCLIENT.ESTCOB as "estcob"
|
||||
FROM PCCLIENT
|
||||
WHERE PCCLIENT.CODCLI = REGEXP_REPLACE('${filter}', '[^0-9]', '')
|
||||
ORDER BY PCCLIENT.CLIENTE`;
|
||||
let customers = await queryRunner.manager.query(sql);
|
||||
|
||||
// Segunda tentativa: busca por CPF/CNPJ se não encontrou por código
|
||||
if (customers.length === 0) {
|
||||
sql = `SELECT PCCLIENT.CODCLI as "id",
|
||||
PCCLIENT.CODCLI || ' - '|| PCCLIENT.CLIENTE||
|
||||
' ( '||REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '')||' )' as "name"
|
||||
,PCCLIENT.ESTCOB as "estcob"
|
||||
FROM PCCLIENT
|
||||
WHERE REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '') = REGEXP_REPLACE('${filter}', '[^0-9]', '')
|
||||
ORDER BY PCCLIENT.CLIENTE`;
|
||||
customers = await queryRunner.manager.query(sql);
|
||||
}
|
||||
|
||||
// Terceira tentativa: busca por nome do cliente se não encontrou por código ou CPF/CNPJ
|
||||
if (customers.length === 0) {
|
||||
sql = `SELECT PCCLIENT.CODCLI as "id",
|
||||
PCCLIENT.CODCLI || ' - '|| PCCLIENT.CLIENTE||
|
||||
' ( '||REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '')||' )' as "name"
|
||||
,PCCLIENT.ESTCOB as "estcob"
|
||||
FROM PCCLIENT
|
||||
WHERE PCCLIENT.CLIENTE LIKE '${filter.toUpperCase().replace('@', '%')}%'
|
||||
ORDER BY PCCLIENT.CLIENTE`;
|
||||
customers = await queryRunner.manager.query(sql);
|
||||
}
|
||||
|
||||
return customers;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Buscar todos os clientes com cache
|
||||
* @returns Array de todos os clientes
|
||||
*/
|
||||
async getAllCustomers() {
|
||||
const cacheKey = 'clientes:all';
|
||||
|
||||
return getOrSetCache(
|
||||
this.redisClient,
|
||||
cacheKey,
|
||||
this.CUSTOMERS_TTL,
|
||||
async () => {
|
||||
const queryRunner: QueryRunner = this.dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
|
||||
try {
|
||||
const sql = `SELECT PCCLIENT.CODCLI as "id"
|
||||
,PCCLIENT.CODCLI || ' - '|| PCCLIENT.CLIENTE||
|
||||
' ( '||REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '')||' )' as "name"
|
||||
,PCCLIENT.ESTCOB as "estcob"
|
||||
FROM PCCLIENT
|
||||
ORDER BY PCCLIENT.CLIENTE`;
|
||||
|
||||
return await queryRunner.manager.query(sql);
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Buscar cliente por ID específico com cache
|
||||
* @param customerId - ID do cliente
|
||||
* @returns Cliente encontrado ou null
|
||||
*/
|
||||
async getCustomerById(customerId: string) {
|
||||
const cacheKey = `clientes:id:${customerId}`;
|
||||
|
||||
return getOrSetCache(
|
||||
this.redisClient,
|
||||
cacheKey,
|
||||
this.CUSTOMERS_TTL,
|
||||
async () => {
|
||||
const queryRunner: QueryRunner = this.dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
|
||||
try {
|
||||
const sql = `SELECT PCCLIENT.CODCLI as "id"
|
||||
,PCCLIENT.CODCLI || ' - '|| PCCLIENT.CLIENTE||
|
||||
' ( '||REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '')||' )' as "name"
|
||||
,PCCLIENT.ESTCOB as "estcob"
|
||||
FROM PCCLIENT
|
||||
WHERE PCCLIENT.CODCLI = '${customerId}'`;
|
||||
|
||||
const customers = await queryRunner.manager.query(sql);
|
||||
return customers.length > 0 ? customers[0] : null;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Limpar cache de clientes (útil para invalidação)
|
||||
* @param pattern - Padrão de chaves para limpar (opcional)
|
||||
*/
|
||||
async clearCustomersCache(pattern?: string) {
|
||||
const cachePattern = pattern || 'clientes:*';
|
||||
|
||||
// Nota: Esta funcionalidade requer implementação específica do Redis
|
||||
// Por enquanto, mantemos a interface para futuras implementações
|
||||
console.log(`Cache de clientes seria limpo para o padrão: ${cachePattern}`);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Controller, Get, Param, UseGuards } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiParam, ApiBearerAuth, ApiResponse } from '@nestjs/swagger';
|
||||
import { Controller, Get, Param, Query, UseGuards, UsePipes, ValidationPipe, ParseIntPipe } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiParam, ApiBearerAuth, ApiResponse, ApiQuery } from '@nestjs/swagger';
|
||||
import { DataConsultService } from './data-consult.service';
|
||||
import { JwtAuthGuard } from 'src/auth/guards/jwt-auth.guard'
|
||||
import { ProductDto } from './dto/product.dto';
|
||||
@@ -7,6 +7,7 @@ import { StoreDto } from './dto/store.dto';
|
||||
import { SellerDto } from './dto/seller.dto';
|
||||
import { BillingDto } from './dto/billing.dto';
|
||||
import { CustomerDto } from './dto/customer.dto';
|
||||
import { CarrierDto, FindCarriersDto } from './dto/carrier.dto';
|
||||
|
||||
@ApiTags('DataConsult')
|
||||
@Controller('api/v1/data-consult')
|
||||
@@ -24,7 +25,7 @@ export class DataConsultController {
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiBearerAuth()
|
||||
@Get('sellers')
|
||||
@ApiOperation({ summary: 'Lista todos os vendedores' })
|
||||
@ApiResponse({ status: 200, description: 'Lista de vendedores retornada com sucesso', type: [SellerDto] })
|
||||
@@ -70,5 +71,36 @@ export class DataConsultController {
|
||||
async getAllProducts(): Promise<ProductDto[]> {
|
||||
return this.dataConsultService.getAllProducts();
|
||||
}
|
||||
|
||||
|
||||
@Get('carriers/all')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Lista todas as transportadoras cadastradas' })
|
||||
@ApiResponse({ status: 200, description: 'Lista de transportadoras retornada com sucesso', type: [CarrierDto] })
|
||||
@UsePipes(new ValidationPipe({ transform: true }))
|
||||
async getAllCarriers(): Promise<CarrierDto[]> {
|
||||
return this.dataConsultService.getAllCarriers();
|
||||
}
|
||||
|
||||
@Get('carriers')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Busca transportadoras por período de data' })
|
||||
@ApiResponse({ status: 200, description: 'Lista de transportadoras por período retornada com sucesso', type: [CarrierDto] })
|
||||
@UsePipes(new ValidationPipe({ transform: true }))
|
||||
async getCarriersByDate(@Query() query: FindCarriersDto): Promise<CarrierDto[]> {
|
||||
return this.dataConsultService.getCarriersByDate(query);
|
||||
}
|
||||
|
||||
@Get('carriers/order/:orderId')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Busca transportadoras de um pedido específico' })
|
||||
@ApiParam({ name: 'orderId', example: 236001388 })
|
||||
@ApiResponse({ status: 200, description: 'Lista de transportadoras do pedido retornada com sucesso', type: [CarrierDto] })
|
||||
@UsePipes(new ValidationPipe({ transform: true }))
|
||||
async getOrderCarriers(@Param('orderId', ParseIntPipe) orderId: number): Promise<CarrierDto[]> {
|
||||
return this.dataConsultService.getOrderCarriers(orderId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,9 +5,10 @@ import { DataConsultRepository } from './data-consult.repository';
|
||||
import { LoggerModule } from 'src/Log/logger.module';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { RedisModule } from 'src/core/configs/cache/redis.module';
|
||||
import { clientes } from './clientes.module';
|
||||
|
||||
@Module({
|
||||
imports: [LoggerModule, ConfigModule, RedisModule],
|
||||
imports: [LoggerModule, ConfigModule, RedisModule, clientes],
|
||||
controllers: [DataConsultController],
|
||||
providers: [
|
||||
DataConsultService,
|
||||
|
||||
@@ -40,7 +40,7 @@ export class DataConsultRepository {
|
||||
return results.map(result => new StoreDto(result));
|
||||
}
|
||||
|
||||
async findSellers(): Promise<SellerDto[]> {
|
||||
async findSellers(): Promise<SellerDto[]> {
|
||||
const sql = `
|
||||
SELECT PCUSUARI.CODUSUR as "id",
|
||||
PCUSUARI.NOME as "name"
|
||||
@@ -55,51 +55,166 @@ export class DataConsultRepository {
|
||||
|
||||
async findBillings(): Promise<BillingDto[]> {
|
||||
const sql = `
|
||||
SELECT PCPEDC.NUMPED as "id",
|
||||
PCPEDC.DATA as "date",
|
||||
PCPEDC.VLTOTAL as "total"
|
||||
FROM PCPEDC
|
||||
WHERE PCPEDC.POSICAO = 'F'
|
||||
SELECT p.CODCOB, p.COBRANCA FROM PCCOB p
|
||||
`;
|
||||
const results = await this.executeQuery<BillingDto[]>(sql);
|
||||
return results.map(result => new BillingDto(result));
|
||||
}
|
||||
|
||||
async findCustomers(filter: string): Promise<CustomerDto[]> {
|
||||
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
|
||||
// 1) limpa todos os não-dígitos para buscas exatas
|
||||
const cleanedDigits = filter.replace(/\D/g, '');
|
||||
|
||||
// 2) prepara filtro para busca por nome (LIKE)
|
||||
const likeFilter = `%${filter.toUpperCase().replace(/@/g, '%')}%`;
|
||||
|
||||
let customers: CustomerDto[] = [];
|
||||
|
||||
// --- 1ª tentativa: busca por código do cliente (CODCLI) ---
|
||||
let sql = `
|
||||
SELECT
|
||||
PCCLIENT.CODCLI AS "id",
|
||||
PCCLIENT.CLIENTE AS "name",
|
||||
REGEXP_REPLACE(PCCLIENT.CGCENT,'[^0-9]','') AS "document",
|
||||
PCCLIENT.ESTCOB AS "estcob"
|
||||
FROM PCCLIENT
|
||||
WHERE PCCLIENT.CODCLI = :0
|
||||
ORDER BY PCCLIENT.CLIENTE
|
||||
`;
|
||||
const results = await this.executeQuery<CustomerDto[]>(sql, [`%${filter}%`]);
|
||||
return results.map(result => new CustomerDto(result));
|
||||
customers = await this.executeQuery<CustomerDto[]>(sql, [cleanedDigits]);
|
||||
|
||||
// --- 2ª tentativa: busca por CPF/CNPJ (CGCENT) ---
|
||||
if (customers.length === 0) {
|
||||
sql = `
|
||||
SELECT
|
||||
PCCLIENT.CODCLI AS "id",
|
||||
PCCLIENT.CLIENTE AS "name",
|
||||
REGEXP_REPLACE(PCCLIENT.CGCENT,'[^0-9]','') AS "document",
|
||||
PCCLIENT.ESTCOB AS "estcob"
|
||||
FROM PCCLIENT
|
||||
WHERE REGEXP_REPLACE(PCCLIENT.CGCENT,'[^0-9]','') = :0
|
||||
ORDER BY PCCLIENT.CLIENTE
|
||||
`;
|
||||
customers = await this.executeQuery<CustomerDto[]>(sql, [cleanedDigits]);
|
||||
}
|
||||
|
||||
// --- 3ª tentativa: busca parcial por nome ---
|
||||
if (customers.length === 0) {
|
||||
sql = `
|
||||
SELECT
|
||||
PCCLIENT.CODCLI AS "id",
|
||||
PCCLIENT.CLIENTE AS "name",
|
||||
REGEXP_REPLACE(PCCLIENT.CGCENT,'[^0-9]','') AS "document",
|
||||
PCCLIENT.ESTCOB AS "estcob"
|
||||
FROM PCCLIENT
|
||||
WHERE UPPER(PCCLIENT.CLIENTE) LIKE :0
|
||||
ORDER BY PCCLIENT.CLIENTE
|
||||
`;
|
||||
customers = await this.executeQuery<CustomerDto[]>(sql, [likeFilter]);
|
||||
}
|
||||
|
||||
return customers.map(row => new CustomerDto(row));
|
||||
}
|
||||
|
||||
async findProducts(filter: string): Promise<ProductDto[]> {
|
||||
const sql = `
|
||||
SELECT PCPRODUT.CODPROD as "id",
|
||||
PCPRODUT.DESCRICAO as "name",
|
||||
PCPRODUT.CODFAB as "manufacturerCode"
|
||||
PCPRODUT.CODPROD || ' - ' || PCPRODUT.DESCRICAO || ' ( ' || PCPRODUT.CODFAB || ' )' as "description"
|
||||
FROM PCPRODUT
|
||||
WHERE PCPRODUT.DESCRICAO LIKE :filter
|
||||
OR PCPRODUT.CODFAB LIKE :filter
|
||||
WHERE PCPRODUT.CODPROD = :filter
|
||||
`;
|
||||
const results = await this.executeQuery<ProductDto[]>(sql, [`%${filter}%`]);
|
||||
const results = await this.executeQuery<ProductDto[]>(sql, [filter]);
|
||||
return results.map(result => new ProductDto(result));
|
||||
}
|
||||
|
||||
async findAllProducts(): Promise<ProductDto[]> {
|
||||
const sql = `
|
||||
SELECT PCPRODUT.CODPROD as "id",
|
||||
PCPRODUT.DESCRICAO as "name",
|
||||
PCPRODUT.CODFAB as "manufacturerCode"
|
||||
PCPRODUT.CODPROD || ' - ' || PCPRODUT.DESCRICAO || ' ( ' || PCPRODUT.CODFAB || ' )' as "description"
|
||||
FROM PCPRODUT
|
||||
WHERE ROWNUM <= 500
|
||||
`;
|
||||
const results = await this.executeQuery<ProductDto[]>(sql);
|
||||
return results.map(result => new ProductDto(result));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca todas as transportadoras cadastradas no sistema
|
||||
*/
|
||||
async findAllCarriers(): Promise<any[]> {
|
||||
const sql = `
|
||||
SELECT DISTINCT
|
||||
PCFORNEC.CODFORNEC as "carrierId",
|
||||
PCFORNEC.FORNECEDOR as "carrierName",
|
||||
PCFORNEC.CODFORNEC || ' - ' || PCFORNEC.FORNECEDOR as "carrierDescription"
|
||||
FROM PCFORNEC
|
||||
WHERE PCFORNEC.CODFORNEC IS NOT NULL
|
||||
AND PCFORNEC.CODFORNEC > 0
|
||||
AND PCFORNEC.FORNECEDOR IS NOT NULL
|
||||
ORDER BY PCFORNEC.FORNECEDOR
|
||||
`;
|
||||
return await this.executeQuery<any[]>(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca as transportadoras por período de data
|
||||
*/
|
||||
async findCarriersByDate(query: any): Promise<any[]> {
|
||||
let sql = `
|
||||
SELECT DISTINCT
|
||||
PCPEDC.CODFORNECFRETE as "carrierId",
|
||||
PCFORNEC.FORNECEDOR as "carrierName",
|
||||
PCPEDC.CODFORNECFRETE || ' - ' || PCFORNEC.FORNECEDOR as "carrierDescription",
|
||||
COUNT(PCPEDC.NUMPED) as "ordersCount"
|
||||
FROM PCPEDC
|
||||
LEFT JOIN PCFORNEC ON PCPEDC.CODFORNECFRETE = PCFORNEC.CODFORNEC
|
||||
WHERE PCPEDC.CODFORNECFRETE IS NOT NULL
|
||||
AND PCPEDC.CODFORNECFRETE > 0
|
||||
`;
|
||||
|
||||
const conditions: string[] = [];
|
||||
const parameters: any[] = [];
|
||||
let paramIndex = 0;
|
||||
|
||||
if (query.dateIni) {
|
||||
conditions.push(`AND PCPEDC.DATA >= TO_DATE(:${paramIndex}, 'YYYY-MM-DD')`);
|
||||
parameters.push(query.dateIni);
|
||||
paramIndex++;
|
||||
}
|
||||
if (query.dateEnd) {
|
||||
conditions.push(`AND PCPEDC.DATA <= TO_DATE(:${paramIndex}, 'YYYY-MM-DD')`);
|
||||
parameters.push(query.dateEnd);
|
||||
paramIndex++;
|
||||
}
|
||||
if (query.codfilial) {
|
||||
conditions.push(`AND PCPEDC.CODFILIAL = :${paramIndex}`);
|
||||
parameters.push(query.codfilial);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
sql += "\n" + conditions.join("\n");
|
||||
sql += "\nGROUP BY PCPEDC.CODFORNECFRETE, PCFORNEC.FORNECEDOR";
|
||||
sql += "\nORDER BY PCPEDC.CODFORNECFRETE";
|
||||
|
||||
return await this.executeQuery<any[]>(sql, parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca as transportadoras de um pedido específico
|
||||
*/
|
||||
async findOrderCarriers(orderId: number): Promise<any[]> {
|
||||
const sql = `
|
||||
SELECT DISTINCT
|
||||
PCPEDC.CODFORNECFRETE as "carrierId",
|
||||
PCFORNEC.FORNECEDOR as "carrierName",
|
||||
PCPEDC.CODFORNECFRETE || ' - ' || PCFORNEC.FORNECEDOR as "carrierDescription"
|
||||
FROM PCPEDC
|
||||
LEFT JOIN PCFORNEC ON PCPEDC.CODFORNECFRETE = PCFORNEC.CODFORNEC
|
||||
WHERE PCPEDC.NUMPED = :0
|
||||
AND PCPEDC.CODFORNECFRETE IS NOT NULL
|
||||
AND PCPEDC.CODFORNECFRETE > 0
|
||||
ORDER BY PCPEDC.CODFORNECFRETE
|
||||
`;
|
||||
return await this.executeQuery<any[]>(sql, [orderId]);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { SellerDto } from './dto/seller.dto';
|
||||
import { BillingDto } from './dto/billing.dto';
|
||||
import { CustomerDto } from './dto/customer.dto';
|
||||
import { ProductDto } from './dto/product.dto';
|
||||
import { CarrierDto, FindCarriersDto } from './dto/carrier.dto';
|
||||
import { ILogger } from '../Log/ILogger';
|
||||
import { RedisClientToken } from '../core/configs/cache/redis-client.adapter.provider';
|
||||
import { IRedisClient } from '../core/configs/cache/IRedisClient';
|
||||
@@ -15,11 +16,14 @@ import { DATA_SOURCE } from '../core/constants';
|
||||
@Injectable()
|
||||
export class DataConsultService {
|
||||
private readonly SELLERS_CACHE_KEY = 'data-consult:sellers';
|
||||
private readonly SELLERS_TTL = 3600;
|
||||
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;
|
||||
private readonly ALL_PRODUCTS_TTL = 600;
|
||||
private readonly CUSTOMERS_TTL = 3600;
|
||||
private readonly CARRIERS_CACHE_KEY = 'data-consult:carriers:all';
|
||||
private readonly CARRIERS_TTL = 3600;
|
||||
|
||||
constructor(
|
||||
private readonly repository: DataConsultRepository,
|
||||
@@ -63,7 +67,7 @@ export class DataConsultService {
|
||||
this.logger.error('Erro ao buscar vendedores', error);
|
||||
throw new HttpException('Erro ao buscar vendedores', HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns Array de BillingDto
|
||||
@@ -134,4 +138,71 @@ export class DataConsultService {
|
||||
throw new HttpException('Erro ao buscar produtos', HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obter todas as transportadoras cadastradas
|
||||
* @returns Array de CarrierDto
|
||||
*/
|
||||
async getAllCarriers(): Promise<CarrierDto[]> {
|
||||
this.logger.log('Buscando todas as transportadoras');
|
||||
try {
|
||||
return getOrSetCache<CarrierDto[]>(
|
||||
this.redisClient,
|
||||
this.CARRIERS_CACHE_KEY,
|
||||
this.CARRIERS_TTL,
|
||||
async () => {
|
||||
const carriers = await this.repository.findAllCarriers();
|
||||
return carriers.map(carrier => ({
|
||||
carrierId: carrier.carrierId?.toString() || '',
|
||||
carrierName: carrier.carrierName || '',
|
||||
carrierDescription: carrier.carrierDescription || '',
|
||||
}));
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
this.logger.error('Erro ao buscar transportadoras', error);
|
||||
throw new HttpException('Erro ao buscar transportadoras', HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obter transportadoras por período de data
|
||||
* @param query - Filtros de data e filial
|
||||
* @returns Array de CarrierDto
|
||||
*/
|
||||
async getCarriersByDate(query: FindCarriersDto): Promise<CarrierDto[]> {
|
||||
this.logger.log(`Buscando transportadoras por período: ${JSON.stringify(query)}`);
|
||||
try {
|
||||
const carriers = await this.repository.findCarriersByDate(query);
|
||||
return carriers.map(carrier => ({
|
||||
carrierId: carrier.carrierId?.toString() || '',
|
||||
carrierName: carrier.carrierName || '',
|
||||
carrierDescription: carrier.carrierDescription || '',
|
||||
ordersCount: carrier.ordersCount ? Number(carrier.ordersCount) : 0,
|
||||
}));
|
||||
} catch (error) {
|
||||
this.logger.error('Erro ao buscar transportadoras por período', error);
|
||||
throw new HttpException('Erro ao buscar transportadoras', HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obter transportadoras de um pedido específico
|
||||
* @param orderId - ID do pedido
|
||||
* @returns Array de CarrierDto
|
||||
*/
|
||||
async getOrderCarriers(orderId: number): Promise<CarrierDto[]> {
|
||||
this.logger.log(`Buscando transportadoras do pedido: ${orderId}`);
|
||||
try {
|
||||
const carriers = await this.repository.findOrderCarriers(orderId);
|
||||
return carriers.map(carrier => ({
|
||||
carrierId: carrier.carrierId?.toString() || '',
|
||||
carrierName: carrier.carrierName || '',
|
||||
carrierDescription: carrier.carrierDescription || '',
|
||||
}));
|
||||
} catch (error) {
|
||||
this.logger.error('Erro ao buscar transportadoras do pedido', error);
|
||||
throw new HttpException('Erro ao buscar transportadoras do pedido', HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
58
src/data-consult/dto/carrier.dto.ts
Normal file
58
src/data-consult/dto/carrier.dto.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsOptional, IsString, IsDateString } from 'class-validator';
|
||||
|
||||
export class CarrierDto {
|
||||
@ApiProperty({
|
||||
description: 'ID da transportadora',
|
||||
example: '123'
|
||||
})
|
||||
carrierId: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Nome da transportadora',
|
||||
example: 'TRANSPORTADORA ABC LTDA'
|
||||
})
|
||||
carrierName: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Descrição completa da transportadora (ID - Nome)',
|
||||
example: '123 - TRANSPORTADORA ABC LTDA'
|
||||
})
|
||||
carrierDescription: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Quantidade de pedidos da transportadora no período',
|
||||
example: 15,
|
||||
required: false
|
||||
})
|
||||
ordersCount?: number;
|
||||
}
|
||||
|
||||
export class FindCarriersDto {
|
||||
@ApiProperty({
|
||||
description: 'Data inicial para filtro (formato YYYY-MM-DD)',
|
||||
example: '2024-01-01',
|
||||
required: false
|
||||
})
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
dateIni?: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Data final para filtro (formato YYYY-MM-DD)',
|
||||
example: '2024-12-31',
|
||||
required: false
|
||||
})
|
||||
@IsOptional()
|
||||
@IsDateString()
|
||||
dateEnd?: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'ID da filial',
|
||||
example: '1',
|
||||
required: false
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
codfilial?: string;
|
||||
}
|
||||
Reference in New Issue
Block a user