UNPKG

eust-conciliation

Version:
119 lines (96 loc) 4.91 kB
/* eslint-disable no-unused-vars */ /* eslint-disable no-await-in-loop */ /* eslint-disable no-restricted-syntax */ import { Inject, Injectable } from '@severo-tech/injection-decorator'; import { Agent, AgentType } from '../../../../domain/agent'; import { PromisesUtil } from '../../../utils'; import { ConciliationBase } from './conciliation-base'; import { Debit } from '../../../../domain/debit'; import { IAgentClient, IDebitClient, IInvoiceClient } from '../../../contracts'; import { IConfig } from '../../../contracts/config'; interface IGroupedDebit { cnpj: string; value: number; debits: Debit[]; } @Injectable() export class ConciliationOneToMany extends ConciliationBase { @Inject('Agent01EUSTClient') private readonly agentClient!: IAgentClient; @Inject('Debit01EUSTClient') private readonly debitClient!: IDebitClient; @Inject('PromisesUtil') private readonly promisesUtil!: PromisesUtil; @Inject('EnvConfig') private readonly config!: IConfig; public async execute(year: number, month: number, user: Agent, startDate: Date, endDate: Date): Promise<void> { this.logger.info(`"ConciliationOneToMany.execute" - Conciliating One User to Many Transmitters debits - UserCode [${user.code}]`); await this.executeBy((debit) => this.groupDebitsByTransmitterCNPJ(debit), year, month, user, startDate, endDate); await this.executeBy((debit) => this.groupDebitsByTransmitterRootCNPJ(debit), year, month, user, startDate, endDate); await this.executeByInvoice(year, month, user, startDate, endDate); this.logger.info('"ConciliationOneToMany.execute" - Finished One-To-Many debits conciliation'); } private async executeBy(groupMethod: (debits: Debit[]) => Promise<IGroupedDebit[]>, year: number, month: number, user: Agent, startDate: Date, endDate: Date): Promise<void> { const debits = await this.debitClient.find({ year, month, userCode: user.code, reconciled: false, }); const groupedDebits = await groupMethod(debits); this.logger.info(`"ConciliationOneToMany.execute" - Grouped ${groupedDebits.length} Debits to process`); const { maxParallelExecution } = this.config.service; await this.promisesUtil.groupExecute(groupedDebits, maxParallelExecution, async (group: IGroupedDebit): Promise<void> => { await this.tryToConciliateDebits(startDate, endDate, group.debits, group.cnpj, user.cnpj, group.value); }); } private async executeByInvoice(year: number, month: number, user: Agent, startDate: Date, endDate: Date): Promise<void> { const debits = await this.debitClient.find({ year, month, userCode: user.code, reconciled: false, }); const groupedDebits = await this.groupDebitsByTransmitterRootCNPJ(debits); this.logger.info(`"ConciliationOneToMany.executeByInvoice" - Grouped ${groupedDebits.length} Debits to process`); const { maxParallelExecution } = this.config.service; await this.promisesUtil.groupExecute(groupedDebits, maxParallelExecution, async (group: IGroupedDebit): Promise<void> => { await this.tryToConciliateInvoice(startDate, endDate, group.debits, group.cnpj, user.cnpj); }); } private async groupDebitsByTransmitterCNPJ(debits: Debit[]): Promise<IGroupedDebit[]> { let groupMap = new Map<string, IGroupedDebit>(); for (const debit of debits) { if (debit.value > 0) { // Groups only debits that haven't been reconciled so far. const [transmitter] = await this.agentClient.find({ code: debit.transmitterCode, type: AgentType.Transmitter }); if (transmitter) { const { cnpj } = transmitter; groupMap = this.setGroupMap(groupMap, cnpj, debit); } } } return [...groupMap.values()].filter((el: IGroupedDebit): boolean => el.debits.length > 1); } private async groupDebitsByTransmitterRootCNPJ(debits: Debit[]): Promise<IGroupedDebit[]> { let groupCnpjRootMap = new Map<string, IGroupedDebit>(); for (const debit of debits) { if (debit.value > 0) { // Groups only debits that haven't been reconciled so far. const [transmitter] = await this.agentClient.find({ code: debit.transmitterCode, type: AgentType.Transmitter }); if (transmitter) { const { cnpj } = transmitter; const cnpjRoot = cnpj.substring(0, 8); groupCnpjRootMap = this.setGroupMap(groupCnpjRootMap, cnpjRoot, debit); } } } return [...groupCnpjRootMap.values()].filter((el: IGroupedDebit): boolean => el.debits.length > 1); } private setGroupMap(group: Map<string, IGroupedDebit>, cnpj: string, debit: Debit): Map<string, IGroupedDebit> { const existingGrouped = group.get(cnpj); return group.set(cnpj, { cnpj, debits: [...(existingGrouped?.debits ?? []), debit], value: +((existingGrouped?.value ?? 0) + debit.value).toFixed(2), }); } }