Ajuste conexao oracle & postgres

This commit is contained in:
unknown
2025-03-28 17:03:25 -03:00
parent d2ffb266db
commit b98b219e52
28 changed files with 916 additions and 1383 deletions

View File

@@ -34,10 +34,9 @@ export class DataConsultController {
}
@Get('products/:filter')
@ApiOperation({ summary: 'Filtra produtos pelo parâmetro fornecido' })
@ApiParam({ name: 'filter', description: 'Filtro de busca para produtos' })
@ApiOperation({ summary: 'Busca produtos filtrados' })
@ApiParam({ name: 'filter', description: 'Filtro de busca' })
async products(@Param('filter') filter: string) {
return this.dataConsultService.products(filter);
}
}
}

View File

@@ -2,15 +2,15 @@ import { Module } from '@nestjs/common';
import { DataConsultService } from './data-consult.service';
import { DataConsultController } from './data-consult.controller';
import { DataConsultRepository } from './data-consult.repository';
import { CacheModule } from '../core/configs/cache/redis.module';
import { LoggerModule } from 'src/Log/logger.module';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [CacheModule,LoggerModule],
imports: [LoggerModule, ConfigModule],
controllers: [DataConsultController],
providers: [
DataConsultService,
DataConsultRepository,
],
],
})
export class DataConsultModule {}

View File

