first
This commit is contained in:
16
src/partners/dto/partner.dto.ts
Normal file
16
src/partners/dto/partner.dto.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class PartnerDto {
|
||||
@ApiProperty({ description: 'Identificador do parceiro' })
|
||||
id: string;
|
||||
|
||||
@ApiProperty({ description: 'CPF do parceiro' })
|
||||
cpf: string;
|
||||
|
||||
@ApiProperty({ description: 'Nome do parceiro' })
|
||||
nome: string;
|
||||
|
||||
constructor(partial: Partial<PartnerDto>) {
|
||||
Object.assign(this, partial);
|
||||
}
|
||||
}
|
||||
48
src/partners/partners.controller.ts
Normal file
48
src/partners/partners.controller.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { ApiTags, ApiOperation, ApiParam, ApiBearerAuth, ApiResponse } from '@nestjs/swagger';
|
||||
import { Controller, Get, Param } from '@nestjs/common';
|
||||
import { PartnersService } from './partners.service';
|
||||
import { PartnerDto } from './dto/partner.dto';
|
||||
|
||||
@ApiTags('Parceiros')
|
||||
@Controller('api/v1/')
|
||||
export class PartnersController {
|
||||
|
||||
constructor(private readonly partnersService: PartnersService) {}
|
||||
|
||||
@Get('parceiros/:filter')
|
||||
@ApiOperation({ summary: 'Busca parceiros por filtro (ID, CPF ou nome)' })
|
||||
@ApiParam({ name: 'filter', description: 'Filtro de busca (ID, CPF ou nome)' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Lista de parceiros encontrados.',
|
||||
type: PartnerDto,
|
||||
isArray: true
|
||||
})
|
||||
async findPartners(@Param('filter') filter: string): Promise<PartnerDto[]> {
|
||||
return this.partnersService.findPartners(filter);
|
||||
}
|
||||
|
||||
@Get('parceiros')
|
||||
@ApiOperation({ summary: 'Lista todos os parceiros' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Lista de todos os parceiros.',
|
||||
type: PartnerDto,
|
||||
isArray: true
|
||||
})
|
||||
async getAllPartners(): Promise<PartnerDto[]> {
|
||||
return this.partnersService.getAllPartners();
|
||||
}
|
||||
|
||||
@Get('parceiros/id/:id')
|
||||
@ApiOperation({ summary: 'Busca parceiro por ID específico' })
|
||||
@ApiParam({ name: 'id', description: 'ID do parceiro' })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Parceiro encontrado.',
|
||||
type: PartnerDto
|
||||
})
|
||||
async getPartnerById(@Param('id') id: string): Promise<PartnerDto | null> {
|
||||
return this.partnersService.getPartnerById(id);
|
||||
}
|
||||
}
|
||||
13
src/partners/partners.module.ts
Normal file
13
src/partners/partners.module.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { PartnersController } from './partners.controller';
|
||||
import { PartnersService } from './partners.service';
|
||||
import { DatabaseModule } from '../core/database/database.module';
|
||||
import { RedisModule } from '../core/configs/cache/redis.module';
|
||||
|
||||
@Module({
|
||||
imports: [DatabaseModule, RedisModule],
|
||||
controllers: [PartnersController],
|
||||
providers: [PartnersService],
|
||||
exports: [PartnersService],
|
||||
})
|
||||
export class PartnersModule {}
|
||||
168
src/partners/partners.service.ts
Normal file
168
src/partners/partners.service.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
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';
|
||||
import { PartnerDto } from './dto/partner.dto';
|
||||
|
||||
@Injectable()
|
||||
export class PartnersService {
|
||||
private readonly PARTNERS_TTL = 60 * 60 * 12; // 12 horas
|
||||
private readonly PARTNERS_CACHE_KEY = 'parceiros:search';
|
||||
|
||||
constructor(
|
||||
@Inject(DATA_SOURCE)
|
||||
private readonly dataSource: DataSource,
|
||||
@Inject(RedisClientToken)
|
||||
private readonly redisClient: IRedisClient,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Buscar parceiros com cache otimizado
|
||||
* @param filter - Filtro de busca (ID, CPF ou nome)
|
||||
* @returns Array de parceiros encontrados
|
||||
*/
|
||||
async findPartners(filter: string): Promise<PartnerDto[]> {
|
||||
const cacheKey = `${this.PARTNERS_CACHE_KEY}:${filter}`;
|
||||
|
||||
return getOrSetCache(
|
||||
this.redisClient,
|
||||
cacheKey,
|
||||
this.PARTNERS_TTL,
|
||||
async () => {
|
||||
const queryRunner: QueryRunner = this.dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
|
||||
try {
|
||||
// Primeira tentativa: busca por ID do parceiro
|
||||
let sql = `SELECT ESTPARCEIRO.ID as "id",
|
||||
ESTPARCEIRO.ID || ' - ' || ESTPARCEIRO.NOME ||
|
||||
' ( ' || ESTPARCEIRO.CPF || ' )' as "name",
|
||||
ESTPARCEIRO.CPF as "cpf"
|
||||
FROM ESTPARCEIRO
|
||||
WHERE ESTPARCEIRO.ID = REGEXP_REPLACE('${filter}', '[^0-9]', '')
|
||||
ORDER BY ESTPARCEIRO.NOME`;
|
||||
let partners = await queryRunner.manager.query(sql);
|
||||
|
||||
// Segunda tentativa: busca por CPF se não encontrou por ID
|
||||
if (partners.length === 0) {
|
||||
sql = `SELECT ESTPARCEIRO.ID as "id",
|
||||
ESTPARCEIRO.ID || ' - ' || ESTPARCEIRO.NOME ||
|
||||
' ( ' || ESTPARCEIRO.CPF || ' )' as "name",
|
||||
ESTPARCEIRO.CPF as "cpf"
|
||||
FROM ESTPARCEIRO
|
||||
WHERE REGEXP_REPLACE(ESTPARCEIRO.CPF, '[^0-9]', '') = REGEXP_REPLACE('${filter}', '[^0-9]', '')
|
||||
ORDER BY ESTPARCEIRO.NOME`;
|
||||
partners = await queryRunner.manager.query(sql);
|
||||
}
|
||||
|
||||
// Terceira tentativa: busca por nome do parceiro se não encontrou por ID ou CPF
|
||||
if (partners.length === 0) {
|
||||
sql = `SELECT ESTPARCEIRO.ID as "id",
|
||||
ESTPARCEIRO.ID || ' - ' || ESTPARCEIRO.NOME ||
|
||||
' ( ' || ESTPARCEIRO.CPF || ' )' as "name",
|
||||
ESTPARCEIRO.CPF as "cpf"
|
||||
FROM ESTPARCEIRO
|
||||
WHERE ESTPARCEIRO.NOME LIKE '${filter.toUpperCase().replace('@', '%')}%'
|
||||
ORDER BY ESTPARCEIRO.NOME`;
|
||||
partners = await queryRunner.manager.query(sql);
|
||||
}
|
||||
|
||||
return partners.map(partner => new PartnerDto({
|
||||
id: partner.id,
|
||||
cpf: partner.cpf,
|
||||
nome: partner.name
|
||||
}));
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Buscar todos os parceiros com cache
|
||||
* @returns Array de todos os parceiros
|
||||
*/
|
||||
async getAllPartners(): Promise<PartnerDto[]> {
|
||||
const cacheKey = 'parceiros:all';
|
||||
|
||||
return getOrSetCache(
|
||||
this.redisClient,
|
||||
cacheKey,
|
||||
this.PARTNERS_TTL,
|
||||
async () => {
|
||||
const queryRunner: QueryRunner = this.dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
|
||||
try {
|
||||
const sql = `SELECT ESTPARCEIRO.ID as "id",
|
||||
ESTPARCEIRO.ID || ' - ' || ESTPARCEIRO.NOME ||
|
||||
' ( ' || ESTPARCEIRO.CPF || ' )' as "name",
|
||||
ESTPARCEIRO.CPF as "cpf"
|
||||
FROM ESTPARCEIRO
|
||||
ORDER BY ESTPARCEIRO.NOME`;
|
||||
|
||||
const partners = await queryRunner.manager.query(sql);
|
||||
return partners.map(partner => new PartnerDto({
|
||||
id: partner.id,
|
||||
cpf: partner.cpf,
|
||||
nome: partner.name
|
||||
}));
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Buscar parceiro por ID específico com cache
|
||||
* @param partnerId - ID do parceiro
|
||||
* @returns Parceiro encontrado ou null
|
||||
*/
|
||||
async getPartnerById(partnerId: string): Promise<PartnerDto | null> {
|
||||
const cacheKey = `parceiros:id:${partnerId}`;
|
||||
|
||||
return getOrSetCache(
|
||||
this.redisClient,
|
||||
cacheKey,
|
||||
this.PARTNERS_TTL,
|
||||
async () => {
|
||||
const queryRunner: QueryRunner = this.dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
|
||||
try {
|
||||
const sql = `SELECT ESTPARCEIRO.ID as "id",
|
||||
ESTPARCEIRO.ID || ' - ' || ESTPARCEIRO.NOME ||
|
||||
' ( ' || ESTPARCEIRO.CPF || ' )' as "name",
|
||||
ESTPARCEIRO.CPF as "cpf"
|
||||
FROM ESTPARCEIRO
|
||||
WHERE ESTPARCEIRO.ID = '${partnerId}'`;
|
||||
|
||||
const partners = await queryRunner.manager.query(sql);
|
||||
return partners.length > 0 ? new PartnerDto({
|
||||
id: partners[0].id,
|
||||
cpf: partners[0].cpf,
|
||||
nome: partners[0].name
|
||||
}) : null;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Limpar cache de parceiros (útil para invalidação)
|
||||
* @param pattern - Padrão de chaves para limpar (opcional)
|
||||
*/
|
||||
async clearPartnersCache(pattern?: string) {
|
||||
const cachePattern = pattern || 'parceiros:*';
|
||||
|
||||
// Nota: Esta funcionalidade requer implementação específica do Redis
|
||||
// Por enquanto, mantemos a interface para futuras implementações
|
||||
console.log(`Cache de parceiros seria limpo para o padrão: ${cachePattern}`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user