diff --git a/src/orders/application/deb.service.ts b/src/orders/application/deb.service.ts new file mode 100644 index 0000000..b1fd695 --- /dev/null +++ b/src/orders/application/deb.service.ts @@ -0,0 +1,34 @@ + +import { Injectable, HttpException, HttpStatus } from '@nestjs/common'; +import { DebRepository } from '../repositories/deb.repository'; +import { DebDto } from '../dto/DebDto'; + +@Injectable() +export class DebService { + constructor( + private readonly debRepository: DebRepository, + ) {} + + /** + * Busca débitos por CPF ou CGCENT + * @param cpfCgcent - CPF ou CGCENT do cliente + * @param matricula - Matrícula do funcionário (opcional) + * @param cobranca - Código de cobrança (opcional) + * @returns Lista de débitos do cliente + */ + async findByCpfCgcent(cpfCgcent: string, matricula?: number, cobranca?: string): Promise { + if (!cpfCgcent) { + throw new HttpException('CPF/CGCENT é obrigatório', HttpStatus.BAD_REQUEST); + } + + try { + const result = await this.debRepository.findByCpfCgcent(cpfCgcent, matricula, cobranca); + return result as DebDto[]; + } catch (error) { + throw new HttpException( + error.message || 'Erro ao buscar débitos', + error.status || HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } +} \ No newline at end of file diff --git a/src/orders/controllers/deb.controller.ts b/src/orders/controllers/deb.controller.ts new file mode 100644 index 0000000..9f75514 --- /dev/null +++ b/src/orders/controllers/deb.controller.ts @@ -0,0 +1,49 @@ +import { + Controller, + Get, + Query, + UsePipes, + HttpException, + HttpStatus, + ValidationPipe, + } from '@nestjs/common'; + import { ApiOperation, ApiTags, ApiResponse } from '@nestjs/swagger'; + import { DebService } from '../application/deb.service'; + import { DebDto } from '../dto/DebDto'; + import { FindDebDto } from '../dto/find-deb.dto'; + + @ApiTags('Débitos') + @Controller('api/v1/deb') + export class DebController { + constructor(private readonly debService: DebService) {} + + @Get('find-by-cpf') + @ApiOperation({ + summary: 'Busca débitos por CPF/CGCENT', + description: 'Busca débitos de um cliente usando CPF ou CGCENT. Opcionalmente pode filtrar por matrícula do funcionário ou código de cobrança.', + }) + @ApiResponse({ + status: 200, + description: 'Lista de débitos retornada com sucesso', + type: [DebDto], + }) + @ApiResponse({ + status: 400, + description: 'CPF/CGCENT é obrigatório', + }) + @UsePipes(new ValidationPipe({ transform: true })) + async findByCpfCgcent( + @Query() query: FindDebDto, + ): Promise { + try { + return await this.debService.findByCpfCgcent(query.cpfCgcent, query.matricula, query.cobranca); + } catch (error) { + throw new HttpException( + error.message || 'Erro ao buscar débitos', + error.status || HttpStatus.INTERNAL_SERVER_ERROR, + ); + } + } + } + + \ No newline at end of file diff --git a/src/orders/dto/find-deb.dto.ts b/src/orders/dto/find-deb.dto.ts new file mode 100644 index 0000000..394b07d --- /dev/null +++ b/src/orders/dto/find-deb.dto.ts @@ -0,0 +1,34 @@ +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { IsString, IsNumber, IsNotEmpty, IsOptional, MinLength } from 'class-validator'; +import { Type } from 'class-transformer'; + +export class FindDebDto { + @IsNotEmpty({ message: 'CPF/CGCENT é obrigatório' }) + @IsString({ message: 'CPF/CGCENT deve ser uma string' }) + @MinLength(11, { message: 'CPF/CGCENT deve ter no mínimo 11 caracteres' }) + @ApiProperty({ + description: 'CPF ou CGCENT do cliente', + example: '70290642167', + minLength: 11, + }) + cpfCgcent: string; + + @IsOptional() + @IsNumber({}, { message: 'Matrícula deve ser um número' }) + @Type(() => Number) + @ApiPropertyOptional({ + description: 'Matrícula do funcionário (opcional)', + example: 1498, + type: Number, + }) + matricula?: number; + + @IsOptional() + @IsString({ message: 'Cobrança deve ser uma string' }) + @ApiPropertyOptional({ + description: 'Código de cobrança (opcional)', + example: 'BOL', + }) + cobranca?: string; +} + diff --git a/src/orders/repositories/deb.repository.ts b/src/orders/repositories/deb.repository.ts new file mode 100644 index 0000000..4184a4e --- /dev/null +++ b/src/orders/repositories/deb.repository.ts @@ -0,0 +1,67 @@ + +import { Injectable } from '@nestjs/common'; +import { DataSource } from 'typeorm'; +import { InjectDataSource } from '@nestjs/typeorm'; + +@Injectable() +export class DebRepository { + constructor( + @InjectDataSource("oracle") private readonly oracleDataSource: DataSource, + ) {} + + /** + * Busca débitos por CPF/CGCENT + * @param cpfCgcent - CPF ou CGCENT do cliente + * @param matricula - Matrícula do funcionário (opcional) + * @param cobranca - Código de cobrança (opcional) + * @returns Lista de débitos do cliente + */ + async findByCpfCgcent(cpfCgcent: string, matricula?: number, cobranca?: string) { + const queryRunner = this.oracleDataSource.createQueryRunner(); + await queryRunner.connect(); + try { + const queryBuilder = queryRunner.manager + .createQueryBuilder() + .select([ + 'p.dtemissao AS "dtemissao"', + 'p.codfilial AS "codfilial"', + 'p.duplic AS "duplic"', + 'p.prest AS "prest"', + 'p.codcli AS "codcli"', + 'c.cliente AS "cliente"', + 'p.codcob AS "codcob"', + 'cb.cobranca AS "cobranca"', + 'p.dtvenc AS "dtvenc"', + 'p.dtpag AS "dtpag"', + 'p.valor AS "valor"', + `CASE + WHEN p.dtpag IS NOT NULL THEN 'PAGO' + WHEN p.dtvenc < TRUNC(SYSDATE) THEN 'EM ATRASO' + WHEN p.dtvenc >= TRUNC(SYSDATE) THEN 'A VENCER' + ELSE 'NENHUM' + END AS "situacao"`, + ]) + .from('pcprest', 'p') + .innerJoin('pcclient', 'c', 'p.codcli = c.codcli') + .innerJoin('pccob', 'cb', 'p.codcob = cb.codcob') + .innerJoin('pcempr', 'e', 'c.cgcent = e.cpf') + .where('p.codcob NOT IN (:...excludedCob)', { excludedCob: ['DESD', 'CANC'] }) + .andWhere('c.cgcent = :cpfCgcent', { cpfCgcent }); + + if (matricula) { + queryBuilder.andWhere('e.matricula = :matricula', { matricula }); + } + + if (cobranca) { + queryBuilder.andWhere('p.codcob = :cobranca', { cobranca }); + } + + queryBuilder.orderBy('p.dtvenc', 'ASC'); + + const result = await queryBuilder.getRawMany(); + return result; + } finally { + await queryRunner.release(); + } + } +} \ No newline at end of file