@@ -1,18 +1,19 @@
import { Injectable } from '@nestjs/common';
import { DataSource } from 'typeorm';
import { typeOrmConfig } from '../core/configs/typeorm.config';
import { createOracleConfig } from '../core/configs/typeorm.oracle.config';
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 { ConfigService } from '@nestjs/config';
@Injectable()
export class DataConsultRepository {
private readonly dataSource: DataSource;
constructor() {
this.dataSource = new DataSource(typeOrmConfig);
constructor(private readonly configService: ConfigService) {
this.dataSource = new DataSource(createOracleConfig(configService));
this.dataSource.initialize();
}
@@ -63,56 +64,64 @@ export class DataConsultRepository {
}
async findCustomers(filter: string): Promise<CustomerDto[]> {
if (!filter || typeof filter !== 'string') return [];
const cleanedNumeric = filter.replace(/[^\d]/g, '');
const likeFilter = filter.toUpperCase().replace('@', '%') + '%';
const queries = [
// Busca por código (apenas números)
{
sql: `
SELECT PCCLIENT.CODCLI as "id",
PCCLIENT.CODCLI || ' - ' || PCCLIENT.CLIENTE ||
' ( ' || REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '') || ' )' as "name"
FROM PCCLIENT
WHERE PCCLIENT.CODCLI = REGEXP_REPLACE(?, '[^0-9]', '')
WHERE PCCLIENT.CODCLI = :1
ORDER BY PCCLIENT.CLIENTE
`,
params: [filter],
params: [cleanedNumeric],
},
// Busca por CNPJ/CPF limpo
{
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]', '') = REGEXP_REPLACE(?, '[^0-9]', '')
WHERE REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '') = :1
ORDER BY PCCLIENT.CLIENTE
`,
params: [filter],
params: [cleanedNumeric],
},
// Busca por nome do cliente
{
sql: `
SELECT PCCLIENT.CODCLI as "id",
PCCLIENT.CODCLI || ' - ' || PCCLIENT.CLIENTE ||
' ( ' || REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '') || ' )' as "name"
FROM PCCLIENT
WHERE PCCLIENT.CLIENTE LIKE ?
WHERE UPPER(PCCLIENT.CLIENTE) LIKE :1
ORDER BY PCCLIENT.CLIENTE
`,
params: [filter.toUpperCase().replace('@', '%') + '%'],
params: [likeFilter],
},
];
for (const { sql, params } of queries) {
const result = await this.executeQuery<CustomerDto[]>(sql, params);
if (result.length > 0) {
return result;
}
}
return [];
}
async findProducts(filter: string): Promise<ProductDto[]> {
const cleanFilter = filter.replace(/[^\d]/g, '');
const cleanedFilter = filter.replace(/[^\d]/g, ''); // apenas números
const likeFilter = filter + '%';
const codAux = filter.replace(/[^\d]/g, '');
const queries = [
{
@@ -124,7 +133,7 @@ export class DataConsultRepository {
WHERE PCPRODUT.CODPROD = ?
ORDER BY PCPRODUT.DESCRICAO
`,
params: [cleanFilter],
params: [cleanedFilter],
},
{
sql: `
@@ -135,7 +144,7 @@ export class DataConsultRepository {
WHERE PCPRODUT.CODAUXILIAR = ?
ORDER BY PCPRODUT.DESCRICAO
`,
params: [codAux],
params: [cleanedFilter],
},
{
sql: `

View File

@@ -1,6 +1,4 @@
import { Inject, Injectable } from '@nestjs/common';
import { IRedisClient } from '../core/configs/cache/IRedisClient';
import { RedisClientToken } from '../core/configs/cache/redis-client.adapter.provider';
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';
@@ -9,119 +7,73 @@ import { CustomerDto } from './dto/customer.dto';
import { ProductDto } from './dto/product.dto';
import { ILogger } from '../Log/ILogger';
const DEFAULT_CACHE_TTL = 100;
@Injectable()
export class DataConsultService {
constructor(
private readonly repository: DataConsultRepository,
@Inject(RedisClientToken)
private readonly redisClient: IRedisClient,
@Inject('LoggerService')
private readonly logger: ILogger
) {}
/**
* Método genérico para lidar com lógica de cache
* @param cacheKey - A chave a ser usada para cache
* @param fetchFn - Função para buscar dados se não estiverem no cache
* @param ttl - Tempo de vida em segundos para o cache
* @returns Os dados em cache ou recentemente buscados
*/
private async getCachedData<T>(
cacheKey: string,
fetchFn: () => Promise<T>,
ttl: number = DEFAULT_CACHE_TTL
): Promise<T> {
try {
this.logger.log(`Tentando obter dados em cache para a chave: ${cacheKey}`);
const cached = await this.redisClient.get<T>(cacheKey);
if (cached) {
this.logger.log(`Cache encontrado para a chave: ${cacheKey}`);
return cached;
}
this.logger.log(`Cache não encontrado para a chave: ${cacheKey}, buscando na origem`);
const result = await fetchFn();
try {
await this.redisClient.set<T>(cacheKey, result, ttl);
this.logger.log(`Dados armazenados em cache com sucesso para a chave: ${cacheKey}`);
} catch (cacheError) {
this.logger.warn(`Falha ao armazenar dados em cache para a chave: ${cacheKey}`);
this.logger.error('Detalhes do erro de cache:', cacheError instanceof Error ? cacheError.stack : '');
}
return result;
} catch (error) {
this.logger.error(
`Erro no método getCachedData para a chave ${cacheKey}:`,
error instanceof Error ? error.stack : ''
);
return fetchFn();
}
}
/**
* Obter todas as lojas com cache
* Obter todas as lojas
* @returns Array de StoreDto
*/
async stores(): Promise<StoreDto[]> {
this.logger.log('Buscando todas as lojas');
return this.getCachedData<StoreDto[]>(
'data-consult:stores',
() => this.repository.findStores()
);
return this.repository.findStores();
}
/**
* Obter todos os vendedores com cache
* Obter todos os vendedores
* @returns Array de SellerDto
*/
async sellers(): Promise<SellerDto[]> {
this.logger.log('Buscando todos os vendedores');
return this.getCachedData<SellerDto[]>(
'data-consult:sellers',
() => this.repository.findSellers()
);
return this.repository.findSellers();
}
/**
* Obter todos os faturamentos com cache
* Obter todos os faturamentos
* @returns Array de BillingDto
*/
async billings(): Promise<BillingDto[]> {
this.logger.log('Buscando todos os faturamentos');
return this.getCachedData<BillingDto[]>(
'data-consult:billings',
() => this.repository.findBillings()
);
return this.repository.findBillings();
}
/**
* Obter clientes filtrados por termo de pesquisa com cache
* Obter clientes filtrados por termo de pesquisa
* @param filter - Termo de pesquisa para filtrar clientes
* @returns Array de CustomerDto
*/
async customers(filter: string): Promise<CustomerDto[]> {
this.logger.log(`Buscando clientes com filtro: ${filter}`);
return this.getCachedData<CustomerDto[]>(
`data-consult:customers:${filter}`,
() => this.repository.findCustomers(filter)
);
return this.repository.findCustomers(filter);
}
/**
* Obter produtos filtrados por termo de pesquisa com cache
* Obter produtos filtrados por termo de pesquisa
* @param filter - Termo de pesquisa para filtrar produtos
* @returns Array de ProductDto
*/
async products(filter: string): Promise<ProductDto[]> {
this.logger.log(`Buscando produtos com filtro: ${filter}`);
return this.getCachedData<ProductDto[]>(
`data-consult:products:${filter}`,
() => this.repository.findProducts(filter)
);
try {
const result = await this.repository.findProducts(filter);
this.logger.log(`Produtos encontrados: ${result.length}`);
return result;
} 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
);
}
}
}