refactor: atualizações e remoção de módulos não utilizados

This commit is contained in:
joelson brito
2025-11-10 09:39:44 -03:00
parent ed68b7e865
commit b8630adf92
121 changed files with 3507 additions and 3531 deletions

View File

@@ -1,50 +1,47 @@
import { Test, TestingModule } from '@nestjs/testing';
import { DataConsultService } from '../data-consult.service';
import { DataConsultRepository } from '../data-consult.repository';
import { ILogger } from '../../Log/ILogger';
import { IRedisClient } from '../../core/configs/cache/IRedisClient';
import { RedisClientToken } from '../../core/configs/cache/redis-client.adapter.provider';
import { DataSource } from 'typeorm';
import { DATA_SOURCE } from '../../core/constants';
export const createMockRepository = (methods: Partial<DataConsultRepository> = {}) => ({
findStores: jest.fn(),
findSellers: jest.fn(),
findBillings: jest.fn(),
findCustomers: jest.fn(),
findAllProducts: jest.fn(),
findAllCarriers: jest.fn(),
findRegions: jest.fn(),
...methods,
} as any);
export const createMockRepository = (
methods: Partial<DataConsultRepository> = {},
) =>
({
findStores: jest.fn(),
findSellers: jest.fn(),
findBillings: jest.fn(),
findCustomers: jest.fn(),
findAllProducts: jest.fn(),
findAllCarriers: jest.fn(),
findRegions: jest.fn(),
...methods,
} as any);
export const createMockLogger = () => ({
log: jest.fn(),
error: jest.fn(),
warn: jest.fn(),
debug: jest.fn(),
} as any);
export const createMockRedisClient = () => ({
get: jest.fn().mockResolvedValue(null),
set: jest.fn().mockResolvedValue(undefined),
} as any);
export const createMockRedisClient = () =>
({
get: jest.fn().mockResolvedValue(null),
set: jest.fn().mockResolvedValue(undefined),
} as any);
export interface DataConsultServiceTestContext {
service: DataConsultService;
mockRepository: jest.Mocked<DataConsultRepository>;
mockLogger: jest.Mocked<ILogger>;
mockRedisClient: jest.Mocked<IRedisClient>;
mockDataSource: jest.Mocked<DataSource>;
}
export async function createDataConsultServiceTestModule(
repositoryMethods: Partial<DataConsultRepository> = {},
redisClientMethods: Partial<IRedisClient> = {}
redisClientMethods: Partial<IRedisClient> = {},
): Promise<DataConsultServiceTestContext> {
const mockRepository = createMockRepository(repositoryMethods);
const mockLogger = createMockLogger();
const mockRedisClient = { ...createMockRedisClient(), ...redisClientMethods } as any;
const mockRedisClient = {
...createMockRedisClient(),
...redisClientMethods,
} as any;
const mockDataSource = {} as any;
const module: TestingModule = await Test.createTestingModule({
@@ -58,10 +55,6 @@ export async function createDataConsultServiceTestModule(
provide: RedisClientToken,
useValue: mockRedisClient,
},
{
provide: 'LoggerService',
useValue: mockLogger,
},
{
provide: DATA_SOURCE,
useValue: mockDataSource,
@@ -74,9 +67,7 @@ export async function createDataConsultServiceTestModule(
return {
service,
mockRepository,
mockLogger,
mockRedisClient,
mockDataSource,
};
}

View File

@@ -23,7 +23,7 @@ describe('DataConsultService', () => {
const result = await context.service.stores();
result.forEach(store => {
result.forEach((store) => {
expect(store.id).toBeDefined();
expect(store.name).toBeDefined();
expect(store.store).toBeDefined();
@@ -36,7 +36,10 @@ describe('DataConsultService', () => {
});
it('should validate that repository result is an array', async () => {
context.mockRepository.findStores.mockResolvedValue({ id: '001', name: 'Loja 1' } as any);
context.mockRepository.findStores.mockResolvedValue({
id: '001',
name: 'Loja 1',
} as any);
const result = await context.service.stores();
expect(Array.isArray(result)).toBe(true);
});
@@ -49,7 +52,7 @@ describe('DataConsultService', () => {
] as any);
const result = await context.service.stores();
result.forEach(store => {
result.forEach((store) => {
expect(store.id).not.toBe('');
expect(store.name).not.toBe('');
expect(store.store).not.toBe('');
@@ -60,7 +63,10 @@ describe('DataConsultService', () => {
const repositoryError = new Error('Database connection failed');
context.mockRepository.findStores.mockRejectedValue(repositoryError);
await expect(context.service.stores()).rejects.toThrow(HttpException);
expect(context.mockLogger.error).toHaveBeenCalledWith('Erro ao buscar lojas', repositoryError);
expect(context.mockLogger.error).toHaveBeenCalledWith(
'Erro ao buscar lojas',
repositoryError,
);
});
});
});
@@ -85,7 +91,7 @@ describe('DataConsultService', () => {
] as any);
const result = await context.service.sellers();
result.forEach(seller => {
result.forEach((seller) => {
expect(seller.id).toBeDefined();
expect(seller.name).toBeDefined();
});
@@ -97,7 +103,10 @@ describe('DataConsultService', () => {
});
it('should validate that repository result is an array', async () => {
context.mockRepository.findSellers.mockResolvedValue({ id: '001', name: 'Vendedor 1' } as any);
context.mockRepository.findSellers.mockResolvedValue({
id: '001',
name: 'Vendedor 1',
} as any);
const result = await context.service.sellers();
expect(Array.isArray(result)).toBe(true);
});
@@ -109,7 +118,7 @@ describe('DataConsultService', () => {
] as any);
const result = await context.service.sellers();
result.forEach(seller => {
result.forEach((seller) => {
expect(seller.id).not.toBe('');
expect(seller.name).not.toBe('');
});
@@ -119,7 +128,10 @@ describe('DataConsultService', () => {
const repositoryError = new Error('Database connection failed');
context.mockRepository.findSellers.mockRejectedValue(repositoryError);
await expect(context.service.sellers()).rejects.toThrow(HttpException);
expect(context.mockLogger.error).toHaveBeenCalledWith('Erro ao buscar vendedores', repositoryError);
expect(context.mockLogger.error).toHaveBeenCalledWith(
'Erro ao buscar vendedores',
repositoryError,
);
});
});
});
@@ -144,7 +156,7 @@ describe('DataConsultService', () => {
] as any);
const result = await context.service.billings();
result.forEach(billing => {
result.forEach((billing) => {
expect(billing.id).toBeDefined();
expect(billing.date).toBeDefined();
expect(billing.total).toBeDefined();
@@ -157,7 +169,11 @@ describe('DataConsultService', () => {
});
it('should validate that repository result is an array', async () => {
context.mockRepository.findBillings.mockResolvedValue({ id: '001', date: new Date(), total: 1000 } as any);
context.mockRepository.findBillings.mockResolvedValue({
id: '001',
date: new Date(),
total: 1000,
} as any);
const result = await context.service.billings();
expect(Array.isArray(result)).toBe(true);
});
@@ -170,7 +186,7 @@ describe('DataConsultService', () => {
] as any);
const result = await context.service.billings();
result.forEach(billing => {
result.forEach((billing) => {
expect(billing.id).not.toBe('');
expect(billing.date).toBeDefined();
expect(billing.total).toBeDefined();
@@ -181,7 +197,10 @@ describe('DataConsultService', () => {
const repositoryError = new Error('Database connection failed');
context.mockRepository.findBillings.mockRejectedValue(repositoryError);
await expect(context.service.billings()).rejects.toThrow(HttpException);
expect(context.mockLogger.error).toHaveBeenCalledWith('Erro ao buscar faturamento', repositoryError);
expect(context.mockLogger.error).toHaveBeenCalledWith(
'Erro ao buscar faturamento',
repositoryError,
);
});
});
});
@@ -206,7 +225,7 @@ describe('DataConsultService', () => {
] as any);
const result = await context.service.customers('test');
result.forEach(customer => {
result.forEach((customer) => {
expect(customer.id).toBeDefined();
expect(customer.name).toBeDefined();
expect(customer.document).toBeDefined();
@@ -219,7 +238,11 @@ describe('DataConsultService', () => {
});
it('should validate that repository result is an array', async () => {
context.mockRepository.findCustomers.mockResolvedValue({ id: '001', name: 'Cliente 1', document: '12345678900' } as any);
context.mockRepository.findCustomers.mockResolvedValue({
id: '001',
name: 'Cliente 1',
document: '12345678900',
} as any);
const result = await context.service.customers('test');
expect(Array.isArray(result)).toBe(true);
});
@@ -232,7 +255,7 @@ describe('DataConsultService', () => {
] as any);
const result = await context.service.customers('test');
result.forEach(customer => {
result.forEach((customer) => {
expect(customer.id).not.toBe('');
expect(customer.name).not.toBe('');
expect(customer.document).not.toBe('');
@@ -242,8 +265,13 @@ describe('DataConsultService', () => {
it('should log error when repository throws exception', async () => {
const repositoryError = new Error('Database connection failed');
context.mockRepository.findCustomers.mockRejectedValue(repositoryError);
await expect(context.service.customers('test')).rejects.toThrow(HttpException);
expect(context.mockLogger.error).toHaveBeenCalledWith('Erro ao buscar clientes', repositoryError);
await expect(context.service.customers('test')).rejects.toThrow(
HttpException,
);
expect(context.mockLogger.error).toHaveBeenCalledWith(
'Erro ao buscar clientes',
repositoryError,
);
});
});
});
@@ -268,7 +296,7 @@ describe('DataConsultService', () => {
] as any);
const result = await context.service.getAllProducts();
result.forEach(product => {
result.forEach((product) => {
expect(product.id).toBeDefined();
expect(product.name).toBeDefined();
expect(product.manufacturerCode).toBeDefined();
@@ -281,7 +309,11 @@ describe('DataConsultService', () => {
});
it('should validate that repository result is an array', async () => {
context.mockRepository.findAllProducts.mockResolvedValue({ id: '001', name: 'Produto 1', manufacturerCode: 'FAB001' } as any);
context.mockRepository.findAllProducts.mockResolvedValue({
id: '001',
name: 'Produto 1',
manufacturerCode: 'FAB001',
} as any);
const result = await context.service.getAllProducts();
expect(Array.isArray(result)).toBe(true);
});
@@ -294,7 +326,7 @@ describe('DataConsultService', () => {
] as any);
const result = await context.service.getAllProducts();
result.forEach(product => {
result.forEach((product) => {
expect(product.id).not.toBe('');
expect(product.name).not.toBe('');
expect(product.manufacturerCode).not.toBe('');
@@ -303,9 +335,16 @@ describe('DataConsultService', () => {
it('should log error when repository throws exception', async () => {
const repositoryError = new Error('Database connection failed');
context.mockRepository.findAllProducts.mockRejectedValue(repositoryError);
await expect(context.service.getAllProducts()).rejects.toThrow(HttpException);
expect(context.mockLogger.error).toHaveBeenCalledWith('Erro ao buscar todos os produtos', repositoryError);
context.mockRepository.findAllProducts.mockRejectedValue(
repositoryError,
);
await expect(context.service.getAllProducts()).rejects.toThrow(
HttpException,
);
expect(context.mockLogger.error).toHaveBeenCalledWith(
'Erro ao buscar todos os produtos',
repositoryError,
);
});
});
});
@@ -325,12 +364,19 @@ describe('DataConsultService', () => {
it('should validate that all carriers have required properties (carrierId, carrierName, carrierDescription)', async () => {
context.mockRepository.findAllCarriers.mockResolvedValue([
{ carrierId: '001', carrierName: 'Transportadora 1' },
{ carrierName: 'Transportadora 2', carrierDescription: '002 - Transportadora 2' },
{ carrierId: '003', carrierName: 'Transportadora 3', carrierDescription: '003 - Transportadora 3' },
{
carrierName: 'Transportadora 2',
carrierDescription: '002 - Transportadora 2',
},
{
carrierId: '003',
carrierName: 'Transportadora 3',
carrierDescription: '003 - Transportadora 3',
},
] as any);
const result = await context.service.getAllCarriers();
result.forEach(carrier => {
result.forEach((carrier) => {
expect(carrier.carrierId).toBeDefined();
expect(carrier.carrierName).toBeDefined();
expect(carrier.carrierDescription).toBeDefined();
@@ -343,20 +389,36 @@ describe('DataConsultService', () => {
});
it('should validate that repository result is an array', async () => {
context.mockRepository.findAllCarriers.mockResolvedValue({ carrierId: '001', carrierName: 'Transportadora 1', carrierDescription: '001 - Transportadora 1' } as any);
context.mockRepository.findAllCarriers.mockResolvedValue({
carrierId: '001',
carrierName: 'Transportadora 1',
carrierDescription: '001 - Transportadora 1',
} as any);
const result = await context.service.getAllCarriers();
expect(Array.isArray(result)).toBe(true);
});
it('should validate that required properties are not empty strings', async () => {
context.mockRepository.findAllCarriers.mockResolvedValue([
{ carrierId: '', carrierName: 'Transportadora 1', carrierDescription: '001 - Transportadora 1' },
{ carrierId: '002', carrierName: '', carrierDescription: '002 - Transportadora 2' },
{ carrierId: '003', carrierName: 'Transportadora 3', carrierDescription: '' },
{
carrierId: '',
carrierName: 'Transportadora 1',
carrierDescription: '001 - Transportadora 1',
},
{
carrierId: '002',
carrierName: '',
carrierDescription: '002 - Transportadora 2',
},
{
carrierId: '003',
carrierName: 'Transportadora 3',
carrierDescription: '',
},
] as any);
const result = await context.service.getAllCarriers();
result.forEach(carrier => {
result.forEach((carrier) => {
expect(carrier.carrierId).not.toBe('');
expect(carrier.carrierName).not.toBe('');
expect(carrier.carrierDescription).not.toBe('');
@@ -365,9 +427,16 @@ describe('DataConsultService', () => {
it('should log error when repository throws exception', async () => {
const repositoryError = new Error('Database connection failed');
context.mockRepository.findAllCarriers.mockRejectedValue(repositoryError);
await expect(context.service.getAllCarriers()).rejects.toThrow(HttpException);
expect(context.mockLogger.error).toHaveBeenCalledWith('Erro ao buscar transportadoras', repositoryError);
context.mockRepository.findAllCarriers.mockRejectedValue(
repositoryError,
);
await expect(context.service.getAllCarriers()).rejects.toThrow(
HttpException,
);
expect(context.mockLogger.error).toHaveBeenCalledWith(
'Erro ao buscar transportadoras',
repositoryError,
);
});
});
});
@@ -392,7 +461,7 @@ describe('DataConsultService', () => {
] as any);
const result = await context.service.getRegions();
result.forEach(region => {
result.forEach((region) => {
expect(region.numregiao).toBeDefined();
expect(region.regiao).toBeDefined();
});
@@ -404,7 +473,10 @@ describe('DataConsultService', () => {
});
it('should validate that repository result is an array', async () => {
context.mockRepository.findRegions.mockResolvedValue({ numregiao: 1, regiao: 'Região Sul' } as any);
context.mockRepository.findRegions.mockResolvedValue({
numregiao: 1,
regiao: 'Região Sul',
} as any);
const result = await context.service.getRegions();
expect(Array.isArray(result)).toBe(true);
});
@@ -417,7 +489,7 @@ describe('DataConsultService', () => {
] as any);
const result = await context.service.getRegions();
result.forEach(region => {
result.forEach((region) => {
expect(region.numregiao).toBeDefined();
expect(region.numregiao).not.toBeNull();
expect(region.regiao).toBeDefined();
@@ -428,8 +500,13 @@ describe('DataConsultService', () => {
it('should log error when repository throws exception', async () => {
const repositoryError = new Error('Database connection failed');
context.mockRepository.findRegions.mockRejectedValue(repositoryError);
await expect(context.service.getRegions()).rejects.toThrow(HttpException);
expect(context.mockLogger.error).toHaveBeenCalledWith('Erro ao buscar regiões', repositoryError);
await expect(context.service.getRegions()).rejects.toThrow(
HttpException,
);
expect(context.mockLogger.error).toHaveBeenCalledWith(
'Erro ao buscar regiões',
repositoryError,
);
});
});
});

View File

@@ -1,21 +1,16 @@
import { ApiTags, ApiOperation, ApiParam, ApiBearerAuth, ApiResponse } from '@nestjs/swagger';
import {
ApiTags,
} 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);
}
export class clientesController {
constructor(private readonly clientesService: clientesService) {}
@Get('clientes/:filter')
async customer(@Param('filter') filter: string) {
return this.clientesService.customers(filter);
}
}

View File

@@ -1,5 +1,5 @@
/* eslint-disable prettier/prettier */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { clientesService } from './clientes.service';
import { clientesController } from './clientes.controller';

View File

@@ -63,7 +63,9 @@ export class clientesService {
' ( '||REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '')||' )' as "name"
,PCCLIENT.ESTCOB as "estcob"
FROM PCCLIENT
WHERE PCCLIENT.CLIENTE LIKE '${filter.toUpperCase().replace('@', '%')}%'
WHERE PCCLIENT.CLIENTE LIKE '${filter
.toUpperCase()
.replace('@', '%')}%'
ORDER BY PCCLIENT.CLIENTE`;
customers = await queryRunner.manager.query(sql);
}
@@ -72,7 +74,7 @@ export class clientesService {
} finally {
await queryRunner.release();
}
}
},
);
}
@@ -103,7 +105,7 @@ export class clientesService {
} finally {
await queryRunner.release();
}
}
},
);
}
@@ -136,19 +138,13 @@ export class clientesService {
} 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}`);
}
}

View File

@@ -1,110 +1,170 @@
import { Controller, Get, Param, Query, UseGuards, UsePipes, ValidationPipe, ParseIntPipe } 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';
import { RegionDto } from './dto/region.dto';
import { CarrierDto, FindCarriersDto } from './dto/carrier.dto';
@ApiTags('DataConsult')
@Controller('api/v1/data-consult')
export class DataConsultController {
constructor(private readonly dataConsultService: DataConsultService) {}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('stores')
@ApiOperation({ summary: 'Lista todas as lojas' })
@ApiResponse({ status: 200, description: 'Lista de lojas retornada com sucesso', type: [StoreDto] })
async stores(): Promise<StoreDto[]> {
return this.dataConsultService.stores();
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('sellers')
@ApiOperation({ summary: 'Lista todos os vendedores' })
@ApiResponse({ status: 200, description: 'Lista de vendedores retornada com sucesso', type: [SellerDto] })
async sellers(): Promise<SellerDto[]> {
return this.dataConsultService.sellers();
}
@Get('billings')
@ApiOperation({ summary: 'Retorna informações de faturamento' })
@ApiResponse({ status: 200, description: 'Informações de faturamento retornadas com sucesso', type: [BillingDto] })
async billings(): Promise<BillingDto[]> {
return this.dataConsultService.billings();
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('customers/:filter')
@ApiOperation({ summary: 'Filtra clientes pelo parâmetro fornecido' })
@ApiParam({ name: 'filter', description: 'Filtro de busca para clientes' })
@ApiResponse({ status: 200, description: 'Lista de clientes filtrados retornada com sucesso', type: [CustomerDto] })
async customer(@Param('filter') filter: string): Promise<CustomerDto[]> {
return this.dataConsultService.customers(filter);
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('products/:filter')
@ApiOperation({ summary: 'Busca produtos filtrados' })
@ApiParam({ name: 'filter', description: 'Filtro de busca' })
@ApiResponse({ status: 200, description: 'Lista de produtos filtrados retornada com sucesso', type: [ProductDto] })
async products(@Param('filter') filter: string): Promise<ProductDto[]> {
return this.dataConsultService.products(filter);
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('all')
@ApiOperation({ summary: 'Lista 500 produtos' })
@ApiResponse({ status: 200, description: 'Lista de 500 produtos retornada com sucesso', type: [ProductDto] })
async getAllProducts(): Promise<ProductDto[]> {
return this.dataConsultService.getAllProducts();
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('carriers/all')
@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();
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('carriers')
@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);
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('carriers/order/:orderId')
@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);
}
@Get('regions')
@ApiOperation({ summary: 'Lista todas as regiões cadastradas' })
@ApiResponse({ status: 200, description: 'Lista de regiões retornada com sucesso', type: [RegionDto] })
async getRegions(): Promise<RegionDto[]> {
return this.dataConsultService.getRegions();
}
}
import {
Controller,
Get,
Param,
Query,
UseGuards,
UsePipes,
ValidationPipe,
ParseIntPipe,
} 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';
import { RegionDto } from './dto/region.dto';
import { CarrierDto, FindCarriersDto } from './dto/carrier.dto';
@ApiTags('DataConsult')
@Controller('api/v1/data-consult')
export class DataConsultController {
constructor(private readonly dataConsultService: DataConsultService) {}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('stores')
@ApiOperation({ summary: 'Lista todas as lojas' })
@ApiResponse({
status: 200,
description: 'Lista de lojas retornada com sucesso',
type: [StoreDto],
})
async stores(): Promise<StoreDto[]> {
return this.dataConsultService.stores();
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('sellers')
@ApiOperation({ summary: 'Lista todos os vendedores' })
@ApiResponse({
status: 200,
description: 'Lista de vendedores retornada com sucesso',
type: [SellerDto],
})
async sellers(): Promise<SellerDto[]> {
return this.dataConsultService.sellers();
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('billings')
@ApiOperation({ summary: 'Retorna informações de faturamento' })
@ApiResponse({
status: 200,
description: 'Informações de faturamento retornadas com sucesso',
type: [BillingDto],
})
async billings(): Promise<BillingDto[]> {
return this.dataConsultService.billings();
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('customers/:filter')
@ApiOperation({ summary: 'Filtra clientes pelo parâmetro fornecido' })
@ApiParam({ name: 'filter', description: 'Filtro de busca para clientes' })
@ApiResponse({
status: 200,
description: 'Lista de clientes filtrados retornada com sucesso',
type: [CustomerDto],
})
async customer(@Param('filter') filter: string): Promise<CustomerDto[]> {
return this.dataConsultService.customers(filter);
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('products/:filter')
@ApiOperation({ summary: 'Busca produtos filtrados' })
@ApiParam({ name: 'filter', description: 'Filtro de busca' })
@ApiResponse({
status: 200,
description: 'Lista de produtos filtrados retornada com sucesso',
type: [ProductDto],
})
async products(@Param('filter') filter: string): Promise<ProductDto[]> {
return this.dataConsultService.products(filter);
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('all')
@ApiOperation({ summary: 'Lista 500 produtos' })
@ApiResponse({
status: 200,
description: 'Lista de 500 produtos retornada com sucesso',
type: [ProductDto],
})
async getAllProducts(): Promise<ProductDto[]> {
return this.dataConsultService.getAllProducts();
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('carriers/all')
@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();
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('carriers')
@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);
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@Get('carriers/order/:orderId')
@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);
}
@Get('regions')
@ApiOperation({ summary: 'Lista todas as regiões cadastradas' })
@ApiResponse({
status: 200,
description: 'Lista de regiões retornada com sucesso',
type: [RegionDto],
})
async getRegions(): Promise<RegionDto[]> {
return this.dataConsultService.getRegions();
}
}

View File

@@ -1,19 +1,14 @@
import { Module } from '@nestjs/common';
import { DataConsultService } from './data-consult.service';
import { DataConsultController } from './data-consult.controller';
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, clientes],
controllers: [DataConsultController],
providers: [
DataConsultService,
DataConsultRepository,
],
})
export class DataConsultModule {}
import { Module } from '@nestjs/common';
import { DataConsultService } from './data-consult.service';
import { DataConsultController } from './data-consult.controller';
import { DataConsultRepository } from './data-consult.repository';
import { ConfigModule } from '@nestjs/config';
import { RedisModule } from 'src/core/configs/cache/redis.module';
import { clientes } from './clientes.module';
@Module({
imports: [ConfigModule, RedisModule, clientes],
controllers: [DataConsultController],
providers: [DataConsultService, DataConsultRepository],
})
export class DataConsultModule {}

View File

@@ -1,331 +1,435 @@
import { Injectable, HttpException, HttpStatus, Inject } from '@nestjs/common';
import { DataConsultRepository } from './data-consult.repository';
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 { ProductDto } from './dto/product.dto';
import { RegionDto } from './dto/region.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';
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;
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 CUSTOMERS_TTL = 3600;
private readonly CARRIERS_CACHE_KEY = 'data-consult:carriers:all';
private readonly CARRIERS_TTL = 3600;
private readonly REGIONS_CACHE_KEY = 'data-consult:regions';
private readonly REGIONS_TTL = 7200;
constructor(
private readonly repository: DataConsultRepository,
@Inject(RedisClientToken) private readonly redisClient: IRedisClient,
@Inject('LoggerService') private readonly logger: ILogger,
@Inject(DATA_SOURCE) private readonly dataSource: DataSource
) {}
async stores(): Promise<StoreDto[]> {
this.logger.log('Buscando todas as lojas');
try {
const stores = await this.repository.findStores();
if (stores === null || stores === undefined) {
throw new HttpException('Resultado inválido do repositório', HttpStatus.INTERNAL_SERVER_ERROR);
}
const storesArray = Array.isArray(stores) ? stores : [stores];
return storesArray
.filter(store => {
if (!store || typeof store !== 'object') {
return false;
}
const hasId = store.id !== undefined && store.id !== null && store.id !== '';
const hasName = store.name !== undefined && store.name !== null && store.name !== '';
const hasStore = store.store !== undefined && store.store !== null && store.store !== '';
return hasId && hasName && hasStore;
})
.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);
}
}
async sellers(): Promise<SellerDto[]> {
this.logger.log('Buscando vendedores com cache Redis...');
try {
return await getOrSetCache<SellerDto[]>(
this.redisClient,
this.SELLERS_CACHE_KEY,
this.SELLERS_TTL,
async () => {
try {
const sellers = await this.repository.findSellers();
if (sellers === null || sellers === undefined) {
throw new HttpException('Resultado inválido do repositório', HttpStatus.INTERNAL_SERVER_ERROR);
}
const sellersArray = Array.isArray(sellers) ? sellers : [sellers];
return sellersArray
.filter(seller => {
if (!seller || typeof seller !== 'object') {
return false;
}
const hasId = seller.id !== undefined && seller.id !== null && seller.id !== '';
const hasName = seller.name !== undefined && seller.name !== null && seller.name !== '';
return hasId && hasName;
})
.map(seller => new SellerDto(seller));
} catch (error) {
this.logger.error('Erro ao buscar vendedores', error);
throw error;
}
}
);
} catch (error) {
this.logger.error('Erro ao buscar vendedores', error);
throw new HttpException('Erro ao buscar vendedores', HttpStatus.INTERNAL_SERVER_ERROR);
}
}
async billings(): Promise<BillingDto[]> {
this.logger.log('Buscando informações de faturamento');
try {
const billings = await this.repository.findBillings();
if (billings === null || billings === undefined) {
throw new HttpException('Resultado inválido do repositório', HttpStatus.INTERNAL_SERVER_ERROR);
}
const billingsArray = Array.isArray(billings) ? billings : [billings];
return billingsArray
.filter(billing => {
if (!billing || typeof billing !== 'object') {
return false;
}
const hasId = billing.id !== undefined && billing.id !== null && billing.id !== '';
const hasDate = billing.date !== undefined && billing.date !== null;
const hasTotal = billing.total !== undefined && billing.total !== null;
return hasId && hasDate && hasTotal;
})
.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);
}
}
async customers(filter: string): Promise<CustomerDto[]> {
this.logger.log(`Buscando clientes com filtro: ${filter}`);
try {
if (!filter || typeof filter !== 'string') {
throw new HttpException('Filtro inválido', HttpStatus.BAD_REQUEST);
}
const customers = await this.repository.findCustomers(filter);
if (customers === null || customers === undefined) {
throw new HttpException('Resultado inválido do repositório', HttpStatus.INTERNAL_SERVER_ERROR);
}
const customersArray = Array.isArray(customers) ? customers : [customers];
return customersArray
.filter(customer => {
if (!customer || typeof customer !== 'object') {
return false;
}
const hasId = customer.id !== undefined && customer.id !== null && customer.id !== '';
const hasName = customer.name !== undefined && customer.name !== null && customer.name !== '';
const hasDocument = customer.document !== undefined && customer.document !== null && customer.document !== '';
return hasId && hasName && hasDocument;
})
.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);
}
}
async products(filter: string): Promise<ProductDto[]> {
this.logger.log(`Buscando produtos com filtro: ${filter}`);
try {
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', error);
throw new HttpException('Erro ao buscar produtos', HttpStatus.INTERNAL_SERVER_ERROR);
}
}
async getAllProducts(): Promise<ProductDto[]> {
this.logger.log('Buscando todos os produtos');
try {
return await getOrSetCache<ProductDto[]>(
this.redisClient,
this.ALL_PRODUCTS_CACHE_KEY,
this.ALL_PRODUCTS_TTL,
async () => {
try {
const products = await this.repository.findAllProducts();
if (products === null || products === undefined) {
throw new HttpException('Resultado inválido do repositório', HttpStatus.INTERNAL_SERVER_ERROR);
}
const productsArray = Array.isArray(products) ? products : [products];
return productsArray
.filter(product => {
if (!product || typeof product !== 'object') {
return false;
}
const hasId = product.id !== undefined && product.id !== null && product.id !== '';
const hasName = product.name !== undefined && product.name !== null && product.name !== '';
const hasManufacturerCode = product.manufacturerCode !== undefined && product.manufacturerCode !== null && product.manufacturerCode !== '';
return hasId && hasName && hasManufacturerCode;
})
.map(product => new ProductDto(product));
} catch (error) {
this.logger.error('Erro ao buscar todos os produtos', error);
throw error;
}
}
);
} catch (error) {
this.logger.error('Erro ao buscar todos os produtos', error);
throw new HttpException('Erro ao buscar produtos', HttpStatus.INTERNAL_SERVER_ERROR);
}
}
async getAllCarriers(): Promise<CarrierDto[]> {
this.logger.log('Buscando todas as transportadoras');
try {
return await getOrSetCache<CarrierDto[]>(
this.redisClient,
this.CARRIERS_CACHE_KEY,
this.CARRIERS_TTL,
async () => {
try {
const carriers = await this.repository.findAllCarriers();
if (carriers === null || carriers === undefined) {
throw new HttpException('Resultado inválido do repositório', HttpStatus.INTERNAL_SERVER_ERROR);
}
const carriersArray = Array.isArray(carriers) ? carriers : [carriers];
return carriersArray
.filter(carrier => {
if (!carrier || typeof carrier !== 'object') {
return false;
}
const hasCarrierId = carrier.carrierId !== undefined && carrier.carrierId !== null && carrier.carrierId !== '';
const hasCarrierName = carrier.carrierName !== undefined && carrier.carrierName !== null && carrier.carrierName !== '';
const hasCarrierDescription = carrier.carrierDescription !== undefined && carrier.carrierDescription !== null && carrier.carrierDescription !== '';
return hasCarrierId && hasCarrierName && hasCarrierDescription;
})
.map(carrier => ({
carrierId: carrier.carrierId?.toString() || '',
carrierName: carrier.carrierName || '',
carrierDescription: carrier.carrierDescription || '',
}));
} catch (error) {
this.logger.error('Erro ao buscar transportadoras', error);
throw error;
}
}
);
} catch (error) {
this.logger.error('Erro ao buscar transportadoras', error);
throw new HttpException('Erro ao buscar transportadoras', HttpStatus.INTERNAL_SERVER_ERROR);
}
}
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);
}
}
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);
}
}
async getRegions(): Promise<RegionDto[]> {
this.logger.log('Buscando todas as regiões');
try {
return await getOrSetCache<RegionDto[]>(
this.redisClient,
this.REGIONS_CACHE_KEY,
this.REGIONS_TTL,
async () => {
try {
const regions = await this.repository.findRegions();
if (regions === null || regions === undefined) {
throw new HttpException('Resultado inválido do repositório', HttpStatus.INTERNAL_SERVER_ERROR);
}
const regionsArray = Array.isArray(regions) ? regions : [regions];
return regionsArray
.filter(region => {
if (!region || typeof region !== 'object') {
return false;
}
const hasNumregiao = region.numregiao !== undefined && region.numregiao !== null;
const hasRegiao = region.regiao !== undefined && region.regiao !== null && region.regiao !== '';
return hasNumregiao && hasRegiao;
})
.map(region => new RegionDto(region));
} catch (error) {
this.logger.error('Erro ao buscar regiões', error);
throw error;
}
}
);
} catch (error) {
this.logger.error('Erro ao buscar regiões', error);
throw new HttpException('Erro ao buscar regiões', HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
import { Injectable, HttpException, HttpStatus, Inject, Logger } from '@nestjs/common';
import { DataConsultRepository } from './data-consult.repository';
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 { ProductDto } from './dto/product.dto';
import { RegionDto } from './dto/region.dto';
import { CarrierDto, FindCarriersDto } from './dto/carrier.dto';
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 logger = new Logger(DataConsultService.name);
private readonly SELLERS_CACHE_KEY = 'data-consult:sellers';
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 CUSTOMERS_TTL = 3600;
private readonly CARRIERS_CACHE_KEY = 'data-consult:carriers:all';
private readonly CARRIERS_TTL = 3600;
private readonly REGIONS_CACHE_KEY = 'data-consult:regions';
private readonly REGIONS_TTL = 7200;
constructor(
private readonly repository: DataConsultRepository,
@Inject(RedisClientToken) private readonly redisClient: IRedisClient,
@Inject(DATA_SOURCE) private readonly dataSource: DataSource,
) {}
async stores(): Promise<StoreDto[]> {
this.logger.log('Buscando todas as lojas');
try {
const stores = await this.repository.findStores();
if (stores === null || stores === undefined) {
throw new HttpException(
'Resultado inválido do repositório',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
const storesArray = Array.isArray(stores) ? stores : [stores];
return storesArray
.filter((store) => {
if (!store || typeof store !== 'object') {
return false;
}
const hasId =
store.id !== undefined && store.id !== null && store.id !== '';
const hasName =
store.name !== undefined &&
store.name !== null &&
store.name !== '';
const hasStore =
store.store !== undefined &&
store.store !== null &&
store.store !== '';
return hasId && hasName && hasStore;
})
.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,
);
}
}
async sellers(): Promise<SellerDto[]> {
this.logger.log('Buscando vendedores com cache Redis...');
try {
return await getOrSetCache<SellerDto[]>(
this.redisClient,
this.SELLERS_CACHE_KEY,
this.SELLERS_TTL,
async () => {
try {
const sellers = await this.repository.findSellers();
if (sellers === null || sellers === undefined) {
throw new HttpException(
'Resultado inválido do repositório',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
const sellersArray = Array.isArray(sellers) ? sellers : [sellers];
return sellersArray
.filter((seller) => {
if (!seller || typeof seller !== 'object') {
return false;
}
const hasId =
seller.id !== undefined &&
seller.id !== null &&
seller.id !== '';
const hasName =
seller.name !== undefined &&
seller.name !== null &&
seller.name !== '';
return hasId && hasName;
})
.map((seller) => new SellerDto(seller));
} catch (error) {
this.logger.error('Erro ao buscar vendedores', error);
throw error;
}
},
);
} catch (error) {
this.logger.error('Erro ao buscar vendedores', error);
throw new HttpException(
'Erro ao buscar vendedores',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async billings(): Promise<BillingDto[]> {
this.logger.log('Buscando informações de faturamento');
try {
const billings = await this.repository.findBillings();
if (billings === null || billings === undefined) {
throw new HttpException(
'Resultado inválido do repositório',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
const billingsArray = Array.isArray(billings) ? billings : [billings];
return billingsArray
.filter((billing) => {
if (!billing || typeof billing !== 'object') {
return false;
}
const hasId =
billing.id !== undefined &&
billing.id !== null &&
billing.id !== '';
const hasDate = billing.date !== undefined && billing.date !== null;
const hasTotal =
billing.total !== undefined && billing.total !== null;
return hasId && hasDate && hasTotal;
})
.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,
);
}
}
async customers(filter: string): Promise<CustomerDto[]> {
this.logger.log(`Buscando clientes com filtro: ${filter}`);
try {
if (!filter || typeof filter !== 'string') {
throw new HttpException('Filtro inválido', HttpStatus.BAD_REQUEST);
}
const customers = await this.repository.findCustomers(filter);
if (customers === null || customers === undefined) {
throw new HttpException(
'Resultado inválido do repositório',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
const customersArray = Array.isArray(customers) ? customers : [customers];
return customersArray
.filter((customer) => {
if (!customer || typeof customer !== 'object') {
return false;
}
const hasId =
customer.id !== undefined &&
customer.id !== null &&
customer.id !== '';
const hasName =
customer.name !== undefined &&
customer.name !== null &&
customer.name !== '';
const hasDocument =
customer.document !== undefined &&
customer.document !== null &&
customer.document !== '';
return hasId && hasName && hasDocument;
})
.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,
);
}
}
async products(filter: string): Promise<ProductDto[]> {
this.logger.log(`Buscando produtos com filtro: ${filter}`);
try {
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', error);
throw new HttpException(
'Erro ao buscar produtos',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async getAllProducts(): Promise<ProductDto[]> {
this.logger.log('Buscando todos os produtos');
try {
return await getOrSetCache<ProductDto[]>(
this.redisClient,
this.ALL_PRODUCTS_CACHE_KEY,
this.ALL_PRODUCTS_TTL,
async () => {
try {
const products = await this.repository.findAllProducts();
if (products === null || products === undefined) {
throw new HttpException(
'Resultado inválido do repositório',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
const productsArray = Array.isArray(products)
? products
: [products];
return productsArray
.filter((product) => {
if (!product || typeof product !== 'object') {
return false;
}
const hasId =
product.id !== undefined &&
product.id !== null &&
product.id !== '';
const hasName =
product.name !== undefined &&
product.name !== null &&
product.name !== '';
const hasManufacturerCode =
product.manufacturerCode !== undefined &&
product.manufacturerCode !== null &&
product.manufacturerCode !== '';
return hasId && hasName && hasManufacturerCode;
})
.map((product) => new ProductDto(product));
} catch (error) {
this.logger.error('Erro ao buscar todos os produtos', error);
throw error;
}
},
);
} catch (error) {
this.logger.error('Erro ao buscar todos os produtos', error);
throw new HttpException(
'Erro ao buscar produtos',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async getAllCarriers(): Promise<CarrierDto[]> {
this.logger.log('Buscando todas as transportadoras');
try {
return await getOrSetCache<CarrierDto[]>(
this.redisClient,
this.CARRIERS_CACHE_KEY,
this.CARRIERS_TTL,
async () => {
try {
const carriers = await this.repository.findAllCarriers();
if (carriers === null || carriers === undefined) {
throw new HttpException(
'Resultado inválido do repositório',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
const carriersArray = Array.isArray(carriers)
? carriers
: [carriers];
return carriersArray
.filter((carrier) => {
if (!carrier || typeof carrier !== 'object') {
return false;
}
const hasCarrierId =
carrier.carrierId !== undefined &&
carrier.carrierId !== null &&
carrier.carrierId !== '';
const hasCarrierName =
carrier.carrierName !== undefined &&
carrier.carrierName !== null &&
carrier.carrierName !== '';
const hasCarrierDescription =
carrier.carrierDescription !== undefined &&
carrier.carrierDescription !== null &&
carrier.carrierDescription !== '';
return hasCarrierId && hasCarrierName && hasCarrierDescription;
})
.map((carrier) => ({
carrierId: carrier.carrierId?.toString() || '',
carrierName: carrier.carrierName || '',
carrierDescription: carrier.carrierDescription || '',
}));
} catch (error) {
this.logger.error('Erro ao buscar transportadoras', error);
throw error;
}
},
);
} catch (error) {
this.logger.error('Erro ao buscar transportadoras', error);
throw new HttpException(
'Erro ao buscar transportadoras',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
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,
);
}
}
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,
);
}
}
async getRegions(): Promise<RegionDto[]> {
this.logger.log('Buscando todas as regiões');
try {
return await getOrSetCache<RegionDto[]>(
this.redisClient,
this.REGIONS_CACHE_KEY,
this.REGIONS_TTL,
async () => {
try {
const regions = await this.repository.findRegions();
if (regions === null || regions === undefined) {
throw new HttpException(
'Resultado inválido do repositório',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
const regionsArray = Array.isArray(regions) ? regions : [regions];
return regionsArray
.filter((region) => {
if (!region || typeof region !== 'object') {
return false;
}
const hasNumregiao =
region.numregiao !== undefined && region.numregiao !== null;
const hasRegiao =
region.regiao !== undefined &&
region.regiao !== null &&
region.regiao !== '';
return hasNumregiao && hasRegiao;
})
.map((region) => new RegionDto(region));
} catch (error) {
this.logger.error('Erro ao buscar regiões', error);
throw error;
}
},
);
} catch (error) {
this.logger.error('Erro ao buscar regiões', error);
throw new HttpException(
'Erro ao buscar regiões',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}

View File

@@ -4,26 +4,26 @@ import { IsOptional, IsString, IsDateString } from 'class-validator';
export class CarrierDto {
@ApiProperty({
description: 'ID da transportadora',
example: '123'
example: '123',
})
carrierId: string;
@ApiProperty({
description: 'Nome da transportadora',
example: 'TRANSPORTADORA ABC LTDA'
example: 'TRANSPORTADORA ABC LTDA',
})
carrierName: string;
@ApiProperty({
description: 'Descrição completa da transportadora (ID - Nome)',
example: '123 - TRANSPORTADORA ABC LTDA'
example: '123 - TRANSPORTADORA ABC LTDA',
})
carrierDescription: string;
@ApiProperty({
description: 'Quantidade de pedidos da transportadora no período',
example: 15,
required: false
required: false,
})
ordersCount?: number;
}
@@ -32,7 +32,7 @@ export class FindCarriersDto {
@ApiProperty({
description: 'Data inicial para filtro (formato YYYY-MM-DD)',
example: '2024-01-01',
required: false
required: false,
})
@IsOptional()
@IsDateString()
@@ -41,7 +41,7 @@ export class FindCarriersDto {
@ApiProperty({
description: 'Data final para filtro (formato YYYY-MM-DD)',
example: '2024-12-31',
required: false
required: false,
})
@IsOptional()
@IsDateString()
@@ -50,9 +50,9 @@ export class FindCarriersDto {
@ApiProperty({
description: 'ID da filial',
example: '1',
required: false
required: false,
})
@IsOptional()
@IsString()
codfilial?: string;
}
}

View File

@@ -20,4 +20,3 @@ export class RegionDto {
Object.assign(this, partial);
}
}