diff --git a/src/app.module.ts b/src/app.module.ts index 747b63ee..ada1262a 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -41,18 +41,10 @@ import { BigqueryModule } from './bigquery/bigquery.module'; import { TestModule } from './test/test.module'; import { CnabModule } from './cnab/cnab.module'; import { SftpModule } from './sftp/sftp.module'; +import sftpConfig from './config/sftp.config'; @Module({ imports: [ - SftpModule.forRoot( - { - host: '', - port: 0, - username: '', - password: '' - }, - false, - ), ConfigModule.forRoot({ isGlobal: true, load: [ @@ -65,6 +57,7 @@ import { SftpModule } from './sftp/sftp.module'; googleConfig, twitterConfig, appleConfig, + sftpConfig, ], envFilePath: ['.env'], }), @@ -119,7 +112,6 @@ import { SftpModule } from './sftp/sftp.module'; TestModule, CnabModule, SftpModule, - // SftpModule, ], }) export class AppModule {} diff --git a/src/bigquery/bigquery.module.ts b/src/bigquery/bigquery.module.ts index 82d2e341..13dfa08e 100644 --- a/src/bigquery/bigquery.module.ts +++ b/src/bigquery/bigquery.module.ts @@ -1,10 +1,21 @@ import { Module } from '@nestjs/common'; import { BigqueryService } from './bigquery.service'; import { ConfigModule } from '@nestjs/config'; +import { BigqueryOrdemPagamentoService } from './services/bigquery-ordem-pagamento.service'; +import { BigqueryOrdemPagamentoRepository } from './repositories/bigquery-ordem-pagamento.repository'; +import { SettingsModule } from 'src/settings/settings.module'; @Module({ - imports: [ConfigModule], - providers: [BigqueryService], - exports: [BigqueryService], + imports: [ConfigModule, SettingsModule], + providers: [ + BigqueryService, + BigqueryOrdemPagamentoService, + BigqueryOrdemPagamentoRepository, + ], + exports: [ + BigqueryService, + BigqueryOrdemPagamentoService, + BigqueryOrdemPagamentoRepository, + ], }) -export class BigqueryModule {} +export class BigqueryModule { } diff --git a/src/cnab/cnab.module.ts b/src/cnab/cnab.module.ts index 7131efc5..b1855d3e 100644 --- a/src/cnab/cnab.module.ts +++ b/src/cnab/cnab.module.ts @@ -1,7 +1,97 @@ import { Module } from '@nestjs/common'; import { CnabService } from './service/cnab.service'; +import { HeaderArquivoService } from './service/header-arquivo.service'; +import { HeaderLoteRepository } from './repository/header-lote.repository'; +import { HeaderLoteService } from './service/header-lote.service'; +import { DetalheAService } from './service/detalhe-a.service'; +import { DetalheARepository } from './repository/detalhe-a.repository'; +import { DetalheBService } from './service/detalhe-b.service'; +import { DetalheBRepository } from './repository/detalhe-b.repository'; +import { ClienteFavorecidoService } from './service/cliente-favorecido.service'; +import { ClienteFavorecidoRepository } from './repository/cliente-favorecido.repository'; +import { PagadorService } from './service/pagador.service'; +import { PagadorRepository } from './repository/pagador.repository'; +import { ArquivoPublicacaoRepository } from './repository/arquivo-publicacao.repository'; +import { TransacaoService } from './service/transacao.service'; +import { TransacaoRepository } from './repository/transacao.repository'; +import { ItemTransacaoService } from './service/item-transacao.service'; +import { ItemTransacaoRepository } from './repository/item-transacao.repository'; +import { SftpModule } from 'src/sftp/sftp.module'; +import { HeaderArquivoRepository } from './repository/header-arquivo.repository'; +import { Cnab104Service } from './service/cnab-104.service'; +import { BanksModule } from 'src/banks/banks.module'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { HeaderArquivo } from './entity/header-arquivo.entity'; +import { HeaderLote } from './entity/header-lote.entity'; +import { DetalheA } from './entity/detalhe-a.entity'; +import { DetalheB } from './entity/detalhe-b.entiy'; +import { ClienteFavorecido } from './entity/cliente-favorecido.entity'; +import { ArquivoPublicacao } from './entity/arquivo-publicacao.entity'; +import { Transacao } from './entity/transacao.entity'; +import { ItemTransacao } from './entity/item-transacao.entity'; +import { Pagador } from './entity/pagador.entity'; +import { UsersModule } from 'src/users/users.module'; +import { BigqueryModule } from 'src/bigquery/bigquery.module'; @Module({ - providers: [CnabService], + imports: [ + UsersModule, + SftpModule, + BanksModule, + BigqueryModule, + TypeOrmModule.forFeature([ + HeaderArquivo, + HeaderLote, + DetalheA, + DetalheB, + ClienteFavorecido, + ArquivoPublicacao, + Transacao, + ItemTransacao, + Pagador, + ]) + ], + providers: [ + CnabService, + Cnab104Service, + HeaderArquivoService, + HeaderArquivoRepository, + HeaderLoteRepository, + HeaderLoteService, + DetalheAService, + DetalheARepository, + DetalheBService, + DetalheBRepository, + ClienteFavorecidoService, + ClienteFavorecidoRepository, + PagadorService, + PagadorRepository, + ArquivoPublicacaoRepository, + TransacaoService, + TransacaoRepository, + ItemTransacaoService, + ItemTransacaoRepository, + ], + exports: [ + CnabService, + Cnab104Service, + HeaderArquivoService, + HeaderArquivoRepository, + HeaderLoteRepository, + HeaderLoteService, + DetalheAService, + DetalheARepository, + DetalheBService, + DetalheBRepository, + ClienteFavorecidoService, + ClienteFavorecidoRepository, + PagadorService, + PagadorRepository, + ArquivoPublicacaoRepository, + TransacaoService, + TransacaoRepository, + ItemTransacaoService, + ItemTransacaoRepository, + ] }) export class CnabModule { } diff --git a/src/cnab/const/cnab-104.const.ts b/src/cnab/const/cnab-104.const.ts index 02784c59..33bf1874 100644 --- a/src/cnab/const/cnab-104.const.ts +++ b/src/cnab/const/cnab-104.const.ts @@ -4,12 +4,14 @@ export const Cnab104Const = { * * @example '18122000' */ - dateOutput: 'ddMMyyyy', + cnabDateOutput: 'ddMMyyyy', /** * HHMMSS - hour is 0-23 * * @example '235911' */ - hourOutput: 'HHmmss', + cnabHourOutput: 'HHmmss', + + dateObjOutput: 'yyyy MM dd', } \ No newline at end of file diff --git a/src/cnab/dto/arquivo-publicacao.dto.ts b/src/cnab/dto/arquivo-publicacao.dto.ts index cbcedfa2..e554e6d1 100644 --- a/src/cnab/dto/arquivo-publicacao.dto.ts +++ b/src/cnab/dto/arquivo-publicacao.dto.ts @@ -1,37 +1,78 @@ +import { IsNotEmpty, ValidateIf } from "class-validator"; + +function isCreate(object: ArquivoPublicacaoDTO): boolean { + return object.id === undefined; +} + export class ArquivoPublicacaoDTO { - constructor(dto?: ArquivoPublicacaoDTO) { - if (dto) { - Object.assign(this, dto); - } + constructor(dto?: ArquivoPublicacaoDTO) { + if (dto) { + Object.assign(this, dto); } - id_arquivo_publicacao: number; - - id_header_arquivo: number; - id_transacao: number; - id_header_lote: number; - dt_geracao_remessa: Date; - hr_geracao_remessa: Date; - dt_geracao_retorno: Date; - hr_geracao_retorno: Date; - - lote_servico: string; - nome_pagador: string; - agencia_pagador: string; - dv_agencia_pagador: string; - conta_pagador: string; - dv_conta_pagador: string; - - nome_cliente?: string; - cpf_cnpj_cliente?: string; - cod_banco_cliente?: string; - agencia_cliente?: string; - dv_agencia_cliente?: string; - conta_corrente_cliente?: string; - dv_conta_corrente_cliente?: string; - - dt_vencimento?: Date; - valor_lancamento?: number; - data_efetivacao?: Date; - valor_real_efetivado?: number; - ocorrencias: string; - } \ No newline at end of file + } + id: number; + + idHeaderArquivo: number; + idTransacao: number; + idHeaderLote: number; + dataGeracaoRemessa: Date; + horaGeracaoRemessa: Date; + dataGeracaoRetorno: Date; + horaGeracaoRetorno: Date; + + + loteServico: string; + nomePagador: string; + agenciaPagador: string; + dvAgenciaPagador: string; + contaPagador: string; + dvContaPagador: string; + + + @ValidateIf(isCreate) + @IsNotEmpty() + nomeCliente?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + cpfCnpjCliente?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + codBancoCliente?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + agenciaCliente?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + dvAgenciaCliente?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + contaCorrenteCliente?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + dvContaCorrenteCliente?: string; + + + @ValidateIf(isCreate) + @IsNotEmpty() + dataVencimento?: Date; + + @ValidateIf(isCreate) + @IsNotEmpty() + valorLancamento?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + dataEfetivacao?: Date; + + @ValidateIf(isCreate) + @IsNotEmpty() + valorRealEfetivado?: number; + + ocorrencias: string; +} \ No newline at end of file diff --git a/src/cnab/dto/detalhe-a.dto.ts b/src/cnab/dto/detalhe-a.dto.ts index 578efc69..d85e0e5e 100644 --- a/src/cnab/dto/detalhe-a.dto.ts +++ b/src/cnab/dto/detalhe-a.dto.ts @@ -16,7 +16,7 @@ export class DetalheADTO { @ValidateIf(isCreate) @IsNotEmpty() - loteServico?: string; + loteServico?: string | null; @ValidateIf(isCreate) @IsNotEmpty() @@ -24,55 +24,55 @@ export class DetalheADTO { @ValidateIf(isCreate) @IsNotEmpty() - tipoFinalidadeConta?: string; + tipoFinalidadeConta?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - dataVencimento?: Date; + dataVencimento?: Date | null; @ValidateIf(isCreate) @IsNotEmpty() - tipoMoeda?: string; + tipoMoeda?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - quantidadeMoeda?: number; + quantidadeMoeda?: number | null; @ValidateIf(isCreate) @IsNotEmpty() - valorLancamento?: number; + valorLancamento?: number | null; @ValidateIf(isCreate) @IsNotEmpty() - numeroDocumentoLancamento?: number; + numeroDocumentoLancamento?: number | null; @ValidateIf(isCreate) @IsNotEmpty() - quantidadeParcelas?: number; + quantidadeParcelas?: number | null; @ValidateIf(isCreate) @IsNotEmpty() - indicadorBloqueio?: string; + indicadorBloqueio?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - indicadorFormaParcelamento?: string; + indicadorFormaParcelamento?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - periodoVencimento?: Date; + periodoVencimento?: Date | null; @ValidateIf(isCreate) @IsNotEmpty() - numeroParcela?: number; + numeroParcela?: number | null; @ValidateIf(isCreate) @IsNotEmpty() - dataEfetivacao?: Date; + dataEfetivacao?: Date | null; @ValidateIf(isCreate) @IsNotEmpty() - valorRealEfetivado?: number; + valorRealEfetivado?: number | null; @ValidateIf(isCreate) @IsNotEmpty() @@ -80,5 +80,5 @@ export class DetalheADTO { @ValidateIf(isCreate) @IsNotEmpty() - ocorrencias: string; + ocorrencias: string | null; } diff --git a/src/cnab/dto/header-arquivo.dto.ts b/src/cnab/dto/header-arquivo.dto.ts index c4aafb3a..3c78be4d 100644 --- a/src/cnab/dto/header-arquivo.dto.ts +++ b/src/cnab/dto/header-arquivo.dto.ts @@ -17,51 +17,55 @@ export class HeaderArquivoDTO { @ValidateIf(isCreate) @IsNotEmpty() - tipoArquivo?: string; + tipoArquivo?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - codigoBanco?: string; + codigoBanco?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - tipoInscricao?: string; + tipoInscricao?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - numeroInscricao?: string; + numeroInscricao?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - codigoConvenio?: string; + codigoConvenio?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - parametroTransmissao?: string; + parametroTransmissao?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - agencia?: string; + agencia?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - dvAgencia?: string; + dvAgencia?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - numeroConta?: string; + numeroConta?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - dvConta?: string; + dvConta?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - nomeEmpresa?: string; + nomeEmpresa?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - dataHoraGeracao?: Date; + dataGeracao?: Date | null; + + @ValidateIf(isCreate) + @IsNotEmpty() + horaGeracao?: Date | null; @ValidateIf(isCreate) @IsNotEmpty() diff --git a/src/cnab/dto/header-lote.dto.ts b/src/cnab/dto/header-lote.dto.ts index b9ee8a53..59fd7f90 100644 --- a/src/cnab/dto/header-lote.dto.ts +++ b/src/cnab/dto/header-lote.dto.ts @@ -22,27 +22,27 @@ export class HeaderLoteDTO { @ValidateIf(isCreate) @IsNotEmpty() - loteServico?: string; + loteServico?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - tipoInscricao?: string; + tipoInscricao?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - numeroInscricao?: string; + numeroInscricao?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - codigoConvenioBanco?: string; + codigoConvenioBanco?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - tipoCompromisso?: string; + tipoCompromisso?: string | null; @ValidateIf(isCreate) @IsNotEmpty() - parametroTransmissao?: string; + parametroTransmissao?: string | null; @ValidateIf(isCreate) @IsNotEmpty() diff --git a/src/cnab/entity/arquivo-publicacao.entity.ts b/src/cnab/entity/arquivo-publicacao.entity.ts index 9b6104d4..e2b3db74 100644 --- a/src/cnab/entity/arquivo-publicacao.entity.ts +++ b/src/cnab/entity/arquivo-publicacao.entity.ts @@ -1,90 +1,92 @@ import { EntityHelper } from "src/utils/entity-helper"; -import { Column, DeepPartial, PrimaryGeneratedColumn } from "typeorm"; +import { Column, DeepPartial, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm"; +import { HeaderArquivo } from "./header-arquivo.entity"; +@Entity() export class ArquivoPublicacao extends EntityHelper { constructor( - arquivoPublicacao?: ArquivoPublicacao | DeepPartial, - ) { - super(); - if (arquivoPublicacao !== undefined) { - Object.assign(this, arquivoPublicacao); - } + arquivoPublicacao:ArquivoPublicacao | DeepPartial, + ) { + super(); + if (arquivoPublicacao !== undefined) { + Object.assign(this, arquivoPublicacao); } - @PrimaryGeneratedColumn() - id_publicacao:number; - - @Column({ type: String, unique: false, nullable: false}) - id_header_arquivo: number; + } + @PrimaryGeneratedColumn() + id: number; - @Column({ type: String, unique: false, nullable: false}) - id_transacao: number; + @ManyToOne(() => HeaderArquivo) + headerArquivo: HeaderArquivo; - @Column({ type: String, unique: false, nullable: false}) - id_header_lote: number; + @Column({ type: String, unique: false, nullable: false }) + idTransacao: number; - @Column({ type: Date, unique: false, nullable: false}) - dt_geracao_remessa: Date; + @Column({ type: String, unique: false, nullable: false }) + idHeaderLote: number; - @Column({ type: Date, unique: false, nullable: false}) - hr_geracao_remessa: Date; + @Column({ type: Date, unique: false, nullable: false }) + dataGeracaoRemessa: Date; - @Column({ type: Date, unique: false, nullable: false}) - dt_geracao_retorno: Date; + @Column({ type: Date, unique: false, nullable: false }) + horaGeracaoRemessa: Date; - @Column({ type: Date, unique: false, nullable: false}) - hr_geracao_retorno: Date; + @Column({ type: Date, unique: false, nullable: false }) + dataGeracaoRetorno: Date; - @Column({ type: String, unique: false, nullable: false}) - lote_servico: string; + @Column({ type: Date, unique: false, nullable: false }) + horaGeracaoRetorno: Date; - @Column({ type: String, unique: false, nullable: false}) - nome_pagador: string; + @Column({ type: String, unique: false, nullable: false }) + loteServico: string; - @Column({ type: String, unique: false, nullable: false}) - agencia_pagador: string; + @Column({ type: String, unique: false, nullable: false }) + nomePagador: string; - @Column({ type: String, unique: false, nullable: false}) - dv_agencia_pagador: string; + @Column({ type: String, unique: false, nullable: false }) + agenciaPagador: string; - @Column({ type: String, unique: false, nullable: false}) - conta_pagador: string; + @Column({ type: String, unique: false, nullable: false }) + dvAgenciaPagador: string; - @Column({ type: String, unique: false, nullable: false}) - dv_conta_pagador: string; - - @Column({ type: String, unique: false, nullable: false}) - nome_cliente?: string; + @Column({ type: String, unique: false, nullable: false }) + contaPagador: string; - @Column({ type: String, unique: false, nullable: false}) - cpf_cnpj_cliente?: string; + @Column({ type: String, unique: false, nullable: false }) + dvContaPagador: string; - @Column({ type: String, unique: false, nullable: false}) - cod_banco_cliente?: string; + @Column({ type: String, unique: false, nullable: false }) + nomeCliente:string; - @Column({ type: String, unique: false, nullable: false}) - agencia_cliente?: string; + @Column({ type: String, unique: false, nullable: false }) + cpfCnpjCliente:string; - @Column({ type: String, unique: false, nullable: false}) - dv_agencia_cliente?: string; + @Column({ type: String, unique: false, nullable: false }) + codigoBancoCliente:string; - @Column({ type: String, unique: false, nullable: false}) - conta_corrente_cliente?: string; + @Column({ type: String, unique: false, nullable: false }) + agenciaCliente:string; - @Column({ type: String, unique: false, nullable: false}) - dv_conta_corrente_cliente?: string; + @Column({ type: String, unique: false, nullable: false }) + dvAgenciaCliente:string; - @Column({ type: String, unique: false, nullable: false}) - dt_vencimento?: Date; + @Column({ type: String, unique: false, nullable: false }) + contaCorrenteCliente:string; - @Column({ type: String, unique: false, nullable: false}) - valor_lancamento?: number; + @Column({ type: String, unique: false, nullable: false }) + dvContaCorrenteCliente:string; - @Column({ type: String, unique: false, nullable: false}) - data_efetivacao?: Date; + @Column({ type: String, unique: false, nullable: false }) + dtVencimento:Date; - @Column({ type: String, unique: false, nullable: false}) - valor_real_efetivado?: number; + @Column({ type: String, unique: false, nullable: false }) + valorLancamento: number | null; - @Column({ type: String, unique: false, nullable: false}) - ocorrencias: string; - } \ No newline at end of file + @Column({ type: String, unique: false, nullable: false }) + dataEfetivacao:Date; + + @Column({ type: String, unique: false, nullable: false }) + valorRealEfetivado: number | null; + + @Column({ type: String, unique: false, nullable: true }) + ocorrencias: string | null; +} \ No newline at end of file diff --git a/src/cnab/entity/detalhe-a.entity.ts b/src/cnab/entity/detalhe-a.entity.ts index 00000e2d..178377d6 100644 --- a/src/cnab/entity/detalhe-a.entity.ts +++ b/src/cnab/entity/detalhe-a.entity.ts @@ -8,57 +8,57 @@ export class DetalheA extends EntityHelper { @PrimaryGeneratedColumn() id: number; - @ManyToOne(() => HeaderLote, {eager: true}) + @ManyToOne(() => HeaderLote, { eager: true }) headerLote: HeaderLote; @Column({ type: String, unique: false, nullable: true }) - loteServico?: string; + loteServico: string | null; - @Column({ type: Number, unique: false, nullable: true }) - clienteFavorecido?: ClienteFavorecido; + @Column({ type: Number, unique: false, nullable: false }) + clienteFavorecido: ClienteFavorecido; @Column({ type: String, unique: false, nullable: true }) - tipoFinalidadeConta?: string; + tipoFinalidadeConta: string | null; @Column({ type: Date, unique: false, nullable: true }) - dataVencimento?: Date; + dataVencimento: Date | null; @Column({ type: String, unique: false, nullable: true }) - tipoMoeda?: string; + tipoMoeda: string | null; @Column({ type: Number, unique: false, nullable: true }) - quantidadeMoeda?: number; + quantidadeMoeda: number | null; @Column({ type: String, unique: false, nullable: true }) - valorLancamento?: number; + valorLancamento: number | null; @Column({ type: String, unique: false, nullable: true }) - numeroDocumentoLancamento?: number; + numeroDocumentoLancamento: number | null; @Column({ type: String, unique: false, nullable: true }) - quantidadeParcelas?: number; + quantidadeParcelas: number | null; @Column({ type: String, unique: false, nullable: true }) - indicadorBloqueio?: string; + indicadorBloqueio: string | null; @Column({ type: String, unique: false, nullable: true }) - indicadorFormaParcelamento?: string; + indicadorFormaParcelamento: string | null; @Column({ type: Date, unique: false, nullable: true }) - periodoVencimento?: Date; + periodoVencimento: Date | null; @Column({ type: String, unique: false, nullable: true }) - numeroParcela?: number; + numeroParcela: number | null; @Column({ type: Date, unique: false, nullable: true }) - dataEfetivacao?: Date; + dataEfetivacao: Date | null; @Column({ type: Number, unique: false, nullable: true }) - valorRealEfetivado?: number; + valorRealEfetivado: number | null; @Column({ type: Number, unique: false, nullable: false }) nsr: number; - @Column({ type: String, length: 10, nullable: true }) - ocorrencias?: string; + @Column({ type: String, unique: false, nullable: true, length: 10 }) + ocorrencias: string | null; } diff --git a/src/cnab/entity/header-arquivo.entity.ts b/src/cnab/entity/header-arquivo.entity.ts index 69484399..69230ad3 100644 --- a/src/cnab/entity/header-arquivo.entity.ts +++ b/src/cnab/entity/header-arquivo.entity.ts @@ -41,11 +41,17 @@ export class HeaderArquivo extends EntityHelper { nomeEmpresa: string | null; @Column({ type: String, unique: false, nullable: true }) - dataHoraGeracao: Date | null; + dataGeracao: Date | null; + + @Column({ type: 'time', unique: false, nullable: true }) + horaGeracao: Date | null; @OneToOne(() => Transacao, { eager: true }) transacao: Transacao; + @Column({ type: Number, unique: true, nullable: false }) + nsa: number; + @CreateDateColumn() createdAt: Date; } diff --git a/src/cnab/repository/header-arquivo.repository.ts b/src/cnab/repository/header-arquivo.repository.ts index e9e5d5a4..33436469 100644 --- a/src/cnab/repository/header-arquivo.repository.ts +++ b/src/cnab/repository/header-arquivo.repository.ts @@ -1,10 +1,10 @@ import { Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { CommonHttpException } from 'src/utils/http-exception/common-http-exception'; import { EntityCondition } from 'src/utils/types/entity-condition.type'; -import { Nullable } from 'src/utils/types/nullable.type'; import { FindOptionsOrder, Repository } from 'typeorm'; -import { HeaderArquivo } from '../entity/header-arquivo.entity'; import { HeaderArquivoDTO } from '../dto/header-arquivo.dto'; +import { HeaderArquivo } from '../entity/header-arquivo.entity'; @Injectable() export class HeaderArquivoRepository { @@ -16,20 +16,29 @@ export class HeaderArquivoRepository { constructor( @InjectRepository(HeaderArquivo) private HeaderArquivoRepository: Repository, - ) {} + ) { } public async save(dto: HeaderArquivoDTO): Promise { return await this.HeaderArquivoRepository.save(dto); } - public async findOne( + public async getOne( fields: EntityCondition | EntityCondition[], order?: FindOptionsOrder - ): Promise> { - return await this.HeaderArquivoRepository.findOne({ + ): Promise { + const header = await this.HeaderArquivoRepository.findOne({ where: fields, order: order, }); + if (!header) { + throw CommonHttpException.invalidField( + 'HeaderArquivo', + Object.values(fields).join(','), + { errorMessage: 'not found.' } + ) + } else { + return header; + } } public async findAll(fields: EntityCondition | EntityCondition[]): Promise { diff --git a/src/cnab/service/cliente-favorecido.service.ts b/src/cnab/service/cliente-favorecido.service.ts index 8990b2df..17d31867 100644 --- a/src/cnab/service/cliente-favorecido.service.ts +++ b/src/cnab/service/cliente-favorecido.service.ts @@ -1,13 +1,12 @@ import { HttpStatus, Injectable, Logger } from '@nestjs/common'; import { User } from 'src/users/entities/user.entity'; import { UsersService } from 'src/users/users.service'; -import { ClienteFavorecido } from '../entity/cliente-favorecido.entity'; -import { ClienteFavorecidoRepository } from '../repository/cliente-favorecido.repository'; -import { SaveClienteFavorecidoDTO } from '../dto/cliente-favorecido.dto'; -import { validateDTO } from 'src/utils/validation-utils'; import { CommonHttpException } from 'src/utils/http-exception/common-http-exception'; import { EntityCondition } from 'src/utils/types/entity-condition.type'; -import { Nullable } from 'src/utils/types/nullable.type'; +import { validateDTO } from 'src/utils/validation-utils'; +import { SaveClienteFavorecidoDTO } from '../dto/cliente-favorecido.dto'; +import { ClienteFavorecido } from '../entity/cliente-favorecido.entity'; +import { ClienteFavorecidoRepository } from '../repository/cliente-favorecido.repository'; @Injectable() export class ClienteFavorecidoService { @@ -48,14 +47,14 @@ export class ClienteFavorecidoService { } public async getOneByIdClienteFavorecido( - id_cliente_favorecido: number, + idClienteFavorecido: number, ): Promise { const cliente_favorecido = - await this.clienteFavorecidoRepository.getOne({ id_cliente_favorecido: id_cliente_favorecido }); + await this.clienteFavorecidoRepository.getOne({ id: idClienteFavorecido }); if (!cliente_favorecido) { throw CommonHttpException.errorDetails( 'cliente_favorecido.conta not found', - { pagadorConta: id_cliente_favorecido }, + { pagadorConta: idClienteFavorecido }, HttpStatus.NOT_FOUND, ); } else { @@ -89,10 +88,19 @@ export class ClienteFavorecidoService { await this.clienteFavorecidoRepository.save(saveObject); } - public async findOne( + public async getOne( fields: EntityCondition | EntityCondition[], - ): Promise> { - return await this.clienteFavorecidoRepository.getOne(fields); + ): Promise { + const cliente = await this.clienteFavorecidoRepository.getOne(fields); + if (!cliente) { + throw CommonHttpException.errorDetails( + 'cliente_favorecido.conta not found', + { pagadorConta: cliente }, + HttpStatus.NOT_FOUND, + ); + } else { + return cliente; + } } } \ No newline at end of file diff --git a/src/cnab/service/header-arquivo.service.ts b/src/cnab/service/header-arquivo.service.ts index c7231bb9..f171e2aa 100644 --- a/src/cnab/service/header-arquivo.service.ts +++ b/src/cnab/service/header-arquivo.service.ts @@ -4,7 +4,7 @@ import { ArquivoPublicacaoDTO } from './../dto/arquivo-publicacao.dto'; import { Injectable, Logger } from '@nestjs/common'; import { BanksService } from 'src/banks/banks.service'; import { SftpService } from 'src/sftp/sftp.service'; -import { asDate, asNumber, asString } from 'src/utils/pipe-utils'; +import { asDate, asNumber, asString, asStringDate } from 'src/utils/pipe-utils'; import { EntityCondition } from 'src/utils/types/entity-condition.type'; import { Nullable } from 'src/utils/types/nullable.type'; import { DetalheADTO } from '../dto/detalhe-a.dto'; @@ -40,6 +40,8 @@ import { HeaderLoteService } from './header-lote.service'; import { ItemTransacaoService } from './item-transacao.service'; import { PagadorService } from './pagador.service'; import { TransacaoService } from './transacao.service'; +import { getDateFromString } from 'src/utils/date-utils'; +import { Cnab104Const } from '../const/cnab-104.const'; @Injectable() export class HeaderArquivoService { @@ -168,8 +170,8 @@ export class HeaderArquivoService { headerArquivo104.nomeEmpresa.value = headerArquivoDTO.nomeEmpresa; headerArquivo104.nomeBanco.value = bank.name; headerArquivo104.tipoArquivo.value = headerArquivoDTO.tipoArquivo; - headerArquivo104.dataGeracaoArquivo.value = headerArquivoDTO.dataHoraGeracao; - headerArquivo104.horaGeracaoArquivo.value = headerArquivoDTO.dataHoraGeracao; + headerArquivo104.dataGeracaoArquivo.value = headerArquivoDTO.dataGeracao; + headerArquivo104.horaGeracaoArquivo.value = headerArquivoDTO.horaGeracao; return headerArquivo104; } @@ -217,7 +219,7 @@ export class HeaderArquivoService { public async findOne( fields: EntityCondition | EntityCondition[], ): Promise> { - return await this.headerArquivoRepository.findOne(fields); + return await this.headerArquivoRepository.getOne(fields); } public async findAll(): Promise { @@ -233,7 +235,8 @@ export class HeaderArquivoService { dto.agencia = asString(pagador.agencia); dto.codigoBanco = String(headerArquivoTemplate.codigoBanco.value); dto.codigoConvenio = String(headerArquivoTemplate.codigoConvenioBanco.value); - dto.dataHoraGeracao = asDate(transacao.dataOrdem); + dto.dataGeracao = asDate(transacao.dataOrdem); + dto.horaGeracao = asDate(transacao.dataOrdem); dto.dvAgencia = asString(pagador.dvAgencia); dto.dvConta = asString(pagador.dvConta); dto.transacao = transacao; @@ -312,7 +315,7 @@ export class HeaderArquivoService { await this.detalheBService.save(detalheB); } public async headerArquivoExists(id_transacao: number): Promise { - const ret = await this.headerArquivoRepository.findOne({ + const ret = await this.headerArquivoRepository.getOne({ transacao: { id: id_transacao }, }); if (ret == null) { @@ -321,131 +324,133 @@ export class HeaderArquivoService { return true; } - public async saveArquivoRetorno(_cnab240:ICnab240_104File):Promise{ + public async saveArquivoRetorno(Cnab240: ICnab240_104File): Promise { const headerArquivo = new HeaderArquivo(); - headerArquivo.cod_banco = String(_cnab240.headerArquivo.codigoBanco.value); - headerArquivo.agencia =String( _cnab240.headerArquivo.agenciaContaCorrente.value ); - headerArquivo.num_conta =String( _cnab240.headerArquivo.numeroConta.value ); - headerArquivo.dv_conta =String( _cnab240.headerArquivo.dvConta.value ); - headerArquivo.dt_geracao = new Date( _cnab240.headerArquivo.dataGeracaoArquivo.value); - headerArquivo.nome_empresa =String( _cnab240.headerArquivo.nomeEmpresa.value); - headerArquivo.nsa =String( _cnab240.headerArquivo.nsa.value); - headerArquivo.param_transmissao =String( _cnab240.headerArquivo.parametroTransmissao.value); - headerArquivo.tipo_arquivo = "retorno"; - headerArquivo.tipo_inscricao =String( _cnab240.headerArquivo.tipoInscricao.value); - headerArquivo.num_inscricao =String( _cnab240.headerArquivo.numeroInscricao.value); - - const headerArquivoRemessa = await this.headerArquivoRepository.findOne({ - nsa: String(_cnab240.headerArquivo.nsa.value), - tipo_arquivo: "remessa" + headerArquivo.codigoBanco = String(Cnab240.headerArquivo.codigoBanco.value); + headerArquivo.agencia = String(Cnab240.headerArquivo.agenciaContaCorrente.value); + headerArquivo.numeroConta = String(Cnab240.headerArquivo.numeroConta.value); + headerArquivo.dvConta = String(Cnab240.headerArquivo.dvConta.value); + headerArquivo.dataGeracao = getDateFromString(Cnab240.headerArquivo.dataGeracaoArquivo.value, Cnab104Const.cnabDateOutput); + headerArquivo.nomeEmpresa = String(Cnab240.headerArquivo.nomeEmpresa.value); + headerArquivo.nsa = Number(Cnab240.headerArquivo.nsa.value); + headerArquivo.parametroTransmissao = String(Cnab240.headerArquivo.parametroTransmissao.value); + headerArquivo.tipoArquivo = "retorno"; + headerArquivo.tipoInscricao = String(Cnab240.headerArquivo.tipoInscricao.value); + headerArquivo.numeroInscricao = String(Cnab240.headerArquivo.numeroInscricao.value); + + const headerArquivoRemessa = await this.headerArquivoRepository.getOne({ + nsa: Number(Cnab240.headerArquivo.nsa.value), + tipoArquivo: "remessa" }); - headerArquivo.id_transacao = headerArquivoRemessa?.id_transacao as number; + headerArquivo.transacao = ({ id: headerArquivoRemessa.transacao.id } as Transacao); const headerArquivoSave = await this.headerArquivoRepository.save(headerArquivo); - _cnab240.lotes.forEach(async l=>{ - const headerLote = new HeaderLoteDTO(); - - headerLote.id_header_arquivo = headerArquivoSave.id_header_arquivo; - headerLote.lote_servico = l.headerLote.loteServico.value ; - headerLote.cod_convenio_banco = l.headerLote.codigoConvenioBanco.value; - headerLote.num_inscricao = l.headerLote.numeroInscricao.value; - headerLote.param_transmissao = l.headerLote.param_transmissao.value ; - headerLote.tipo_compromisso = l.headerLote.tipoCompromisso.value ; - headerLote.tipo_inscricao = l.headerLote.tipoInscricao.value ; - - const pagador = await this.pagadorService.findByConta(l.headerLote.numeroConta.value); - headerLote.id_pagador = Number(pagador?.id_pagador); - - const headerLoteSave = await this.headerLoteService.save(headerLote); - l.registros.forEach(async r=>{ - const detalheA = new DetalheADTO(); - detalheA.id_header_lote = headerLoteSave.id_header_lote; - detalheA.data_efetivacao = r.detalheA?.dataEfetivacao as unknown as Date; - detalheA.dt_vencimento = r.detalheA?.dataVencimento as unknown as Date; - detalheA.indicador_bloqueio = r.detalheA?.indicadorBloqueio.value ; - detalheA.indicador_forma_parcelamento = r.detalheA?.indicadorFormaParcelamento.value ; - detalheA.lote_servico = r.detalheA?.loteServico.value ; - detalheA.nsr = r.detalheA?.nsr.value; - detalheA.num_doc_lancamento = r.detalheA?.numeroDocumento.value; - detalheA.num_parcela = r.detalheA?.numeroParcela.value; - detalheA.periodo_vencimento = new Date(r.detalheA?.dataVencimento.value); - detalheA.qtde_moeda = r.detalheA?.quantidadeMoeda.value; - detalheA.qtde_parcelas = r.detalheA?.quantidadeMoeda.value; - detalheA.valor_lancamento = r.detalheA?.valor_lancamento.value; - detalheA.tipo_finalidade_conta = r.detalheA?.tipoContaFinalidade.value ; - detalheA.tipo_moeda = String(r.detalheA?.tipoMoeda.value) ; - detalheA.valor_real_efetivado = r.detalheA?.valorRealEfetivado.value; - - const cliente = - await this.clienteFavorecidoService.findOne( - {conta_corrente: r.detalheA?.contaCorrenteDestino.value , - dv_conta_corrente: r.detalheA?.dvContaDestino.value }); - - detalheA.id_cliente_favorecido = cliente?.id_cliente_favorecido; - - const detalheASave = await this.detalheAService.save(detalheA); - - const detalheB = new DetalheBDTO(); - detalheB.id_detalhe_a = detalheASave.id_detalhe_a; - detalheB.nsr = r.detalheB?.nsr.value; - detalheB.data_vencimento = r.detalheB?.dataVencimento as unknown as Date; - await this.detalheBService.save(detalheB); - }); + Cnab240.lotes.forEach(async l => { + const headerLote = new HeaderLoteDTO(); + + headerLote.id = headerArquivoSave.id; + headerLote.loteServico = asString(l.headerLote.loteServico.value); + headerLote.codigoConvenioBanco = asString(l.headerLote.codigoConvenioBanco.value); + headerLote.numeroInscricao = asString(l.headerLote.numeroInscricao.value); + headerLote.parametroTransmissao = asString(l.headerLote.param_transmissao.value); + headerLote.tipoCompromisso = l.headerLote.tipoCompromisso.value; + headerLote.tipoInscricao = l.headerLote.tipoInscricao.value; + + const pagador = await this.pagadorService.getByConta(l.headerLote.numeroConta.value); + headerLote.pagador = { id: pagador.id }; + const headerLoteSave = await this.headerLoteService.save(headerLote); + l.registros.forEach(async registro => { + const r = (registro as ICnab240_104RegistroAB); + const detalheA = new DetalheADTO(); + detalheA.headerLote = { id: headerLoteSave.id }; + detalheA.dataEfetivacao = getDateFromString(r.detalheA.dataEfetivacao.value, Cnab104Const.dateObjOutput); + detalheA.dataVencimento = asStringDate(r.detalheA.dataVencimento.value); + detalheA.indicadorBloqueio = r.detalheA?.indicadorBloqueio.value; + detalheA.indicadorFormaParcelamento = asString(r.detalheA?.indicadorFormaParcelamento.value); + detalheA.loteServico = asString(r.detalheA?.loteServico.value); + detalheA.nsr = Number(asString(r.detalheA.nsr.value)); + detalheA.numeroDocumentoLancamento = Number(asString(r.detalheA?.numeroDocumento.value)); + detalheA.numeroParcela = Number(asString(r.detalheA?.numeroParcela.value)); + detalheA.periodoVencimento = getDateFromString(r.detalheA?.dataVencimento.value, Cnab104Const.dateObjOutput); + detalheA.quantidadeMoeda = asNumber(r.detalheA?.quantidadeMoeda.value); + detalheA.quantidadeParcelas = asNumber(r.detalheA?.quantidadeMoeda.value); + detalheA.valorLancamento = asNumber(r.detalheA?.valor_lancamento.value); + detalheA.tipoFinalidadeConta = asString(r.detalheA?.tipoContaFinalidade.value); + detalheA.tipoMoeda = asString(r.detalheA?.tipoMoeda.value); + detalheA.valorRealEfetivado = asNumber(r.detalheA?.valorRealEfetivado.value); + + const cliente = + await this.clienteFavorecidoService.getOne( + { + contaCorrente: r.detalheA.contaCorrenteDestino.value, + dvContaCorrente: r.detalheA.dvContaDestino.value + }); + + detalheA.clienteFavorecido = { id: cliente.id }; + + const detalheASave = await this.detalheAService.save(detalheA); + + const detalheB = new DetalheBDTO(); + detalheB.detalhe_a = { id: detalheASave.id }; + detalheB.nsr = r.detalheB.nsr.value; + detalheB.dataVencimento = getDateFromString(r.detalheB.dataVencimento.value, Cnab104Const.dateObjOutput); + await this.detalheBService.save(detalheB); + }); }) } - public async compareRemessaToRetorno():Promise{ - const arquivosRemessa = await this.headerArquivoRepository.findAll({tipo_arquivo: "remessa"}); - + public async compareRemessaToRetorno(): Promise { + const arquivosRemessa = await this.headerArquivoRepository.findAll({ tipoArquivo: "remessa" }); + arquivosRemessa.forEach(async headerArquivo => { const arquivoPublicacao = new ArquivoPublicacaoDTO(); - arquivoPublicacao.id_header_arquivo = headerArquivo.id_header_arquivo - arquivoPublicacao.id_transacao = headerArquivo.id_transacao; - arquivoPublicacao.dt_geracao_remessa = headerArquivo.dt_geracao; - arquivoPublicacao.hr_geracao_remessa = headerArquivo.hr_geracao; - const arquivosRetorno = - await this.headerArquivoRepository.findAll({tipo_arquivo:"retorno", nsa: headerArquivo.nsa}) ; - if (arquivosRetorno !=null){ + arquivoPublicacao.idHeaderArquivo = headerArquivo.id + arquivoPublicacao.idTransacao = headerArquivo.transacao.id; + arquivoPublicacao.dataGeracaoRemessa = asDate(headerArquivo.dataGeracao); + arquivoPublicacao.horaGeracaoRemessa = asDate(headerArquivo.dataGeracao); + const arquivosRetorno = + await this.headerArquivoRepository.findAll({ tipoArquivo: "retorno", nsa: headerArquivo.nsa }); + if (arquivosRetorno != null) { //Header Arquivo Retorno - arquivosRetorno.forEach(async arquivoRetorno=> { - const headersLoteRetorno = - await this.headerLoteService.findMany({ id_header_arquivo: arquivoRetorno.id_header_arquivo }); - arquivoPublicacao.dt_geracao_retorno = arquivoRetorno.dt_geracao; - arquivoPublicacao.hr_geracao_retorno = arquivoRetorno.hr_geracao; + arquivosRetorno.forEach(async arquivoRetorno => { + const headersLoteRetorno = + await this.headerLoteService.findMany({ id: arquivoRetorno.id }); + arquivoPublicacao.dataGeracaoRetorno = asDate(arquivoRetorno.dataGeracao); + arquivoPublicacao.horaGeracaoRetorno = asDate(arquivoRetorno.horaGeracao); //Header lote Retorno headersLoteRetorno.forEach(async headerLoteRetorno => { //DetalheA Retorno - const detalhesA = await this.detalheAService.findMany({ id_header_lote: headerLoteRetorno.id_header_lote}); - detalhesA.forEach( async detalheA => { - arquivoPublicacao.lote_servico = detalheA.lote_servico; - arquivoPublicacao.dt_vencimento = detalheA.dt_vencimento; - arquivoPublicacao.valor_lancamento = detalheA.valor_lancamento; - arquivoPublicacao.data_efetivacao = detalheA.data_efetivacao; - arquivoPublicacao.valor_real_efetivado = detalheA.valor_real_efetivado; - const clienteFavorecido = - await this.clienteFavorecidoService.getOneByIdClienteFavorecido(detalheA.id_cliente_favorecido); - arquivoPublicacao.nome_cliente = clienteFavorecido.nome ; - arquivoPublicacao.cpf_cnpj_cliente = String(clienteFavorecido.cpf_cnpj); - arquivoPublicacao.cod_banco_cliente = String(clienteFavorecido.cod_banco) ; - arquivoPublicacao.agencia_cliente = String(clienteFavorecido.agencia); - arquivoPublicacao.dv_agencia_cliente = String(clienteFavorecido.dv_agencia); - arquivoPublicacao.conta_corrente_cliente = String(clienteFavorecido.conta_corrente); - arquivoPublicacao.dv_conta_corrente_cliente = String(clienteFavorecido.dv_conta_corrente); - arquivoPublicacao.ocorrencias = detalheA.ocorrencias; - void this.arquivoPublicacaoRepository.save(arquivoPublicacao); + const detalhesA = await this.detalheAService.findMany({ id: headerLoteRetorno.id }); + detalhesA.forEach(async detalheA => { + arquivoPublicacao.loteServico = asString(detalheA.loteServico); + arquivoPublicacao.dataVencimento = asDate(detalheA.dataVencimento); + arquivoPublicacao.valorLancamento = asNumber(detalheA.valorLancamento); + arquivoPublicacao.dataEfetivacao = asDate(detalheA.dataEfetivacao); + arquivoPublicacao.valorRealEfetivado = asNumber(detalheA.valorRealEfetivado); + const clienteFavorecido = + await this.clienteFavorecidoService.getOneByIdClienteFavorecido(detalheA.clienteFavorecido.id); + arquivoPublicacao.nomeCliente = clienteFavorecido.nome; + arquivoPublicacao.cpfCnpjCliente = String(clienteFavorecido.cpfCnpj); + arquivoPublicacao.codBancoCliente = String(clienteFavorecido.codigoBanco); + arquivoPublicacao.agenciaCliente = String(clienteFavorecido.agencia); + arquivoPublicacao.dvAgenciaCliente = String(clienteFavorecido.dvAgencia); + arquivoPublicacao.contaCorrenteCliente = String(clienteFavorecido.contaCorrente); + arquivoPublicacao.dvContaCorrenteCliente = String(clienteFavorecido.dvContaCorrente); + arquivoPublicacao.ocorrencias = asString(detalheA.ocorrencias); + void this.arquivoPublicacaoRepository.save(arquivoPublicacao); }); }); }); } - }); + }); } /** * Get the most recent CNAB Retorno Date saved in database. */ public async getMostRecentRetornoDate(): Promise { - const retorno = await this.headerArquivoRepository.findOne( + const retorno = await this.headerArquivoRepository.getOne( { tipoArquivo: HeaderArquivoTipoArquivo.Retorno }, { createdAt: 'DESC' } ); diff --git a/src/cnab/service/pagador.service.ts b/src/cnab/service/pagador.service.ts index 74fefd6b..161bdae4 100644 --- a/src/cnab/service/pagador.service.ts +++ b/src/cnab/service/pagador.service.ts @@ -14,6 +14,19 @@ export class PagadorService { return await this.pagadorRepository.findOne({ conta: conta }); } + public async getByConta(conta: PagadorContaEnum | string): Promise { + const pagador = await this.pagadorRepository.findOne({ conta: conta }); + if (!pagador) { + throw CommonHttpException.errorDetails( + 'Pagador.conta not found', + { pagadorConta: conta }, + HttpStatus.NOT_FOUND, + ); + } else { + return pagador; + } + } + public async getOneByConta( conta: PagadorContaEnum | string, ): Promise { diff --git a/src/cnab/templates/cnab-240/104/cnab-240-104-detalhe-a-template.const.ts b/src/cnab/templates/cnab-240/104/cnab-240-104-detalhe-a-template.const.ts index 0ec6736f..d950a649 100644 --- a/src/cnab/templates/cnab-240/104/cnab-240-104-detalhe-a-template.const.ts +++ b/src/cnab/templates/cnab-240/104/cnab-240-104-detalhe-a-template.const.ts @@ -43,7 +43,7 @@ export const cnab240_104DetalheATemplate: ICnab240_104DetalheA = { filler: { pos: [80, 92], picture: 'X(013)', value: ' ' }, tipoContaFinalidadeTed: { pos: [93, 93], picture: 'X(001)', value: ' ' }, /** DDMMAAAA */ - dataVencimento: { pos: [94, 101], picture: '9(008)', value: '00000000', dateFormat: { output: Cnab104Const.dateOutput } }, + dataVencimento: { pos: [94, 101], picture: '9(008)', value: '00000000', dateFormat: { output: Cnab104Const.cnabDateOutput } }, tipoMoeda: { pos: [102, 104], picture: 'X(003)', diff --git a/src/cnab/templates/cnab-240/104/cnab-240-104-detalhe-b-template.const.ts b/src/cnab/templates/cnab-240/104/cnab-240-104-detalhe-b-template.const.ts index ca5fbb0b..59a03720 100644 --- a/src/cnab/templates/cnab-240/104/cnab-240-104-detalhe-b-template.const.ts +++ b/src/cnab/templates/cnab-240/104/cnab-240-104-detalhe-b-template.const.ts @@ -39,7 +39,7 @@ export const cnab240_104DetalheBTemplate: ICnab240_104DetalheB = { /** DDMMAAAA */ dataVencimento: { pos: [128, 135], picture: '9(008)', value: '00000000', - dateFormat: { output: Cnab104Const.dateOutput } + dateFormat: { output: Cnab104Const.cnabDateOutput } }, valorDocumento: { pos: [136, 150], diff --git a/src/cnab/templates/cnab-240/104/cnab-240-104-header-arquivo-template.const.ts b/src/cnab/templates/cnab-240/104/cnab-240-104-header-arquivo-template.const.ts index a821e91a..19ba226a 100644 --- a/src/cnab/templates/cnab-240/104/cnab-240-104-header-arquivo-template.const.ts +++ b/src/cnab/templates/cnab-240/104/cnab-240-104-header-arquivo-template.const.ts @@ -118,14 +118,14 @@ export const cnab240_104HeaderArquivoTemplate: ICnab240_104HeaderArquivo = { pos: [144, 151], picture: '9(008)', value: '00000000', - dateFormat: { output: Cnab104Const.dateOutput } + dateFormat: { output: Cnab104Const.cnabDateOutput } }, /** HHMMSS */ horaGeracaoArquivo: { pos: [152, 157], picture: '9(006)', value: '000000', - dateFormat: { output: Cnab104Const.hourOutput } + dateFormat: { output: Cnab104Const.cnabHourOutput } }, nsa: { pos: [158, 163], diff --git a/src/cnab/utils/cnab-field-utils.ts b/src/cnab/utils/cnab-field-utils.ts index a8a4780c..7809966d 100644 --- a/src/cnab/utils/cnab-field-utils.ts +++ b/src/cnab/utils/cnab-field-utils.ts @@ -1,5 +1,5 @@ import { format, isDate } from 'date-fns'; -import { stringToDate } from 'src/utils/date-utils'; +import { getDateFromString } from 'src/utils/date-utils'; import { getStringNoSpecials, getStringUpperUnaccent, @@ -197,7 +197,7 @@ export function formatDate( ? String(field.value) : String( format( - stringToDate(field.value, field.dateFormat?.input), + getDateFromString(field.value, field.dateFormat?.input), field.dateFormat?.output || 'yymmdd', ), ); @@ -211,7 +211,7 @@ function validateFormatDate(field: CnabField) { if (!field.dateFormat) { throw new Error(`CnabField must have dateFormat.`); } - if (isNaN(stringToDate(field.value, field.dateFormat.input).getDate())) { + if (isNaN(getDateFromString(field.value, field.dateFormat.input).getDate())) { const dateFormat = field.dateFormat ? JSON.stringify(field.dateFormat) : 'undefined'; diff --git a/src/cron-jobs/cron-jobs.module.ts b/src/cron-jobs/cron-jobs.module.ts index 619ccb95..9d5bf892 100644 --- a/src/cron-jobs/cron-jobs.module.ts +++ b/src/cron-jobs/cron-jobs.module.ts @@ -1,12 +1,13 @@ import { Module } from '@nestjs/common'; -import { CronJobsService } from './cron-jobs.service'; +import { ConfigModule } from '@nestjs/config'; import { ScheduleModule } from '@nestjs/schedule'; +import { MailCountModule } from 'src/mail-count/mail-count.module'; import { MailHistoryModule } from 'src/mail-history/mail-history.module'; import { MailModule } from 'src/mail/mail.module'; import { SettingsModule } from 'src/settings/settings.module'; -import { ConfigModule } from '@nestjs/config'; import { UsersModule } from 'src/users/users.module'; -import { MailCountModule } from 'src/mail-count/mail-count.module'; +import { CronJobsService } from './cron-jobs.service'; +import { CnabModule } from 'src/cnab/cnab.module'; @Module({ imports: [ @@ -17,6 +18,7 @@ import { MailCountModule } from 'src/mail-count/mail-count.module'; MailModule, UsersModule, MailCountModule, + CnabModule, ], providers: [CronJobsService], exports: [CronJobsService], diff --git a/src/cron-jobs/cron-jobs.service.spec.ts b/src/cron-jobs/cron-jobs.service.spec.ts index dad6e148..cb15705a 100644 --- a/src/cron-jobs/cron-jobs.service.spec.ts +++ b/src/cron-jobs/cron-jobs.service.spec.ts @@ -17,9 +17,6 @@ import { RoleEnum } from 'src/roles/roles.enum'; import { MailRegistrationInterface } from 'src/mail/interfaces/mail-registration.interface'; import { DeepPartial } from 'typeorm'; -/** - * FIXME: 'imports: [ < the Module containing BankRepository > ]' - */ xdescribe('CronJobsService', () => { let cronJobsService: CronJobsService; let settingsService: SettingsService; diff --git a/src/cron-jobs/cron-jobs.service.ts b/src/cron-jobs/cron-jobs.service.ts index 1adf652d..216c04d6 100644 --- a/src/cron-jobs/cron-jobs.service.ts +++ b/src/cron-jobs/cron-jobs.service.ts @@ -29,8 +29,6 @@ export enum CrobJobsEnum { pollDb = 'pollDb', bulkResendInvites = 'bulkResendInvites', updateTransacaoFromJae = 'updateTransacaoFromJae', - sendNewCNABs = 'sendNewCNABs', - getRetornoCNAB = 'getRetornoCNAB', updateRemessa = 'updateRemessa', updateRetorno = 'updateRetorno' } @@ -117,27 +115,27 @@ export class CronJobsService implements OnModuleInit { { name: CrobJobsEnum.updateTransacaoFromJae, cronJobParameters: { - cronTime: '45 14 * * *', // 14:45 GMT = 11:45BRT (GMT-3) + cronTime: '* * * * *', onTick: async () => { - await this.bulkResendInvites(); + await this.updateTransacaoFromJae(); }, }, }, { name: CrobJobsEnum.updateRemessa, cronJobParameters: { - cronTime: '45 14 * * *', // 14:45 GMT = 11:45BRT (GMT-3) + cronTime: '45 14 * * *', onTick: async () => { await this.updateRemessa(); }, }, }, { - name: CrobJobsEnum.getRetornoCNAB, + name: CrobJobsEnum.updateRetorno, cronJobParameters: { cronTime: '45 14 * * *', // 14:45 GMT = 11:45BRT (GMT-3) onTick: async () => { - await this.getRetornoCNAB(); + await this.updateRetorno(); }, }, } diff --git a/src/database/migrations/1709840947523-AddArquivoPub.ts b/src/database/migrations/1709840947523-AddArquivoPub.ts new file mode 100644 index 00000000..f1937b94 --- /dev/null +++ b/src/database/migrations/1709840947523-AddArquivoPub.ts @@ -0,0 +1,28 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddArquivoPub1709840947523 implements MigrationInterface { + name = 'AddArquivoPub1709840947523' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE "arquivo_publicacao" ("id" SERIAL NOT NULL, "idTransacao" character varying NOT NULL, "idHeaderLote" character varying NOT NULL, "dataGeracaoRemessa" TIMESTAMP NOT NULL, "horaGeracaoRemessa" TIMESTAMP NOT NULL, "dataGeracaoRetorno" TIMESTAMP NOT NULL, "horaGeracaoRetorno" TIMESTAMP NOT NULL, "loteServico" character varying NOT NULL, "nomePagador" character varying NOT NULL, "agenciaPagador" character varying NOT NULL, "dvAgenciaPagador" character varying NOT NULL, "contaPagador" character varying NOT NULL, "dvContaPagador" character varying NOT NULL, "nomeCliente" character varying NOT NULL, "cpfCnpjCliente" character varying NOT NULL, "codigoBancoCliente" character varying NOT NULL, "agenciaCliente" character varying NOT NULL, "dvAgenciaCliente" character varying NOT NULL, "contaCorrenteCliente" character varying NOT NULL, "dvContaCorrenteCliente" character varying NOT NULL, "dtVencimento" character varying NOT NULL, "valorLancamento" character varying NOT NULL, "dataEfetivacao" character varying NOT NULL, "valorRealEfetivado" character varying NOT NULL, "ocorrencias" character varying, "headerArquivoId" integer, CONSTRAINT "PK_22de2aadff9e230e92bc4cb1ef6" PRIMARY KEY ("id"))`); + await queryRunner.query(`ALTER TABLE "header_arquivo" DROP COLUMN "dataHoraGeracao"`); + await queryRunner.query(`ALTER TABLE "header_arquivo" ADD "dataGeracao" character varying`); + await queryRunner.query(`ALTER TABLE "header_arquivo" ADD "horaGeracao" TIME`); + await queryRunner.query(`ALTER TABLE "header_arquivo" ADD "nsa" integer NOT NULL`); + await queryRunner.query(`ALTER TABLE "header_arquivo" ADD CONSTRAINT "UQ_785f0108ddcd63b34b2574b4a2d" UNIQUE ("nsa")`); + await queryRunner.query(`ALTER TABLE "detalhe_a" ALTER COLUMN "clienteFavorecido" SET NOT NULL`); + await queryRunner.query(`ALTER TABLE "arquivo_publicacao" ADD CONSTRAINT "FK_9034ea1202b6574b75a2304d419" FOREIGN KEY ("headerArquivoId") REFERENCES "header_arquivo"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "arquivo_publicacao" DROP CONSTRAINT "FK_9034ea1202b6574b75a2304d419"`); + await queryRunner.query(`ALTER TABLE "detalhe_a" ALTER COLUMN "clienteFavorecido" DROP NOT NULL`); + await queryRunner.query(`ALTER TABLE "header_arquivo" DROP CONSTRAINT "UQ_785f0108ddcd63b34b2574b4a2d"`); + await queryRunner.query(`ALTER TABLE "header_arquivo" DROP COLUMN "nsa"`); + await queryRunner.query(`ALTER TABLE "header_arquivo" DROP COLUMN "horaGeracao"`); + await queryRunner.query(`ALTER TABLE "header_arquivo" DROP COLUMN "dataGeracao"`); + await queryRunner.query(`ALTER TABLE "header_arquivo" ADD "dataHoraGeracao" character varying`); + await queryRunner.query(`DROP TABLE "arquivo_publicacao"`); + } + +} diff --git a/src/sftp/sftp-client/sftp-client.service.ts b/src/sftp/sftp-client/sftp-client.service.ts index 5b3827d7..d8c4b57e 100644 --- a/src/sftp/sftp-client/sftp-client.service.ts +++ b/src/sftp/sftp-client/sftp-client.service.ts @@ -5,10 +5,10 @@ import { ConnectConfig } from '../interfaces/connect-config.interface'; @Injectable() export class SftpClientService { private readonly logger: Logger; - constructor( - private readonly sftpClient: SftpClient - ) { - this.logger = new Logger(SftpClientService.name); + private sftpClient: SftpClient; + constructor() { + this.logger = new Logger('SftpClientService'); + this.sftpClient = new SftpClient(); } client() { diff --git a/src/sftp/sftp.module.ts b/src/sftp/sftp.module.ts index b5f88283..98ac1324 100644 --- a/src/sftp/sftp.module.ts +++ b/src/sftp/sftp.module.ts @@ -6,7 +6,8 @@ import { ConnectConfig } from './interfaces/connect-config.interface'; import { SftpService } from './sftp.service'; @Module({ - providers: [SftpClientService, SftpService] + providers: [SftpClientService, SftpService], + exports: [SftpClientService, SftpService], }) export class SftpModule { static forRoot( @@ -28,7 +29,7 @@ export class SftpModule { }, }, ], - exports: [SftpClientService], + exports: [SftpClientService, SftpService], }; } } diff --git a/src/sftp/sftp.service.ts b/src/sftp/sftp.service.ts index caa01a60..11abccd3 100644 --- a/src/sftp/sftp.service.ts +++ b/src/sftp/sftp.service.ts @@ -2,6 +2,8 @@ import { Injectable, Logger } from '@nestjs/common'; import { SftpClientService } from './sftp-client/sftp-client.service'; import { ConnectConfig } from './interfaces/connect-config.interface'; import { FileInfo } from './interfaces/file-info.interface'; +import { ConfigService } from '@nestjs/config'; +import { AllConfigType } from 'src/config/config.type'; @Injectable() export class SftpService { @@ -10,10 +12,26 @@ export class SftpService { private readonly RETORNO_FOLDER = '/retorno' private readonly BACKUP_REMESSA = '/backup/remessa' private readonly BACKUP_RETORNO_FOLDER = '/backup/retorno' - constructor(private readonly sftpClient: SftpClientService) { + constructor( + private readonly configService: ConfigService, + private readonly sftpClient: SftpClientService, + ) { this.logger = new Logger('SftpService', { timestamp: true }); } + private getClientCredentials(): ConnectConfig { + return { + host: this.configService.getOrThrow('sftp.host', { infer: true }), + port: this.configService.getOrThrow('sftp.port', { infer: true }), + username: this.configService.getOrThrow('sftp.username', { infer: true }), + password: this.configService.getOrThrow('sftp.password', { infer: true }), + } + } + + private async connectClient() { + await this.sftpClient.connect(this.getClientCredentials()); + } + public async download( remotePath: string, localPath: string, @@ -57,6 +75,7 @@ export class SftpService { cnabName: string | null, cnabString: string | null, }> { + await this.connectClient(); const fileInfo: FileInfo = await this.sftpClient.list( this.RETORNO_FOLDER, this.getRegexForCnab('retorno'), @@ -73,6 +92,7 @@ export class SftpService { * @param cnabName Name with extension. No folder path. */ public async backupCnabRetorno(cnabName: string) { + await this.connectClient(); await this.sftpClient.rename( `${this.RETORNO_FOLDER}/${cnabName}`, `${this.BACKUP_RETORNO_FOLDER}/${cnabName}` diff --git a/src/utils/date-utils.ts b/src/utils/date-utils.ts index d15f05d6..0ce5ff20 100644 --- a/src/utils/date-utils.ts +++ b/src/utils/date-utils.ts @@ -112,7 +112,7 @@ export function getDateYMDString(date: Date): string { * * @param inputFormat date-fns date format. (see {@link https://date-fns.org/v3.3.1/docs/format}) */ -export function stringToDate( +export function getDateFromString( value: string, inputFormat?: string, throwIfInvalid = true,