diff --git a/package-lock.json b/package-lock.json index 2061f437..ad366f3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "class-transformer": "0.5.1", "class-validator": "0.14.0", "date-fns": "^2.30.0", + "dotenv": "^16.4.5", "fb": "2.0.0", "gerador-validador-cpf": "^5.0.2", "google-auth-library": "8.8.0", @@ -3431,6 +3432,14 @@ "rxjs": "^6.0.0 || ^7.2.0" } }, + "node_modules/@nestjs/config/node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "engines": { + "node": ">=12" + } + }, "node_modules/@nestjs/config/node_modules/uuid": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", @@ -6470,11 +6479,14 @@ } }, "node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "engines": { "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, "node_modules/dotenv-expand": { @@ -18463,6 +18475,11 @@ "uuid": "9.0.0" }, "dependencies": { + "dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" + }, "uuid": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", @@ -20839,9 +20856,9 @@ } }, "dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" }, "dotenv-expand": { "version": "10.0.0", diff --git a/package.json b/package.json index 4803c63b..c6af548b 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "class-transformer": "0.5.1", "class-validator": "0.14.0", "date-fns": "^2.30.0", + "dotenv": "^16.4.5", "fb": "2.0.0", "gerador-validador-cpf": "^5.0.2", "google-auth-library": "8.8.0", diff --git a/src/bigquery/entities/ordem-pagamento.bigquery-entity.ts b/src/bigquery/entities/ordem-pagamento.bigquery-entity.ts new file mode 100644 index 00000000..ad2ab81d --- /dev/null +++ b/src/bigquery/entities/ordem-pagamento.bigquery-entity.ts @@ -0,0 +1,90 @@ +export class BigqueryOrdemPagamento { + /** Data da ordem de pagamento (partição) */ + data_ordem: Date; + + /** Data de pagamento da ordem */ + data_pagamento: Date; + + /** Nome cadastro.consorcios */ + id_consorcio: string; + + /** Nome do consórcio */ + consorcio: string; + + /** Identificador da operadora na tabela cadastro.operadoras */ + id_operadora: string; + + /** Nome da operadora */ + operadora: string; + + /** Nome curto da linha operada com variação de serviço (ex: 010, 011SN, ...) */ + servico: string; + + /** Identificador da ordem pagamento no banco de dados da Jaé */ + id_ordem_pagamento: string; + + /** Identificador da ordem ressarcimento no banco de dados da Jaé */ + id_ordem_ressarcimento: string; + + /** Quantidade de transações feitas na modalidade débito */ + quantidade_transacao_debito: number; + + /** Valor total das transações feitas na modalidade débito (R$) */ + valor_debito: number; + + /** Quantidade de transações feitas em espécie */ + quantidade_transacao_especie: number; + + /** Valor total das transações feitas em espécie (R$) */ + valor_especie: number; + + /** Quantidade de transações feitas com gratuidade */ + quantidade_transacao_gratuidade: number; + + /** Valor total das transações feitas com gratuidade (R$) */ + valor_gratuidade: number; + + /** Quantidade de transações feitas com integração */ + quantidade_transacao_integracao: number; + + /** Valor total das transações feitas com integração (R$) */ + valor_integracao: number; + + /** Número de transações com rateio de crédito */ + quantidade_transacao_rateio_credito: number; + + /** Valor total das transações com rateio de crédito (R$) */ + valor_rateio_credito: number; + + /** Número de transações com rateio de débito */ + quantidade_transacao_rateio_debito: number; + + /** Valor total das transações com rateio de débito (R$) */ + valor_rateio_debito: number; + + /** Quantidade total de transações realizadas */ + quantidade_total_transacao: number; + + /** Valor total das transações realizadas (R$) */ + valor_total_transacao_bruto: number; + + /** Valor da taxa descontado do valor total (R$) */ + valor_desconto_taxa: number; + + /** Valor total das transações menos o valor_desconto_taxa (R$) */ + valor_total_transacao_liquido: number; + + /** Quantidade total de transações calculada pela captura de transações */ + quantidade_total_transacao_captura: number; + + /** Valor total das transações realizadas calculada pela captura de transações (R$) */ + valor_total_transacao_captura: number; + + /** Indicador de validação da ordem de pagamento */ + indicador_ordem_valida: boolean; + + /** Código de controle de versão do dado (SHA Github) */ + versao: string; + + aux_nextFriday: Date; +} diff --git a/src/bigquery/entities/transacao.bq-entity.ts b/src/bigquery/entities/transacao.bigquery-entity.ts similarity index 69% rename from src/bigquery/entities/transacao.bq-entity.ts rename to src/bigquery/entities/transacao.bigquery-entity.ts index d04e7ba4..6c605902 100644 --- a/src/bigquery/entities/transacao.bq-entity.ts +++ b/src/bigquery/entities/transacao.bigquery-entity.ts @@ -1,14 +1,16 @@ -export class BqTransacao { +export class BigqueryTransacao { id: number; - data: Date; + data: string; hora: number; - datetime_transacao: Date; - datetime_processamento: Date; - datetime_captura: Date; + datetime_transacao: string; + datetime_processamento: string; + datetime_captura: string; modo: string; id_consorcio: string; + /** Nome do consórcio */ consorcio: string; id_operadora: string; + /** Nome da operadora */ operadora: string; servico: string; sentido: string; @@ -27,4 +29,6 @@ export class BqTransacao { stop_lon: number; valor_transacao: number; versao: string; + + aux_nextFriday: string; } diff --git a/src/bigquery/interfaces/bq-find-transacao-by.interface.ts b/src/bigquery/interfaces/bq-find-transacao-by.interface.ts index d217e4da..581588a3 100644 --- a/src/bigquery/interfaces/bq-find-transacao-by.interface.ts +++ b/src/bigquery/interfaces/bq-find-transacao-by.interface.ts @@ -5,5 +5,5 @@ export interface IBqFetchTransacao { limit?: number; offset?: number; getToday?: boolean; - previousDays?: boolean; + previousDaysOnly?: boolean; } diff --git a/src/bigquery/interfaces/bq-get-week-transacao-by.interface.ts b/src/bigquery/interfaces/bq-get-week-transacao-by.interface.ts new file mode 100644 index 00000000..da50929e --- /dev/null +++ b/src/bigquery/interfaces/bq-get-week-transacao-by.interface.ts @@ -0,0 +1,3 @@ +export interface IBqGetWeekTransacao { + cpfCnpj: string; +} diff --git a/src/bigquery/repositories/bigquery-ordem-pagamento.repository.ts b/src/bigquery/repositories/bigquery-ordem-pagamento.repository.ts new file mode 100644 index 00000000..f76e0534 --- /dev/null +++ b/src/bigquery/repositories/bigquery-ordem-pagamento.repository.ts @@ -0,0 +1,229 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { appSettings } from 'src/settings/app.settings'; +import { BigqueryEnvironment } from 'src/settings/enums/bigquery-env.enum'; +import { SettingsService } from 'src/settings/settings.service'; +import { isCpfOrCnpj } from 'src/utils/cpf-cnpj'; +import { QueryBuilder } from 'src/utils/query-builder/query-builder'; +import { BQSInstances, BigqueryService } from '../bigquery.service'; +import { BigqueryOrdemPagamento } from '../entities/ordem-pagamento.bigquery-entity'; +import { IBqFetchTransacao } from '../interfaces/bq-find-transacao-by.interface'; + +@Injectable() +export class BigqueryOrdemPagamentoRepository { + private logger: Logger = new Logger('BigqueryOrdemPagamentoRepository', { + timestamp: true, + }); + + constructor( + private readonly bigqueryService: BigqueryService, + private readonly settingsService: SettingsService, + ) {} + + public async findTransacaoBy( + filter?: IBqFetchTransacao, + ): Promise { + const transacoes: BigqueryOrdemPagamento[] = ( + await this.fetchTransacao(filter) + ).data; + return transacoes; + } + + private async fetchTransacao( + args?: IBqFetchTransacao, + ): Promise<{ data: BigqueryOrdemPagamento[]; countAll: number }> { + const qArgs = await this.getQueryArgs(args); + const query = + ` + SELECT + CAST(t.data AS STRING) AS \`data\`, + t.hora AS hora, + CAST(t.datetime_transacao AS STRING) AS datetime_transacao, + CAST(t.datetime_processamento AS STRING) AS datetime_processamento, + t.datetime_captura AS captureDateTime, + t.modo AS modo, + t.servico AS servico, + t.sentido AS sentido, + t.id_veiculo AS id_veiculo, + t.id_cliente AS id_cliente, + t.id_transacao AS id_transacao, + t.${qArgs.tTipoPgto} AS tipo_pagamento, + t.tipo_transacao AS tipo_transacao, + t.id_tipo_integracao AS id_tipo_integracao, + t.id_integracao AS id_integracao, + t.latitude AS latitude, + t.longitude AS longitude, + t.stop_id AS stop_id, + t.stop_lat AS stop_lat, + t.stop_lon AS stop_lon, + CASE WHEN t.tipo_transacao = 'Integração' THEN i.valor_transacao_total ELSE t.valor_transacao END AS valor_transacao, + t.versao AS bqDataVersion, + DATE_ADD(t.data, INTERVAL MOD(6 - EXTRACT(DAYOFWEEK FROM t.data) + 7, 7) DAY) AS aux_nextFriday, + (${qArgs.countQuery}) AS count, + 'ok' AS status + FROM \`${qArgs.transacao}\` t\n` + + qArgs.joinCpfCnpj + + '\n' + + qArgs.joinIntegracao + + '\n' + + (qArgs.qWhere.length ? `WHERE ${qArgs.qWhere}\n` : '') + + `UNION ALL + SELECT ${'null, '.repeat(23)} + (${qArgs.countQuery}) AS count, 'empty' AS status` + + `\nORDER BY \`data\` DESC, hora DESC` + + (qArgs?.limit !== undefined ? `\nLIMIT ${qArgs.limit + 1}` : '') + + (qArgs?.offset !== undefined ? `\nOFFSET ${qArgs.offset}` : ''); + const queryResult = await this.bigqueryService.query( + BQSInstances.smtr, + query, + ); + + const count: number = queryResult[0].count; + // Remove unwanted keys and remove last item (all null if empty) + const transacoes: BigqueryOrdemPagamento[] = queryResult.map((i) => { + delete i.status; + delete i.count; + return i; + }); + transacoes.pop(); + // transacoes = this.mapBqTransacao(transacoes); + + return { + data: transacoes, + countAll: count, + }; + } + + private async getQueryArgs(args?: IBqFetchTransacao): Promise<{ + qWhere: string; + bucket: string; + transacao: string; + integracao: string; + tTipoPgto: string; + joinCpfCnpj: string; + joinIntegracao: string; + countQuery: string; + offset?: number; + limit?: number; + }> { + const IS_BQ_PROD = + ( + await this.settingsService.getOneBySettingData( + appSettings.any__bigquery_env, + true, + ) + ).getValueAsString() === BigqueryEnvironment.Production; + const Q_CONSTS = { + bucket: IS_BQ_PROD ? 'rj-smtr' : 'rj-smtr-dev', + transacao: IS_BQ_PROD + ? 'rj-smtr.br_rj_riodejaneiro_bilhetagem.transacao' + : 'rj-smtr-dev.br_rj_riodejaneiro_bilhetagem_cct.transacao', + integracao: IS_BQ_PROD + ? 'rj-smtr.br_rj_riodejaneiro_bilhetagem.integracao' + : 'rj-smtr-dev.br_rj_riodejaneiro_bilhetagem_cct.integracao', + tTipoPgto: IS_BQ_PROD ? 'tipo_pagamento' : 'id_tipo_pagamento', + }; + // Args + let offset = args?.offset; + const queryBuilder = new QueryBuilder(); + queryBuilder.pushOR([]); + if (args?.offset !== undefined && args.limit === undefined) { + this.logger.warn( + "fetchTicketRevenues(): 'offset' is defined but 'limit' is not." + + " 'offset' will be ignored to prevent query fail", + ); + offset = undefined; + } + + if (args?.startDate) { + const startDate = args.startDate.toISOString().slice(0, 10); + queryBuilder.pushAND( + `DATE(t.datetime_processamento) >= DATE('${startDate}')`, + ); + } + if (args?.endDate) { + const endDate = args.endDate.toISOString().slice(0, 10); + queryBuilder.pushAND( + `DATE(t.datetime_processamento) <= DATE('${endDate}')`, + ); + } + if (args?.previousDaysOnly === true) { + queryBuilder.pushAND( + 'DATE(t.datetime_processamento) > DATE(t.datetime_transacao)', + ); + } + + queryBuilder.pushOR([]); + if (args?.getToday) { + const nowStr = new Date(Date.now()).toISOString().slice(0, 10); + queryBuilder.pushAND( + `DATE(t.datetime_processamento) = DATE('${nowStr}')`, + ); + } + + let qWhere = queryBuilder.toSQL(); + if (args?.cpfCnpj !== undefined) { + const cpfCnpj = args.cpfCnpj; + qWhere = + isCpfOrCnpj(args?.cpfCnpj) === 'cpf' + ? `b.documento = '${cpfCnpj}' AND (${qWhere})` + : `b.cnpj = '${cpfCnpj}' AND (${qWhere})`; + } + + // Query + const joinCpfCnpj = + isCpfOrCnpj(args?.cpfCnpj) === 'cpf' + ? `LEFT JOIN \`${Q_CONSTS.bucket}.cadastro.operadoras\` b ON b.id_operadora = t.id_operadora ` + : `LEFT JOIN \`${Q_CONSTS.bucket}.cadastro.consorcios\` b ON b.id_consorcio = t.id_consorcio `; + const joinIntegracao = `INNER JOIN ${Q_CONSTS.integracao} i ON i.id_transacao = t.id_transacao`; + + const countQuery = + 'SELECT COUNT(*) AS count ' + + `FROM \`${Q_CONSTS.transacao}\` t\n` + + joinCpfCnpj + + '\n' + + joinIntegracao + + '\n' + + (qWhere.length ? ` WHERE ${qWhere}\n` : ''); + return { + qWhere, + bucket: Q_CONSTS.bucket, + transacao: Q_CONSTS.transacao, + integracao: Q_CONSTS.integracao, + tTipoPgto: Q_CONSTS.tTipoPgto, + joinCpfCnpj, + joinIntegracao, + countQuery, + offset, + limit: args?.limit, + }; + } + + /** + * Convert id or some values into desired string values + */ + // private mapBqTransacao( + // transacoes: BigqueryOrdemPagamento[], + // ): BigqueryOrdemPagamento[] { + // return transacoes.map((item: BigqueryOrdemPagamento) => { + // const tipo_transacao = item.tipo_transacao; + // const tipo_pagamento = item.tipo_pagamento; + // const tipo_integracao = item.tipo_integracao; + // Object.values(TRIntegrationTypeMap[0]); + // return { + // ...item, + // paymentMediaType: + // tipo_pagamento !== null + // ? BqTransacaoTipoPagamentoMap?.[tipo_pagamento] || tipo_pagamento + // : tipo_pagamento, + // transportIntegrationType: + // tipo_integracao !== null + // ? BqTsansacaoTipoIntegracaoMap?.[tipo_integracao] || tipo_integracao + // : tipo_integracao, + // transactionType: + // tipo_transacao !== null + // ? BqTransacaoTipoTransacaoMap?.[tipo_transacao] || tipo_transacao + // : tipo_transacao, + // }; + // }); + // } +} diff --git a/src/bigquery/repositories/bigquery-transacao.repository.spec.ts b/src/bigquery/repositories/bigquery-transacao.repository.spec.ts new file mode 100644 index 00000000..4532f547 --- /dev/null +++ b/src/bigquery/repositories/bigquery-transacao.repository.spec.ts @@ -0,0 +1,89 @@ +import { Provider } from '@nestjs/common'; +import { Test, TestingModule } from '@nestjs/testing'; +import { BigqueryService } from 'src/bigquery/bigquery.service'; +import { SettingsService } from 'src/settings/settings.service'; +import { BigqueryTransacaoRepository } from './bigquery-transacao.repository'; +import { ConfigService } from '@nestjs/config'; +import { resolve } from 'path'; +import { config } from 'dotenv'; +import { BigqueryEnvironment } from 'src/settings/enums/bigquery-env.enum'; +import { SettingEntity } from 'src/settings/entities/setting.entity'; + +describe('BigqueryTransacaoRepositoryService', () => { + let settingsService: SettingsService; + let bqTransacaoRepository: BigqueryTransacaoRepository; + const mockBqGoogleCredentials = () => ({ + 'google.clientApiType': process.env.GOOGLE_CLIENT_API_TYPE, + 'google.clientApiProjectId': process.env.GOOGLE_CLIENT_API_PROJECT_ID, + 'google.clientApiPrivateKeyId': + process.env.GOOGLE_CLIENT_API_PRIVATE_KEY_ID, + 'google.clientApiPrivateKey': process.env.GOOGLE_CLIENT_API_PRIVATE_KEY, + 'google.clientApiClientEmail': process.env.GOOGLE_CLIENT_API_CLIENT_EMAIL, + 'google.clientApiClientId': process.env.GOOGLE_CLIENT_API_CLIENT_ID, + 'google.clientApiAuthUri': process.env.GOOGLE_CLIENT_API_AUTH_URI, + 'google.clientApiTokenUri': process.env.GOOGLE_CLIENT_API_TOKEN_URI, + 'google.clientApiAuthProviderX509CertUrl': + process.env.GOOGLE_CLIENT_API_AUTH_PROVIDER_X509_CERT_URL, + 'google.clientApiClientX509CertUrl': + process.env.GOOGLE_CLIENT_API_CLIENT_X509_CERT_URL, + 'google.clientApiUniverseDomain': + process.env.GOOGLE_CLIENT_API_UNIVERSE_DOMAIN, + }); + + beforeAll(() => { + const envPath = resolve(__dirname, '../../../.env'); + config({ path: envPath }); + }); + + beforeEach(async () => { + const settingsServiceMock = { + provide: SettingsService, + useValue: { + getOneBySettingData: jest.fn(), + }, + } as Provider; + const configServiceMock = { + provide: ConfigService, + useValue: { + getOrThrow: jest.fn((key: string) => mockBqGoogleCredentials()[key]), + }, + } as Provider; + const module: TestingModule = await Test.createTestingModule({ + providers: [ + BigqueryService, + BigqueryTransacaoRepository, + settingsServiceMock, + configServiceMock, + ], + }).compile(); + + settingsService = module.get(SettingsService); + bqTransacaoRepository = module.get(BigqueryTransacaoRepository); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should be defined', () => { + expect(settingsService).toBeDefined(); + }); + + describe('findTransacaoBy', () => { + it('should return some data', async () => { + // Arrange + jest.spyOn(settingsService, 'getOneBySettingData').mockResolvedValueOnce({ + getValueAsString: () => BigqueryEnvironment.Development, + } as SettingEntity); + + // Act + const result = await bqTransacaoRepository.findTransacaoBy({ + startDate: new Date('2023-06-01'), + endDate: new Date('2024-06-01'), + }); + + // Assert + expect(result.length).toBeGreaterThan(0); + }); + }); +}); diff --git a/src/bigquery/repositories/bq-transacao.repository.service.ts b/src/bigquery/repositories/bigquery-transacao.repository.ts similarity index 88% rename from src/bigquery/repositories/bq-transacao.repository.service.ts rename to src/bigquery/repositories/bigquery-transacao.repository.ts index 14da7edd..040ad49f 100644 --- a/src/bigquery/repositories/bq-transacao.repository.service.ts +++ b/src/bigquery/repositories/bigquery-transacao.repository.ts @@ -1,20 +1,20 @@ import { Injectable, Logger } from '@nestjs/common'; -import { BQSInstances, BigqueryService } from '../bigquery.service'; -import { BqTransacao } from '../entities/transacao.bq-entity'; -import { IBqFetchTransacao } from '../interfaces/bq-find-transacao-by.interface'; -import { SettingsService } from 'src/settings/settings.service'; import { appSettings } from 'src/settings/app.settings'; import { BigqueryEnvironment } from 'src/settings/enums/bigquery-env.enum'; -import { QueryBuilder } from 'src/utils/query-builder/query-builder'; -import { isCpfOrCnpj } from 'src/utils/cpf-cnpj'; +import { SettingsService } from 'src/settings/settings.service'; import { TRIntegrationTypeMap } from 'src/ticket-revenues/maps/ticket-revenues.map'; +import { isCpfOrCnpj } from 'src/utils/cpf-cnpj'; +import { QueryBuilder } from 'src/utils/query-builder/query-builder'; +import { BQSInstances, BigqueryService } from '../bigquery.service'; +import { BigqueryTransacao } from '../entities/transacao.bigquery-entity'; +import { IBqFetchTransacao } from '../interfaces/bq-find-transacao-by.interface'; import { BqTsansacaoTipoIntegracaoMap } from '../maps/bq-transacao-tipo-integracao.map'; -import { BqTransacaoTipoTransacaoMap } from '../maps/bq-transacao-tipo-transacao.map'; import { BqTransacaoTipoPagamentoMap } from '../maps/bq-transacao-tipo-pagamento.map'; +import { BqTransacaoTipoTransacaoMap } from '../maps/bq-transacao-tipo-transacao.map'; @Injectable() -export class BqTransacaoRepositoryService { - private logger: Logger = new Logger('BqTransacaoRepositoryService', { +export class BigqueryTransacaoRepository { + private logger: Logger = new Logger('BigqueryTransacaoRepository', { timestamp: true, }); @@ -25,20 +25,21 @@ export class BqTransacaoRepositoryService { public async findTransacaoBy( filter?: IBqFetchTransacao, - ): Promise { - const transacoes: BqTransacao[] = (await this.fetchTransacao(filter)).data; + ): Promise { + const transacoes: BigqueryTransacao[] = (await this.fetchTransacao(filter)) + .data; return transacoes; } private async fetchTransacao( args?: IBqFetchTransacao, - ): Promise<{ data: BqTransacao[]; countAll: number }> { + ): Promise<{ data: BigqueryTransacao[]; countAll: number }> { const qArgs = await this.getQueryArgs(args); const query = ` SELECT - CAST(t.data AS STRING) AS partitionDate, - t.hora AS processingHour, + CAST(t.data AS STRING) AS \`data\`, + t.hora AS hora, CAST(t.datetime_transacao AS STRING) AS datetime_transacao, CAST(t.datetime_processamento AS STRING) AS datetime_processamento, t.datetime_captura AS captureDateTime, @@ -59,6 +60,7 @@ export class BqTransacaoRepositoryService { t.stop_lon AS stop_lon, CASE WHEN t.tipo_transacao = 'Integração' THEN i.valor_transacao_total ELSE t.valor_transacao END AS valor_transacao, t.versao AS bqDataVersion, + CAST(DATE_ADD(t.data, INTERVAL MOD(6 - EXTRACT(DAYOFWEEK FROM t.data) + 7, 7) DAY) AS STRING) AS aux_nextFriday, (${qArgs.countQuery}) AS count, 'ok' AS status FROM \`${qArgs.transacao}\` t\n` + @@ -68,9 +70,9 @@ export class BqTransacaoRepositoryService { '\n' + (qArgs.qWhere.length ? `WHERE ${qArgs.qWhere}\n` : '') + `UNION ALL - SELECT ${'null, '.repeat(22)} + SELECT ${'null, '.repeat(23)} (${qArgs.countQuery}) AS count, 'empty' AS status` + - `\nORDER BY t.data DESC, t.hora DESC` + + `\nORDER BY \`data\` DESC, hora DESC` + (qArgs?.limit !== undefined ? `\nLIMIT ${qArgs.limit + 1}` : '') + (qArgs?.offset !== undefined ? `\nOFFSET ${qArgs.offset}` : ''); const queryResult = await this.bigqueryService.query( @@ -80,7 +82,7 @@ export class BqTransacaoRepositoryService { const count: number = queryResult[0].count; // Remove unwanted keys and remove last item (all null if empty) - let transacoes: BqTransacao[] = queryResult.map((i) => { + let transacoes: BigqueryTransacao[] = queryResult.map((i) => { delete i.status; delete i.count; return i; @@ -147,7 +149,7 @@ export class BqTransacaoRepositoryService { `DATE(t.datetime_processamento) <= DATE('${endDate}')`, ); } - if (args?.previousDays === true) { + if (args?.previousDaysOnly === true) { queryBuilder.pushAND( 'DATE(t.datetime_processamento) > DATE(t.datetime_transacao)', ); @@ -202,8 +204,8 @@ export class BqTransacaoRepositoryService { /** * Convert id or some values into desired string values */ - private mapBqTransacao(transacoes: BqTransacao[]): BqTransacao[] { - return transacoes.map((item: BqTransacao) => { + private mapBqTransacao(transacoes: BigqueryTransacao[]): BigqueryTransacao[] { + return transacoes.map((item: BigqueryTransacao) => { const tipo_transacao = item.tipo_transacao; const tipo_pagamento = item.tipo_pagamento; const tipo_integracao = item.tipo_integracao; diff --git a/src/bigquery/services/bigquery-transacao.service.ts b/src/bigquery/services/bigquery-transacao.service.ts new file mode 100644 index 00000000..cd80bbd6 --- /dev/null +++ b/src/bigquery/services/bigquery-transacao.service.ts @@ -0,0 +1,27 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { nextFriday } from 'date-fns'; +import { getPaymentWeek } from 'src/utils/payment-date-utils'; +import { BigqueryTransacao } from '../entities/transacao.bigquery-entity'; +import { BigqueryTransacaoRepository } from '../repositories/bigquery-transacao.repository'; + +@Injectable() +export class BigqueryTransacaoService { + private logger: Logger = new Logger('BigqueryTransacaoService', { + timestamp: true, + }); + + constructor( + private readonly bigqueryTransacaoRepository: BigqueryTransacaoRepository, + ) {} + + /** + * Get data from current payment week (from thu to wed) + */ + public async getTransacaoOfCurrentWeek(): Promise { + const paymentWeek = getPaymentWeek(nextFriday(new Date())); + return this.bigqueryTransacaoRepository.findTransacaoBy({ + startDate: paymentWeek.startDate, + endDate: paymentWeek.endDate, + }); + } +} diff --git a/src/cnab/dto/header-arquivo.dto.ts b/src/cnab/dto/header-arquivo.dto.ts index fe8838b5..0c19ee83 100644 --- a/src/cnab/dto/header-arquivo.dto.ts +++ b/src/cnab/dto/header-arquivo.dto.ts @@ -12,8 +12,7 @@ export class HeaderArquivoDTO{ num_conta :string; dv_conta:string; nome_empresa:string; - dt_geracao: Date; - @Column({ arg0: { type: 'timestamp' } }) + dt_geracao: Date; hr_geracao: Date; id_transacao:number; } \ No newline at end of file diff --git a/src/cnab/dto/item-transacao.dto.ts b/src/cnab/dto/item-transacao.dto.ts new file mode 100644 index 00000000..4f163ff7 --- /dev/null +++ b/src/cnab/dto/item-transacao.dto.ts @@ -0,0 +1,13 @@ +export class ItemTransacaoDTO{ + id_item_transacao: number; + dt_transacao: Date; + dt_processamento; + dt_captura; + modo: string; + nome_consorcio: string; + id_tipo_pagamento: number; + tipo_transacao: string; + valor_item_transacao: number; + id_transacao: number; + id_cliente_favorecido:number; +} \ No newline at end of file diff --git a/src/cnab/dto/save-cliente-favorecido.dto.ts b/src/cnab/dto/save-cliente-favorecido.dto.ts new file mode 100644 index 00000000..2ec7c2c1 --- /dev/null +++ b/src/cnab/dto/save-cliente-favorecido.dto.ts @@ -0,0 +1,69 @@ +import { IsNotEmpty, ValidateIf } from 'class-validator'; + +function isCreate(object: SaveClienteFavorecidoDTO): boolean { + return object.id_cliente_favorecido === undefined; +} + +export class SaveClienteFavorecidoDTO { + id_cliente_favorecido?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + nome?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + cpf_cnpj?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + cod_banco?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + agencia?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + dv_agencia?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + conta_corrente?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + dv_conta_corrente?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + logradouro?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + numero?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + complemento?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + bairro?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + cidade?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + cep?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + complemento_cep?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + uf?: string; +} diff --git a/src/cnab/dto/save-detalhe-a.dto.ts b/src/cnab/dto/save-detalhe-a.dto.ts new file mode 100644 index 00000000..6303e298 --- /dev/null +++ b/src/cnab/dto/save-detalhe-a.dto.ts @@ -0,0 +1,73 @@ +import { IsNotEmpty, ValidateIf } from 'class-validator'; + +function isCreate(object: SaveDetalheADTO): boolean { + return object.id_detalhe_a === undefined; +} + +export class SaveDetalheADTO { + id_detalhe_a?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + id_header_lote?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + lote_servico?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + id_cliente_favorecido?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + tipo_finalidade_conta?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + dt_vencimento?: Date; + + @ValidateIf(isCreate) + @IsNotEmpty() + tipo_moeda?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + qtde_moeda?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + valor_lancamento?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + num_doc_lancamento?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + qtde_parcelas?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + indicador_bloqueio?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + indicador_forma_parcelamento?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + periodo_vencimento?: Date; + + @ValidateIf(isCreate) + @IsNotEmpty() + num_parcela?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + data_efetivacao?: Date; + + @ValidateIf(isCreate) + @IsNotEmpty() + valor_real_efetivado?: number; +} diff --git a/src/cnab/dto/save-detalhe-b.dto.ts b/src/cnab/dto/save-detalhe-b.dto.ts new file mode 100644 index 00000000..55c97c6b --- /dev/null +++ b/src/cnab/dto/save-detalhe-b.dto.ts @@ -0,0 +1,21 @@ +import { IsNotEmpty, ValidateIf } from 'class-validator'; + +function isCreate(object: SaveDetalheBDTO): boolean { + return object.id_detalhe_a === undefined; +} + +export class SaveDetalheBDTO { + id_detalhe_b?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + id_detalhe_a?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + nsr?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + data_vencimento?: Date; +} diff --git a/src/cnab/dto/save-pagador.dto.ts b/src/cnab/dto/save-pagador.dto.ts new file mode 100644 index 00000000..bda1a8dc --- /dev/null +++ b/src/cnab/dto/save-pagador.dto.ts @@ -0,0 +1,61 @@ +import { IsNotEmpty, ValidateIf } from 'class-validator'; + +function isCreate(object: SavePagadorDTO): boolean { + return object.id_pagador === undefined; +} + +export class SavePagadorDTO { + id_pagador?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + nome_empresa: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + agencia: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + dv_agencia: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + conta: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + dv_conta: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + logradouro: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + numero: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + complemento: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + bairro: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + cidade: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + cep: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + complemento_cep: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + uf: string; +} diff --git a/src/cnab/dto/save-transacao-cliente-item.dto.ts b/src/cnab/dto/save-transacao-cliente-item.dto.ts new file mode 100644 index 00000000..e5c940d9 --- /dev/null +++ b/src/cnab/dto/save-transacao-cliente-item.dto.ts @@ -0,0 +1,17 @@ +import { IsNotEmpty, ValidateIf } from 'class-validator'; + +function isCreate(object: SaveTransacaoClienteItemDTO): boolean { + return object.id === undefined; +} + +export class SaveTransacaoClienteItemDTO { + id?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + id_item_transacao?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + id_cliente_favorecido?: number; +} diff --git a/src/cnab/dto/save-transacao.dto.ts b/src/cnab/dto/save-transacao.dto.ts new file mode 100644 index 00000000..9c03213a --- /dev/null +++ b/src/cnab/dto/save-transacao.dto.ts @@ -0,0 +1,80 @@ +import { IsNotEmpty, ValidateIf } from 'class-validator'; + +function isCreate(object: SaveTransacaoDTO): boolean { + return object.id_transacao === undefined; +} + +export class SaveTransacaoDTO { + id_transacao?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + dt_ordem?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + dt_pagamento?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + nome_consorcio?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + nome_operadora?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + servico?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + id_ordem_ressarcimento?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + qtde_transacao_rateio_credito?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + vlr_rateio_credito?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + qtde_transacao_rateio_debito?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + vlr_rateio_debito?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + quantidade_total_transacao?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + vlr_total_transacao_bruto?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + vlr_desconto_taxa?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + vlr_total_transacao_liquido?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + qtde_total_transacao_captura?: number; + + @ValidateIf(isCreate) + @IsNotEmpty() + vlr_total_transacao_captura?: number; + + @ValidateIf(isCreate) + indicador_ordem_valida?: string; + + @ValidateIf(isCreate) + @IsNotEmpty() + id_pagador?: number; +} diff --git a/src/cnab/entity/cliente-favorecido.entity.ts b/src/cnab/entity/cliente-favorecido.entity.ts index 2a19d9d8..8dc2b7ce 100644 --- a/src/cnab/entity/cliente-favorecido.entity.ts +++ b/src/cnab/entity/cliente-favorecido.entity.ts @@ -59,4 +59,12 @@ export class ClienteFavorecido extends EntityHelper { @Column({ type: String, unique: false, nullable: true, length: 2 }) uf: string; + + public getLogInfo(showName?: boolean): string { + if (showName === undefined) { + showName = false; + } + const response = `#${this.cpf_cnpj}` + showName ? ` '${this.nome}'` : ''; + return response; + } } diff --git a/src/cnab/entity/detalhe-a.entity.ts b/src/cnab/entity/detalhe-a.entity.ts index 09b230a8..190f849c 100644 --- a/src/cnab/entity/detalhe-a.entity.ts +++ b/src/cnab/entity/detalhe-a.entity.ts @@ -16,9 +16,7 @@ export class DetalheA extends EntityHelper{ @Column({ type: Date, unique: false, nullable: true }) dt_vencimento: Date; @Column({ type: String, unique: false, nullable: true }) - tipo_moeda :string; - @Column({ type: String, unique: false, nullable: true }) - qtde_moeda :number; + tipo_moeda :string; @Column({ type: String, unique: false, nullable: true }) valor_lancamento: number; @Column({ type: String, unique: false, nullable: true }) @@ -36,7 +34,5 @@ export class DetalheA extends EntityHelper{ @Column({ type: Date, unique: false, nullable: true }) data_efetivacao: Date; @Column({ type: Number, unique: false, nullable: true }) - valor_real_efetivado:number -} - - + valor_real_efetivado:number; +} \ No newline at end of file diff --git a/src/cnab/entity/detalhe-b.entiy.ts b/src/cnab/entity/detalhe-b.entiy.ts index b1f4f6cd..ce4c558f 100644 --- a/src/cnab/entity/detalhe-b.entiy.ts +++ b/src/cnab/entity/detalhe-b.entiy.ts @@ -1,14 +1,22 @@ -import { EntityHelper } from "src/utils/entity-helper"; -import { Column, Entity , PrimaryGeneratedColumn} from 'typeorm'; - -@Entity() -export class DetalheB extends EntityHelper{ - @PrimaryGeneratedColumn() - id_detalhe_b:number; - @Column({ type: Number, unique: false, nullable: true }) - id_detalhe_a :number; - @Column({ type: String, unique: false, nullable: true }) - nsr:string; - @Column({ type: Date, unique: false, nullable: true }) - data_vencimento: Date; +import { EntityHelper } from 'src/utils/entity-helper'; +import { DeepPartial, Entity } from 'typeorm'; + +@Entity() +export class DetalheB extends EntityHelper { + constructor(detalheB?: DetalheB | DeepPartial) { + super(); + if (detalheB !== undefined) { + Object.assign(this, detalheB); + } + } + + id_detalhe_b: number; + id_detalhe_a: number; + nsr: string; + data_vencimento: Date; + + public getLogInfo(): string { + const response = `#${this.id_detalhe_b}`; + return response; + } } \ No newline at end of file diff --git a/src/cnab/entity/header-arquivo.entity.ts b/src/cnab/entity/header-arquivo.entity.ts index 847bb0f6..abea8f8b 100644 --- a/src/cnab/entity/header-arquivo.entity.ts +++ b/src/cnab/entity/header-arquivo.entity.ts @@ -33,6 +33,4 @@ export class HeaderArquivo extends EntityHelper{ hr_geracao: Date; @Column({ type: Number, unique: false, nullable: true }) id_transacao:number; -} - - +} \ No newline at end of file diff --git a/src/cnab/entity/header-lote.entity.ts b/src/cnab/entity/header-lote.entity.ts index 7ecbadc5..db1743d7 100644 --- a/src/cnab/entity/header-lote.entity.ts +++ b/src/cnab/entity/header-lote.entity.ts @@ -21,4 +21,4 @@ export class HeaderLote extends EntityHelper{ param_transmissao:string; @Column({ type: Number, unique: false, nullable: true }) id_pagadora:number; -} \ No newline at end of file +} diff --git a/src/cnab/entity/item-transacao.entity.ts b/src/cnab/entity/item-transacao.entity.ts index a3049c23..39f794ea 100644 --- a/src/cnab/entity/item-transacao.entity.ts +++ b/src/cnab/entity/item-transacao.entity.ts @@ -1,20 +1,22 @@ -import { EntityHelper } from "src/utils/entity-helper"; - - -@Entity() -class ItemTransacao extends EntityHelper{ - id_item_transacao:number; - dt_transacao: Date; - dt_processamentoDate; - dt_capturaDate; - modo:string; - nome_consorcio:string; - id_tipo_pagamento:number; - tipo_transacao:string; - valor_item_transacao:number; - id_transacao:number; -} - -function Entity(): (target: typeof ItemTransacao) => void | typeof ItemTransacao { - throw new Error("Function not implemented."); -} +import { EntityHelper } from 'src/utils/entity-helper'; + +@Entity() +export class ItemTransacao extends EntityHelper { + id_item_transacao: number; + dt_transacao: Date; + dt_processamento; + dt_captura; + modo: string; + nome_consorcio: string; + id_tipo_pagamento: number; + tipo_transacao: string; + valor_item_transacao: number; + id_cliente_favorecido: number; + id_transacao: number; +} + +function Entity(): ( + target: typeof ItemTransacao, +) => void | typeof ItemTransacao { + throw new Error('Function not implemented.'); +} diff --git a/src/cnab/entity/pagador.entity.ts b/src/cnab/entity/pagador.entity.ts index bdb8d4ed..3d6b7e20 100644 --- a/src/cnab/entity/pagador.entity.ts +++ b/src/cnab/entity/pagador.entity.ts @@ -51,4 +51,10 @@ export class Pagador extends EntityHelper { @Column({ type: String, unique: false, nullable: true, length: 2 }) uf: string; + + public getLogInfo(): string { + const response = + `#${this.id_pagador}` + ` '${this.nome_empresa.substring(0, 15)}...'`; + return response; + } } diff --git a/src/cnab/entity/transacao-cliente-item.entity.ts b/src/cnab/entity/transacao-cliente-item.entity.ts index f3ff2f8e..e349187b 100644 --- a/src/cnab/entity/transacao-cliente-item.entity.ts +++ b/src/cnab/entity/transacao-cliente-item.entity.ts @@ -1,10 +1,30 @@ -import { EntityHelper } from '../../utils/entity-helper'; -@Entity() -class TransacaoClienteItem extends EntityHelper{ - id_item_transacao:number; - id_cliente_favorecido:number; -} - -function Entity(): (target: typeof TransacaoClienteItem) => void | typeof TransacaoClienteItem { - throw new Error('Function not implemented.'); -} \ No newline at end of file +import { EntityHelper } from 'src/utils/entity-helper'; +import { Column, DeepPartial, Entity, PrimaryGeneratedColumn } from 'typeorm'; + +@Entity() +export class TransacaoClienteItem extends EntityHelper { + constructor( + entity?: TransacaoClienteItem | DeepPartial, + ) { + super(); + if (entity !== undefined) { + Object.assign(this, entity); + } + } + + @PrimaryGeneratedColumn() + id?: number; + + @Column({ type: Number, unique: false, nullable: true, length: 150 }) + id_item_transacao: number; + + @Column({ type: Number, unique: false, nullable: true, length: 150 }) + id_cliente_favorecido: number; + + public getLogInfo(): string { + const response = + `#${this.id}` + `, itemTransacao: '${this.id_item_transacao}'`; + +`, clienteFavorecido: '${this.id_cliente_favorecido}'`; + return response; + } +} diff --git a/src/cnab/entity/transacao.entity.ts b/src/cnab/entity/transacao.entity.ts index 9382cb10..c146995e 100644 --- a/src/cnab/entity/transacao.entity.ts +++ b/src/cnab/entity/transacao.entity.ts @@ -13,11 +13,11 @@ export class Transacao extends EntityHelper { @PrimaryGeneratedColumn() id_transacao: number; - @Column({ type: String, unique: false, nullable: true }) - dt_ordem: string; + @Column({ type: Date, unique: false, nullable: true }) + dt_ordem: Date; - @Column({ type: String, unique: false, nullable: true }) - dt_pagamento: string; + @Column({ type: Date, unique: false, nullable: true }) + dt_pagamento: Date; @Column({ type: String, unique: false, nullable: true, length: 200 }) nome_consorcio: string; @@ -102,4 +102,9 @@ export class Transacao extends EntityHelper { @Column({ type: Number, unique: false, nullable: true }) id_pagador: number; + + public getLogInfo(): string { + const response = `#${this.id_transacao}`; + return response; + } } diff --git a/src/cnab/enums/pagador/pagador.enum.ts b/src/cnab/enums/pagador/pagador.enum.ts new file mode 100644 index 00000000..c12b645d --- /dev/null +++ b/src/cnab/enums/pagador/pagador.enum.ts @@ -0,0 +1,4 @@ +export enum PagadorContaEnum { + JAE = '1', + FASE_4 = '2', +} diff --git a/src/cnab/interfaces/cnab-field-map-detalhe.interface.ts b/src/cnab/interfaces/cnab-all/cnab-field-map-detalhe.interface.ts similarity index 100% rename from src/cnab/interfaces/cnab-field-map-detalhe.interface.ts rename to src/cnab/interfaces/cnab-all/cnab-field-map-detalhe.interface.ts diff --git a/src/cnab/interfaces/cnab-field-map-trailer-arquivo.interface.ts b/src/cnab/interfaces/cnab-all/cnab-field-map-trailer-arquivo.interface.ts similarity index 100% rename from src/cnab/interfaces/cnab-field-map-trailer-arquivo.interface.ts rename to src/cnab/interfaces/cnab-all/cnab-field-map-trailer-arquivo.interface.ts diff --git a/src/cnab/interfaces/cnab-field-map-trailer-lote.interface.ts b/src/cnab/interfaces/cnab-all/cnab-field-map-trailer-lote.interface.ts similarity index 100% rename from src/cnab/interfaces/cnab-field-map-trailer-lote.interface.ts rename to src/cnab/interfaces/cnab-all/cnab-field-map-trailer-lote.interface.ts diff --git a/src/cnab/interfaces/cnab-field-map.interface.ts b/src/cnab/interfaces/cnab-all/cnab-field-map.interface.ts similarity index 100% rename from src/cnab/interfaces/cnab-field-map.interface.ts rename to src/cnab/interfaces/cnab-all/cnab-field-map.interface.ts diff --git a/src/cnab/listener/transacao.listener.ts b/src/cnab/listener/transacao.listener.ts index fb2d6fab..56d6261a 100644 --- a/src/cnab/listener/transacao.listener.ts +++ b/src/cnab/listener/transacao.listener.ts @@ -1,10 +1,10 @@ -class TransacaoListener{ - - private transacaoService:TransacaoService; - - //rodar as 09:00 e as 14:00 - function JobTransaction(){ - transacaoService.insereTransacoes(); - } - -} \ No newline at end of file +// class TransacaoListener{ + +// private transacaoService:TransacaoService; + +// //rodar as 09:00 e as 14:00 +// function JobTransaction(){ +// transacaoService.insereTransacoes(); +// } + +// } diff --git a/src/cnab/repository/cliente-favorecido.repository.ts b/src/cnab/repository/cliente-favorecido.repository.ts index c6902bd7..1850473b 100644 --- a/src/cnab/repository/cliente-favorecido.repository.ts +++ b/src/cnab/repository/cliente-favorecido.repository.ts @@ -1 +1,75 @@ -//metodo de insert cliente favorecido +import { Injectable, Logger } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { EntityCondition } from 'src/utils/types/entity-condition.type'; +import { NullableType } from 'src/utils/types/nullable.type'; +import { Repository, UpdateResult } from 'typeorm'; +import { SaveClienteFavorecidoDTO } from '../dto/save-cliente-favorecido.dto'; +import { ClienteFavorecido } from '../entity/cliente-favorecido.entity'; + +@Injectable() +export class ClienteFavorecidoRepository { + private logger: Logger = new Logger('ClienteFavorecidoRepository', { + timestamp: true, + }); + + constructor( + @InjectRepository(ClienteFavorecido) + private clienteFavorecidoRepository: Repository, + ) {} + + async save(dto: SaveClienteFavorecidoDTO): Promise { + if (dto.id_cliente_favorecido === undefined) { + await this.create(dto); + } else { + await this.update(dto.id_cliente_favorecido, dto); + } + } + + async create( + createProfileDto: SaveClienteFavorecidoDTO, + ): Promise { + const createdUser = await this.clienteFavorecidoRepository.save( + this.clienteFavorecidoRepository.create(createProfileDto), + ); + this.logger.log(`ClienteFavorecido criado: ${createdUser.getLogInfo()}`); + return createdUser; + } + + async update( + id: number, + updateDto: SaveClienteFavorecidoDTO, + ): Promise { + const updatePayload = await this.clienteFavorecidoRepository.update( + { id_cliente_favorecido: id }, + updateDto, + ); + const updatedItem = new ClienteFavorecido({ + id_cliente_favorecido: id, + ...updateDto, + }); + this.logger.log( + `ClienteFavorecido atualizado: ${updatedItem.getLogInfo()}`, + ); + return updatePayload; + } + + public async findOne( + fields: + | EntityCondition + | EntityCondition[], + ): Promise> { + return await this.clienteFavorecidoRepository.findOne({ + where: fields, + }); + } + + public async findMany( + fields: + | EntityCondition + | EntityCondition[], + ): Promise { + return await this.clienteFavorecidoRepository.find({ + where: fields, + }); + } +} diff --git a/src/cnab/repository/detalhe-a.repository.ts b/src/cnab/repository/detalhe-a.repository.ts index e5f31949..c190bc68 100644 --- a/src/cnab/repository/detalhe-a.repository.ts +++ b/src/cnab/repository/detalhe-a.repository.ts @@ -1,3 +1,4 @@ +<<<<<<< HEAD import { Injectable, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { EntityCondition } from 'src/utils/types/entity-condition.type'; @@ -39,4 +40,70 @@ export class DetalheARepository { }); } -} \ No newline at end of file +} +======= +import { Injectable, Logger } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { EntityCondition } from 'src/utils/types/entity-condition.type'; +import { NullableType } from 'src/utils/types/nullable.type'; +import { Repository, UpdateResult } from 'typeorm'; +import { SaveDetalheADTO } from '../dto/save-detalhe-a.dto'; +import { DetalheA } from '../entity/detalhe-a.entity'; + +@Injectable() +export class DetalheARepository { + private logger: Logger = new Logger('DetalheARepository', { + timestamp: true, + }); + + constructor( + @InjectRepository(DetalheA) + private DetalheARepository: Repository, + ) {} + + async save(dto: SaveDetalheADTO): Promise { + if (dto.id_detalhe_a === undefined) { + await this.create(dto); + } else { + await this.update(dto.id_detalhe_a, dto); + } + } + + async create(createProfileDto: SaveDetalheADTO): Promise { + const createdUser = await this.DetalheARepository.save( + this.DetalheARepository.create(createProfileDto), + ); + this.logger.log(`DetalheA criado: ${createdUser.getLogInfo()}`); + return createdUser; + } + + async update(id: number, updateDto: SaveDetalheADTO): Promise { + const updatePayload = await this.DetalheARepository.update( + { id_cliente_favorecido: id }, + updateDto, + ); + const updatedItem = new DetalheA({ + id_cliente_favorecido: id, + ...updateDto, + }); + this.logger.log(`DetalheA atualizado: ${updatedItem.getLogInfo()}`); + return updatePayload; + } + + public async findOne( + fields: EntityCondition | EntityCondition[], + ): Promise> { + return await this.DetalheARepository.findOne({ + where: fields, + }); + } + + public async findMany( + fields: EntityCondition | EntityCondition[], + ): Promise { + return await this.DetalheARepository.find({ + where: fields, + }); + } +} +>>>>>>> 7733f18adc3b550c8f39c3a515f35364c9082856 diff --git a/src/cnab/repository/detalhe-b.repository.ts b/src/cnab/repository/detalhe-b.repository.ts index 0a5e670a..6eed00da 100644 --- a/src/cnab/repository/detalhe-b.repository.ts +++ b/src/cnab/repository/detalhe-b.repository.ts @@ -1,42 +1,42 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { EntityCondition } from 'src/utils/types/entity-condition.type'; -import { NullableType } from 'src/utils/types/nullable.type'; -import { - Repository, - UpdateResult -} from 'typeorm'; -import { DetalheB } from '../entity/detalhe-b.entity'; -import { DetalheBDTO } from '../dto/detalhe-b.dto'; - - -@Injectable() -export class DetalheBRepository { - private logger: Logger = new Logger('DetalheBRepository', { timestamp: true }); - - constructor( - @InjectRepository(DetalheB) - private DetalheBRepository: Repository, - ) { } - - public async save(dto: DetalheBDTO): Promise { - return await this.DetalheBRepository.save(dto); - } - - public async findOne( - fields: EntityCondition | EntityCondition[], - ): Promise> { - return await this.DetalheBRepository.findOne({ - where: fields, - }); - } - - public async findMany( - fields: EntityCondition | EntityCondition[], - ): Promise { - return await this.DetalheBRepository.find({ - where: fields, - }); - } - +import { Injectable, Logger } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { EntityCondition } from 'src/utils/types/entity-condition.type'; +import { NullableType } from 'src/utils/types/nullable.type'; +import { + Repository, + UpdateResult +} from 'typeorm'; +import { DetalheB } from '../entity/detalhe-b.entity'; +import { DetalheBDTO } from '../dto/detalhe-b.dto'; + + +@Injectable() +export class DetalheBRepository { + private logger: Logger = new Logger('DetalheBRepository', { timestamp: true }); + + constructor( + @InjectRepository(DetalheB) + private DetalheBRepository: Repository, + ) { } + + public async save(dto: DetalheBDTO): Promise { + return await this.DetalheBRepository.save(dto); + } + + public async findOne( + fields: EntityCondition | EntityCondition[], + ): Promise> { + return await this.DetalheBRepository.findOne({ + where: fields, + }); + } + + public async findMany( + fields: EntityCondition | EntityCondition[], + ): Promise { + return await this.DetalheBRepository.find({ + where: fields, + }); + } + } \ No newline at end of file diff --git a/src/cnab/repository/header-arquivo.repository.ts b/src/cnab/repository/header-arquivo.repository.ts index 15613d65..c01c9feb 100644 --- a/src/cnab/repository/header-arquivo.repository.ts +++ b/src/cnab/repository/header-arquivo.repository.ts @@ -3,8 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { EntityCondition } from 'src/utils/types/entity-condition.type'; import { NullableType } from 'src/utils/types/nullable.type'; import { - Repository, - UpdateResult + Repository } from 'typeorm'; import { HeaderArquivo } from '../entity/header-arquivo.entity'; import { HeaderArquivoDTO } from '../dto/header-arquivo.dto'; @@ -12,6 +11,7 @@ import { HeaderArquivoDTO } from '../dto/header-arquivo.dto'; @Injectable() export class HeaderArquivoRepository { + [x: string]: any; private logger: Logger = new Logger('HeaderArquivoRepository', { timestamp: true }); constructor( @@ -19,7 +19,7 @@ export class HeaderArquivoRepository { private HeaderArquivoRepository: Repository, ) { } - public async save(dto: HeaderArquivoDto): Promise { + public async save(dto: HeaderArquivoDTO): Promise { return await this.HeaderArquivoRepository.save(dto); } @@ -31,12 +31,7 @@ export class HeaderArquivoRepository { }); } - public async findMany( - fields: EntityCondition | EntityCondition[], - ): Promise { - return await this.HeaderArquivoRepository.find({ - where: fields, - }); + public async findAll(): Promise { + return await this.HeaderArquivoRepository.find(); } - } \ No newline at end of file diff --git a/src/cnab/repository/item-transacao.repository.ts b/src/cnab/repository/item-transacao.repository.ts new file mode 100644 index 00000000..862f9383 --- /dev/null +++ b/src/cnab/repository/item-transacao.repository.ts @@ -0,0 +1,41 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { EntityCondition } from 'src/utils/types/entity-condition.type'; +import { NullableType } from 'src/utils/types/nullable.type'; +import { + Repository +} from 'typeorm'; +import { ItemTransacao } from '../entity/item-transacao.entity'; +import { ItemTransacaoDTO } from '../dto/item-transacao.dto'; + + +@Injectable() +export class ItemTransacaoRepository { + [x: string]: any; + private logger: Logger = new Logger('ItemTransacaoRepository', { timestamp: true }); + + constructor( + @InjectRepository(ItemTransacao) + private ItemTransacaoRepository: Repository, + ) { } + + public async save(dto: ItemTransacaoDTO): Promise { + return await this.ItemTransacaoRepository.save(dto); + } + + public async findOne( + fields: EntityCondition | EntityCondition[], + ): Promise> { + return await this.ItemTransacaoRepository.findOne({ + where: fields, + }); + } + + public async findAll( + fields: EntityCondition | EntityCondition[], + ): Promise { + return await this.ItemTransacaoRepository.find({ + where: fields, + }); + } +} \ No newline at end of file diff --git a/src/cnab/repository/pagador.repository.ts b/src/cnab/repository/pagador.repository.ts index bb361d46..7d105dbc 100644 --- a/src/cnab/repository/pagador.repository.ts +++ b/src/cnab/repository/pagador.repository.ts @@ -1,9 +1,61 @@ -class Pagador { - - - function getPagador(tipo:string):Pagador{//Saber se é fase 4 ou CCT pra pegar o pagador - //Se o tipo for CCT pagador 2 - //Senao 1 - - } -} \ No newline at end of file +import { Injectable, Logger } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { EntityCondition } from 'src/utils/types/entity-condition.type'; +import { NullableType } from 'src/utils/types/nullable.type'; +import { Repository, UpdateResult } from 'typeorm'; +import { Pagador } from '../entity/pagador.entity'; +import { SavePagadorDTO } from '../dto/save-pagador.dto'; + +@Injectable() +export class PagadorRepository { + private logger: Logger = new Logger('PagadorRepository', { timestamp: true }); + + constructor( + @InjectRepository(Pagador) + private PagadorRepository: Repository, + ) {} + + public async save(dto: SavePagadorDTO): Promise { + if (dto.id_pagador === undefined) { + await this.create(dto); + } else { + await this.update(dto.id_pagador, dto); + } + } + + public async create(createProfileDto: SavePagadorDTO): Promise { + const createdItem = await this.PagadorRepository.save( + this.PagadorRepository.create(createProfileDto), + ); + this.logger.log(`Pagador criado: ${createdItem[0].getLogInfo()}`); + return createdItem; + } + + public async update( + id: number, + updateDto: SavePagadorDTO, + ): Promise { + const updatePayload = await this.PagadorRepository.update( + { id_pagador: id }, + updateDto, + ); + const updatedItem = new Pagador({ id_pagador: id, ...updateDto }); + this.logger.log(`Pagador atualizado: ${updatedItem.getLogInfo()}`); + return updatePayload; + } + + public async findOne( + fields: EntityCondition): Promise { + return await this.PagadorRepository.findOne({ + where: fields + }); + } + + public async findMany( + fields: EntityCondition | EntityCondition[], + ): Promise { + return await this.PagadorRepository.find({ + where: fields, + }); + } +} diff --git a/src/cnab/repository/transacao-cliente-item.repository.ts b/src/cnab/repository/transacao-cliente-item.repository.ts new file mode 100644 index 00000000..7dca4d3d --- /dev/null +++ b/src/cnab/repository/transacao-cliente-item.repository.ts @@ -0,0 +1,72 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { EntityCondition } from 'src/utils/types/entity-condition.type'; +import { NullableType } from 'src/utils/types/nullable.type'; +import { Repository, UpdateResult } from 'typeorm'; +import { TransacaoClienteItem } from '../entity/transacao-cliente-item.entity'; +import { SaveTransacaoClienteItemDTO } from '../dto/save-transacao-cliente-item.dto'; + +@Injectable() +export class TransacaoClienteItemRepository { + private logger: Logger = new Logger('TransacaoClienteItemRepository', { + timestamp: true, + }); + + constructor( + @InjectRepository(TransacaoClienteItem) + private transacaoClienteItemRepository: Repository, + ) {} + + public async save(dto: SaveTransacaoClienteItemDTO): Promise { + if (dto.id === undefined) { + await this.create(dto); + } else { + await this.update(dto.id, dto); + } + } + + public async create( + createProfileDto: SaveTransacaoClienteItemDTO, + ): Promise { + const createdItem = await this.transacaoClienteItemRepository.save( + this.transacaoClienteItemRepository.create(createProfileDto), + ); + this.logger.log(`TransacaoClienteItem criado: ${createdItem.getLogInfo()}`); + return createdItem; + } + + public async update( + id: number, + updateDto: SaveTransacaoClienteItemDTO, + ): Promise { + const updatePayload = await this.transacaoClienteItemRepository.update( + { id_cliente_favorecido: id }, + updateDto, + ); + const updatedItem = new TransacaoClienteItem({ id: id, ...updateDto }); + this.logger.log( + `TransacaoClienteItem atualizado: ${updatedItem.getLogInfo()}`, + ); + return updatePayload; + } + + public async findOne( + fields: + | EntityCondition + | EntityCondition[], + ): Promise> { + return await this.transacaoClienteItemRepository.findOne({ + where: fields, + }); + } + + public async findMany( + fields: + | EntityCondition + | EntityCondition[], + ): Promise { + return await this.transacaoClienteItemRepository.find({ + where: fields, + }); + } +} diff --git a/src/cnab/repository/transacao.repository.ts b/src/cnab/repository/transacao.repository.ts index e69de29b..fbc2c957 100644 --- a/src/cnab/repository/transacao.repository.ts +++ b/src/cnab/repository/transacao.repository.ts @@ -0,0 +1,64 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { EntityCondition } from 'src/utils/types/entity-condition.type'; +import { NullableType } from 'src/utils/types/nullable.type'; +import { Repository, UpdateResult } from 'typeorm'; +import { Transacao } from '../entity/transacao.entity'; +import { SaveTransacaoDTO } from '../dto/save-transacao.dto'; + +@Injectable() +export class TransacaoRepository { + private logger: Logger = new Logger('TransacaoRepository', { + timestamp: true, + }); + + constructor( + @InjectRepository(Transacao) + private transacaoRepository: Repository, + ) {} + + public async save(dto: SaveTransacaoDTO): Promise { + if (dto.id_transacao === undefined) { + await this.create(dto); + } else { + await this.update(dto.id_transacao, dto); + } + } + + private async create(createProfileDto: SaveTransacaoDTO): Promise { + const createdItem = await this.transacaoRepository.save( + this.transacaoRepository.create(createProfileDto), + ); + this.logger.log(`Transacao criado: ${createdItem.getLogInfo()}`); + return createdItem; + } + + private async update( + id: number, + updateDto: SaveTransacaoDTO, + ): Promise { + const updatePayload = await this.transacaoRepository.update( + { id_transacao: id }, + updateDto, + ); + const updatedItem = new Transacao({ id_transacao: id, ...updateDto }); + this.logger.log(`Transacao atualizado: ${updatedItem.getLogInfo()}`); + return updatePayload; + } + + public async findOne( + fields: EntityCondition | EntityCondition[], + ): Promise> { + return await this.transacaoRepository.findOne({ + where: fields, + }); + } + + public async findAll( + fields: EntityCondition | EntityCondition[], + ): Promise { + return await this.transacaoRepository.find({ + where: fields, + }); + } +} diff --git a/src/cnab/service/Item-transacao.service.ts b/src/cnab/service/Item-transacao.service.ts index d3f5a12f..9b696f59 100644 --- a/src/cnab/service/Item-transacao.service.ts +++ b/src/cnab/service/Item-transacao.service.ts @@ -1 +1,13 @@ +import { NullableType } from 'src/utils/types/nullable.type'; +import { ItemTransacaoRepository } from '../repository/item-transacao.repository'; +import { ItemTransacao } from './../entity/item-transacao.entity'; +export class ItemTransacaoService{ + constructor( + private itemTransacaoRepository: ItemTransacaoRepository + ) { } + + public async getByIdTransacao(id_transacao:number):Promise{ + return await this.itemTransacaoRepository.find(id_transacao); + } +} \ No newline at end of file diff --git a/src/cnab/service/cliente-favorecido.service.ts b/src/cnab/service/cliente-favorecido.service.ts index 439f891a..9ea87bf1 100644 --- a/src/cnab/service/cliente-favorecido.service.ts +++ b/src/cnab/service/cliente-favorecido.service.ts @@ -1,30 +1,63 @@ -import { UsersService } from 'src/users/users.service'; -import { ClienteFavorecido } from './../entitys/cliente-favorecido.entity'; - -class ClienteFavorecidoService{ - - private clienteFavorecido: ClienteFavorecidoRepository; - - private userService: UsersService; - - function insertClienteFavorecido(){ - - // userService.get - - for{ - //veirificar se o usuario já existe na base - ClienteFavorecido.findByCpfCnj(cpf_cnpj); - - - // de/para -> user / Cliente - - //se não existir - - clienteFavorecido.insere(); - - //Se exitir - ClienteFavorecido.atualiza(); - } - } - -} \ No newline at end of file +import { 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/save-cliente-favorecido.dto'; +import { validateDTO } from 'src/utils/validation-utils'; + +@Injectable() +export class ClienteFavorecidoService { + private logger: Logger = new Logger('ClienteFavorecidoService', { + timestamp: true, + }); + + constructor( + private usersService: UsersService, + private clienteFavorecidoRepository: ClienteFavorecidoRepository, + ) {} + + /** + * All ClienteFavoecidos will be created or updated from users based of cpfCnpj. + * @returns All favorecidos after update + */ + public async updateAllFromUsers(): Promise { + const allUsers = await this.usersService.findMany({}); + for (const user of allUsers) { + const favorecido = await this.clienteFavorecidoRepository.findOne({ + cpf_cnpj: user.getCpfCnpj(), + }); + await this.saveFavorecidoFromUser( + user, + favorecido?.id_cliente_favorecido, + ); + } + return await this.clienteFavorecidoRepository.findMany({}); + } + + private async saveFavorecidoFromUser( + user: User, + existingId_facorecido?: number, + ): Promise { + const saveObject: SaveClienteFavorecidoDTO = { + id_cliente_favorecido: existingId_facorecido, + nome: user.getFullName(), + cpf_cnpj: user.getCpfCnpj(), + cod_banco: String(user.getBankCode()), + agencia: user.getBankAgencyWithoutDigit(), + dv_agencia: user.getBankAgencyDigit(), + conta_corrente: user.getBankAccount(), + dv_conta_corrente: user.getBankAccountDigit(), + logradouro: '', + numero: '', + complemento: '', + bairro: '', + cidade: '', + cep: '', + complemento_cep: '', + uf: '', + }; + await validateDTO(SaveClienteFavorecidoDTO, saveObject); + await this.clienteFavorecidoRepository.save(saveObject); + } +} diff --git a/src/cnab/service/detalhe-a.service.ts b/src/cnab/service/detalhe-a.service.ts index a0f6ab29..17d9273b 100644 --- a/src/cnab/service/detalhe-a.service.ts +++ b/src/cnab/service/detalhe-a.service.ts @@ -20,8 +20,8 @@ export class DetalheAService { private detalheARepository: DetalheARepository ) { } - public async save(dto: DetalheADTO): Promise { - await this.detalheARepository.save(dto); + public async save(dto: DetalheADTO): Promise { + return await this.detalheARepository.save(dto); } diff --git a/src/cnab/service/header-arquivo.service.ts b/src/cnab/service/header-arquivo.service.ts index a4b9e76c..f2ca2a09 100644 --- a/src/cnab/service/header-arquivo.service.ts +++ b/src/cnab/service/header-arquivo.service.ts @@ -1,39 +1,76 @@ -import { Injectable, Logger } from '@nestjs/common'; +import { HeaderLoteService } from './header-lote.service'; +import { HeaderLoteDTO } from './../dto/header-lote.dto'; +import { HeaderArquivo } from './../entity/header-arquivo.entity'; +import { Injectable, Logger, Get } from '@nestjs/common'; import { InjectService } from '@nestjs/typeorm'; import { EntityCondition } from 'src/utils/types/entity-condition.type'; import { NullableType } from 'src/utils/types/nullable.type'; -import { HeaderArquivo } from '../entity/header-arquivo.entity'; import { HeaderArquivoDTO } from '../dto/header-arquivo.dto'; import { HeaderArquivoRepository } from '../repository/header-arquivo.repository'; import { TransacaoService } from './transacao.service'; -import { Transacao } from '../entity/transacao.entity'; import { ItemTransacaoService } from './Item-transacao.service'; - +import { Transacao } from '../entity/transacao.entity'; +import { PagadorService } from './pagador.service'; +import { ItemTransacao } from '../entity/item-transacao.entity'; +import { DetalheAService } from './detalhe-a.service'; +import { DetalheBService } from './detalhe-b.service'; +import { DetalheADTO } from '../dto/detalhe-a.dto'; +import { DetalheBDTO } from '../dto/detalhe-b.dto'; @Injectable() export class HeaderArquivoService { private logger: Logger = new Logger('HeaderArquivoService', { timestamp: true }); + private COD_BANCO ="104"; + + private CONVENIO_BANCO = "444773"; + + private PARAM_TRANSMISSAO = "01"; + + private NUM_INSCRICAO = "546037000110"; + + private TIPO_INSCRICAO = "2"; + + private TIPO_COMPROMISSO = "0001"; + + private FINALIDADE= "001"; + + private MOEDA = "BRL"; + + private INDICADOR_BLOQUEIO="N"; + + private FORMA_PARCELAMENTO = "1"; + + private NUM_PARCELA=1; + constructor( @InjectService(HeaderArquivo) private headerArquivoRepository: HeaderArquivoRepository, private transacaoService:TransacaoService, - private itemTransacaoService:ItemTransacaoService - ) { } - - public async save(dto: HeaderArquivoDTO): Promise { - var listAllTransacao = await this.transacaoService.getAllTransacao(); - listAllTransacao.forEach(transacao=>{ - var listItem = itemTransacaoService.getByTransacao(transacao.id_transacao); - listItem.forEach(item => { - - }); - }); - await this.headerArquivoRepository.save(dto); + private headerLoteService:HeaderLoteService, + private itemTransacaoService:ItemTransacaoService, + private pagadorService:PagadorService, + private detalheAService:DetalheAService, + private detalheBService:DetalheBService + ) { } + + public async saveRemessa(): Promise { + var listAllTransacao = await this.transacaoService.getAll(); + listAllTransacao.forEach(async transacao=>{ + if(!this.verficaHeaderArquivo(transacao.id_transacao)){ + var headerArquivo = await this.transacaoToHeaderArquivo(transacao, "remessa"); + this.headerArquivoRepository.save(headerArquivo); + var headerLoteDTO = await this.transacaoToHeaderLote(transacao,headerArquivo) + this.headerLoteService.save(headerLoteDTO); + var listItem = this.itemTransacaoService.getByIdTransacao(transacao.id_transacao); + (await listItem).forEach(async itemTransacao => { + this.saveDetalhes(itemTransacao, await headerLoteDTO); + }); + } + }); } - public async findOne( fields: EntityCondition | EntityCondition[], ): Promise> { @@ -42,19 +79,77 @@ export class HeaderArquivoService { }); } - public async findMany( - fields: EntityCondition | EntityCondition[], - ): Promise { - return await this.headerArquivoRepository.find({ - where: fields, - }); + public async findAll(): Promise { + return await this.headerArquivoRepository.findAll(); } - private validateDTO(dto:HeaderArquivoDTO):boolean{ - return true; + private async transacaoToHeaderArquivo(transacao: Transacao,tipo_arquivo:string) + :Promise{ + var dto = new HeaderArquivoDTO(); + var pagador = await this.pagadorService.findById(transacao.id_pagador); + dto.agencia = pagador.agencia; + dto.cod_banco = this.COD_BANCO; + dto.cod_convenio = this.CONVENIO_BANCO; + dto.dt_geracao = transacao.dt_ordem; + dto.dv_agencia = pagador.dv_agencia + dto.dv_conta = pagador.dv_conta + dto.hr_geracao = transacao.dt_ordem + dto.id_transacao = transacao.id_transacao; + dto.nome_empresa = pagador.nome_empresa; + dto.num_conta = pagador.conta; + dto.num_inscricao = this.NUM_INSCRICAO; + dto.param_transmissao = this.PARAM_TRANSMISSAO; + dto.tipo_arquivo = tipo_arquivo; + dto.tipo_inscricao = this.TIPO_INSCRICAO; + return dto; } -} + private async transacaoToHeaderLote(transacao: Transacao,headerArquivoDTO: HeaderArquivoDTO) + :Promise{ + var dto = new HeaderLoteDTO(); + dto.cod_convenio_banco = headerArquivoDTO.cod_convenio; + dto.id_header_arquivo = headerArquivoDTO.id_header_arquivo; + dto.id_pagadora = transacao.id_pagador; + //autoincremento no banco => dto.lote_servico = ; + dto.num_inscricao = headerArquivoDTO.num_inscricao; + dto.param_transmissao = headerArquivoDTO.param_transmissao; + dto.tipo_compromisso = this.TIPO_COMPROMISSO; + dto.tipo_inscricao = headerArquivoDTO.tipo_inscricao; + return dto; + } + private async saveDetalhes(itemTransacao: ItemTransacao,headerLoteDTO:HeaderLoteDTO) + :Promise{ + var detalheA = new DetalheADTO(); + detalheA.data_efetivacao = itemTransacao.dt_transacao; + detalheA.dt_vencimento = itemTransacao.dt_processamento; + detalheA.id_header_lote = headerLoteDTO.id_header_lote; + detalheA.indicador_bloqueio = this.INDICADOR_BLOQUEIO ; + detalheA.id_cliente_favorecido = itemTransacao.id_cliente_favorecido; + detalheA.indicador_forma_parcelamento = this.FORMA_PARCELAMENTO; + detalheA.lote_servico = headerLoteDTO.lote_servico; + //detalheA.num_doc_lancamento = this.geraLoteServico(); autoincrementar no banco + detalheA.periodo_vencimento = itemTransacao.dt_processamento; + detalheA.num_parcela = this.NUM_PARCELA; + detalheA.qtde_parcelas = this.NUM_PARCELA; + detalheA.tipo_finalidade_conta = this.FINALIDADE; + detalheA.tipo_moeda = this.MOEDA; + detalheA.valor_lancamento = itemTransacao.valor_item_transacao; + detalheA.valor_real_efetivado = itemTransacao.valor_item_transacao; + var saveDetalheA = this.detalheAService.save(detalheA); + var detalheB = new DetalheBDTO(); + detalheB.data_vencimento = itemTransacao.dt_processamento; + // detalheB.nsr = // this.geraLoteServico(); auto incrementar no banco // pegar da geracao do arquivo e salvar + detalheB.id_detalhe_a = (await saveDetalheA).id_detalhe_a; + this.detalheBService.save(detalheB); + } + private verficaHeaderArquivo(id_transacao:number):boolean{ + var ret = this.headerArquivoRepository.findOne(id_transacao); + if(ret == null){ + return false; + } + return true; + } +} \ No newline at end of file diff --git a/src/cnab/service/pagador.service.ts b/src/cnab/service/pagador.service.ts index e69de29b..f168b117 100644 --- a/src/cnab/service/pagador.service.ts +++ b/src/cnab/service/pagador.service.ts @@ -0,0 +1,35 @@ +import { HttpStatus, Injectable, Logger } from '@nestjs/common'; +import { CommonHttpException } from 'src/utils/http-exception/common-http-exception'; +import { Pagador } from '../entity/pagador.entity'; +import { PagadorContaEnum } from '../enums/pagador/pagador.enum'; +import { PagadorRepository } from '../repository/pagador.repository'; +import { NullableType } from 'src/utils/types/nullable.type'; + +@Injectable() +export class PagadorService { + private logger: Logger = new Logger('PagadorService', { timestamp: true }); + + constructor(private pagadorRepository: PagadorRepository) {} + + public async findByConta(conta: PagadorContaEnum | string) { + return await this.pagadorRepository.findOne({ conta: conta }); + } + + public async getOneById(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 findById(id_pagador:number): Promise{ + return await this.pagadorRepository.findOne(id_pagador); + } + +} diff --git a/src/cnab/repository/Item-transacao.repository.ts b/src/cnab/service/transacao-cliente-item.service.ts similarity index 100% rename from src/cnab/repository/Item-transacao.repository.ts rename to src/cnab/service/transacao-cliente-item.service.ts diff --git a/src/cnab/service/transacao.service.ts b/src/cnab/service/transacao.service.ts index 7a35eedf..b144b957 100644 --- a/src/cnab/service/transacao.service.ts +++ b/src/cnab/service/transacao.service.ts @@ -1,9 +1,79 @@ -import { Transacao } from "../entity/transacao.entity"; - -export class TransacaoService{ - - public async getAllTransacao(): Promise (){ - return await null; - } - -} +import { getPagination } from './../../utils/get-pagination'; + +import { Injectable } from '@nestjs/common'; +// import { nextFriday } from 'date-fns'; +// import { BigqueryTransacao } from 'src/bigquery/entities/transacao.bigquery-entity'; +import { BigqueryTransacaoService } from 'src/bigquery/services/bigquery-transacao.service'; +// import { PagadorContaEnum } from '../enums/pagador/pagador.enum'; +// import { TransacaoRepository } from '../repository/transacao.repository'; +import { ClienteFavorecidoService } from './cliente-favorecido.service'; +import { Transacao } from '../entity/transacao.entity'; +import { TransacaoRepository } from '../repository/transacao.repository'; +// import { PagadorService } from './pagador.service'; + +@Injectable() +export class TransacaoService { + constructor( + private transacaoRepository: TransacaoRepository, + // private transacaoClienteItemService: TransacaoClienteItemService, + private clienteFavorecidoService: ClienteFavorecidoService, + // private pagadorService: PagadorService, + private bigqueryTransacaoService: BigqueryTransacaoService, + ) {} + public async insereTransacoes() { + const favorecidos = + await this.clienteFavorecidoService.updateAllFromUsers(); + const transacoesJae = + await this.bigqueryTransacaoService.getTransacaoOfCurrentWeek(); + for (const bigqueryTransacao of transacoesJae) { + // WIP + console.log(bigqueryTransacao, favorecidos); // tslint ignore + // const pagador = await this.pagadorService.getOneById(PagadorContaEnum.JAE); + // var id_transacao = await this.insertTransacao(bigqueryTransacao, pagador.id_pagador); + // //buscar todas as ordens de pagamento por idTransacaoFernanda + // var ordensPgto = buscarOrder(bigqueryTransacao.id_transacao); + // for (const ordemPgto of ordensPgto) { + // var id_cliente_favorecido = listaCliente.findByCPFCNPJ(ordemPgto.cpf_enpj); + // itemTransacao.id_cliente_favorecido = id_cliente_favorecido; + // //insere o item detalhamento + // itemTransacao.id_transacao = id_transacao; + // itemTransacao.idClientFavorecido = idClienteFavorecido; + // itemTransacao.dt_transacao = ordemPgto.dt_transacao; + // itemTransacaoRepository.insere(itemTransacao); + // } + } + } + + /** + * Para cada BigqueryOrdemPagamento insere em Transacao + */ + // public async insertTransacao( + // bigqueryTransacao: BigqueryTransacao, + // bigqueryOrdemPagamento: BigqueryOrdemPagamento + // id_pagador: number, + // ): Promise { + // return await this.transacaoRepository.create({ + // dt_ordem: nextFriday(new Date(bigqueryTransacao.datetime_processamento)), + // dt_pagamento: '', + // nome_consorcio: bigqueryTransacao.consorcio, + // nome_operadora: bigqueryTransacao.operadora, + // servico: bigqueryTransacao.servico, + // id_ordem_ressarcimento: -1, + // qtde_transacao_rateio_credito: number + // vlr_rateio_credito: number + // qtde_transacao_rateio_debito: number + // vlr_rateio_debito: number + // quantidade_total_transacao: number + // vlr_total_transacao_bruto: number + // vlr_desconto_taxa: number + // vlr_total_transacao_liquido: number + // qtde_total_transacao_captura: number + // vlr_total_transacao_captura: number + // indicador_ordem_valida: string + // }); + // } + + public async getAll():Promise{ + return await this.transacaoRepository.findAll(Transacao); + } +} \ No newline at end of file diff --git a/src/cnab/templates/cnab-all/cnab-all-104-registro-field-map-template.ts b/src/cnab/templates/cnab-all/cnab-all-104-registro-field-map-template.ts index fbbd9671..0f0df2ce 100644 --- a/src/cnab/templates/cnab-all/cnab-all-104-registro-field-map-template.ts +++ b/src/cnab/templates/cnab-all/cnab-all-104-registro-field-map-template.ts @@ -1,7 +1,7 @@ -import { ICnabFieldMapDetalhe } from 'src/cnab/interfaces/cnab-field-map-detalhe.interface'; -import { ICnabFieldMapTrailerArquivo } from 'src/cnab/interfaces/cnab-field-map-trailer-arquivo.interface'; -import { ICnabFieldMapTrailerLote } from 'src/cnab/interfaces/cnab-field-map-trailer-lote.interface'; -import { ICnabFieldMap } from 'src/cnab/interfaces/cnab-field-map.interface'; +import { ICnabFieldMapDetalhe } from 'src/cnab/interfaces/cnab-all/cnab-field-map-detalhe.interface'; +import { ICnabFieldMapTrailerArquivo } from 'src/cnab/interfaces/cnab-all/cnab-field-map-trailer-arquivo.interface'; +import { ICnabFieldMapTrailerLote } from 'src/cnab/interfaces/cnab-all/cnab-field-map-trailer-lote.interface'; +import { ICnabFieldMap } from 'src/cnab/interfaces/cnab-all/cnab-field-map.interface'; const registro: ICnabFieldMap = { registroIdField: 'codigoRegistro', diff --git a/src/cnab/test/templates/240/generic/cnab-240-generic-field-map-template-test.const.ts b/src/cnab/test/templates/240/generic/cnab-240-generic-field-map-template-test.const.ts index 535e2b6e..bbf69421 100644 --- a/src/cnab/test/templates/240/generic/cnab-240-generic-field-map-template-test.const.ts +++ b/src/cnab/test/templates/240/generic/cnab-240-generic-field-map-template-test.const.ts @@ -1,4 +1,4 @@ -import { ICnabFieldMap } from 'src/cnab/interfaces/cnab-field-map.interface'; +import { ICnabFieldMap } from 'src/cnab/interfaces/cnab-all/cnab-field-map.interface'; const base: ICnabFieldMap = { registroIdField: 'codigoRegistro', diff --git a/src/cnab/types/cnab-registro.type.ts b/src/cnab/types/cnab-registro.type.ts index a7c1572a..4a0ed678 100644 --- a/src/cnab/types/cnab-registro.type.ts +++ b/src/cnab/types/cnab-registro.type.ts @@ -1,5 +1,5 @@ import { isArrayContainEqual } from 'src/utils/array-utils'; -import { ICnabFieldMap } from '../interfaces/cnab-field-map.interface'; +import { ICnabFieldMap } from '../interfaces/cnab-all/cnab-field-map.interface'; import { CnabFields } from './cnab-field.type'; export type CnabRegistro = { diff --git a/src/cnab/utils/cnab-utils.spec.ts b/src/cnab/utils/cnab-utils.spec.ts index 5fba460c..9329c8cb 100644 --- a/src/cnab/utils/cnab-utils.spec.ts +++ b/src/cnab/utils/cnab-utils.spec.ts @@ -9,7 +9,7 @@ import { CnabFields } from '../types/cnab-field.type'; import { CnabFile } from '../types/cnab-file.type'; import { CnabLote } from '../types/cnab-lote.type'; import { CnabRegistro } from '../types/cnab-registro.type'; -import { ICnabFieldMap } from '../interfaces/cnab-field-map.interface'; +import { ICnabFieldMap } from '../interfaces/cnab-all/cnab-field-map.interface'; import * as path from 'path'; import * as fs from 'fs'; import { cnab240GenericFieldMapTemplateTest } from '../test/templates/240/generic/cnab-240-generic-field-map-template-test.const'; diff --git a/src/cnab/utils/cnab-utils.ts b/src/cnab/utils/cnab-utils.ts index 615573b6..d83614b3 100644 --- a/src/cnab/utils/cnab-utils.ts +++ b/src/cnab/utils/cnab-utils.ts @@ -1,7 +1,7 @@ import { Exception } from 'handlebars'; import { CNAB_EOL, CNAB_SUPPORTED_FORMATS } from '../cnab-consts'; import { CnabAllCodigoRegistro } from '../enums/all/cnab-all-codigo-registro.enum'; -import { ICnabFieldMap } from '../interfaces/cnab-field-map.interface'; +import { ICnabFieldMap } from '../interfaces/cnab-all/cnab-field-map.interface'; import { CnabField } from '../types/cnab-field.type'; import { CnabFile, isCnabFile } from '../types/cnab-file.type'; import { CnabLote, isCnabLote } from '../types/cnab-lote.type'; diff --git a/src/config/database.config.ts b/src/config/database.config.ts index ff779e1c..e34dd54e 100644 --- a/src/config/database.config.ts +++ b/src/config/database.config.ts @@ -16,15 +16,15 @@ class EnvironmentVariablesValidator { @IsString() DATABASE_URL: string; - @ValidateIf((envValues) => !envValues.DATABASE_URL) + @ValidateIf((envValues) => !envValues.DATABASE_TYPE) @IsString() DATABASE_TYPE: string; - @ValidateIf((envValues) => !envValues.DATABASE_URL) + @ValidateIf((envValues) => !envValues.DATABASE_HOST) @IsString() DATABASE_HOST: string; - @ValidateIf((envValues) => !envValues.DATABASE_URL) + @ValidateIf((envValues) => !envValues.DATABASE_PORT) @IsInt() @Min(0) @Max(65535) diff --git a/src/users/entities/user.entity.ts b/src/users/entities/user.entity.ts index b49b8f4f..efb20931 100644 --- a/src/users/entities/user.entity.ts +++ b/src/users/entities/user.entity.ts @@ -234,6 +234,115 @@ export class User extends EntityHelper { return response; } + /** + * Get field validated + * @throws `HttpException` + */ + getBankAgency(args?: { + errorMessage?: string; + httpStatusCode?: HttpStatus; + }): string { + if (!this.bankAgency) { + throw UserHttpException.invalidField('bankAgency', { + errorMessage: args?.errorMessage, + httpStatusCode: args?.httpStatusCode, + }); + } + return this.bankAgency; + } + + /** + * Get field validated + * @throws `HttpException` + */ + getBankAgencyWithoutDigit(args?: { + errorMessage?: string; + httpStatusCode?: HttpStatus; + }): string { + const agency = this.getBankAgency(args); + return agency.substring(0, agency.length - 1); + } + + /** + * Get field validated + * @throws `HttpException` + */ + getBankAgencyDigit(args?: { + errorMessage?: string; + httpStatusCode?: HttpStatus; + }): string { + const agency = this.getBankAgency(args); + return agency.substring(agency.length - 1); + } + + /** + * Get field validated + * @throws `HttpException` + */ + getBankAccount(args?: { + errorMessage?: string; + httpStatusCode?: HttpStatus; + }): string { + if (!this.bankAccount) { + throw UserHttpException.invalidField('bankAgency', { + errorMessage: args?.errorMessage, + httpStatusCode: args?.httpStatusCode, + }); + } + return this.bankAccount; + } + + /** + * Get field validated + * @throws `HttpException` + */ + getBankAccountDigit(args?: { + errorMessage?: string; + httpStatusCode?: HttpStatus; + }): string { + if (!this.bankAccountDigit) { + throw UserHttpException.invalidField('bankAgency', { + errorMessage: args?.errorMessage, + httpStatusCode: args?.httpStatusCode, + }); + } + return this.bankAccountDigit; + } + + /** + * Get field validated + * @throws `HttpException` + */ + getBankCode(args?: { + errorMessage?: string; + httpStatusCode?: HttpStatus; + }): number { + if (!this.bankCode) { + throw UserHttpException.invalidField('bankAgency', { + errorMessage: args?.errorMessage, + httpStatusCode: args?.httpStatusCode, + }); + } + return this.bankCode; + } + + /** + * Get field validated + * @throws `HttpException` + */ + getFullName(args?: { + errorMessage?: string; + httpStatusCode?: HttpStatus; + }): string { + if (!this.fullName) { + throw UserHttpException.invalidField('bankAgency', { + errorMessage: args?.errorMessage, + httpStatusCode: args?.httpStatusCode, + }); + } + return this.fullName; + } + /** * Get field validated * @throws `HttpException` diff --git a/src/users/users.service.ts b/src/users/users.service.ts index a0de1c97..b60d69f3 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -19,7 +19,7 @@ import { HttpStatusMessage } from 'src/utils/enums/http-error-message.enum'; import { formatLog } from 'src/utils/logging'; import { getStringUpperUnaccent } from 'src/utils/string-utils'; import { EntityCondition } from 'src/utils/types/entity-condition.type'; -import { InvalidRowsType } from 'src/utils/types/invalid-rows.type'; +import { InvalidRows } from 'src/utils/types/invalid-rows.type'; import { PaginationOptions } from 'src/utils/types/pagination-options'; import { Brackets, @@ -401,14 +401,14 @@ export class UsersService { async validateFileValues( userFile: IFileUser, fileUsers: IFileUser[], - validatorDto, - ): Promise { + validatorDto: any, + ): Promise { const schema = plainToClass(validatorDto, userFile.user); const errors = await validate(schema as Record, { stopAtFirstError: true, }); const SEPARATOR = '; '; - const errorDictionary: InvalidRowsType = errors.reduce((result, error) => { + const errorDictionary: InvalidRows = errors.reduce((result, error) => { const { property, constraints } = error; if (property && constraints) { result[property] = Object.values(constraints).join(SEPARATOR); diff --git a/src/utils/http-exception/common-http-exception.ts b/src/utils/http-exception/common-http-exception.ts index eb86af59..71211f02 100644 --- a/src/utils/http-exception/common-http-exception.ts +++ b/src/utils/http-exception/common-http-exception.ts @@ -16,7 +16,19 @@ export const CommonHttpException = { }, httpStatusCode, ), - simpleDetail: (details: any, httpStatusCode: HttpStatus = 500) => + errorDetails: ( + error: string, + details: object, + httpStatusCode: HttpStatus = 500, + ) => + new HttpException( + { + error: getHttpStatusMessage(httpStatusCode), + details, + }, + httpStatusCode, + ), + simpleDetails: (details: any, httpStatusCode: HttpStatus = 500) => new HttpException( { error: getHttpStatusMessage(httpStatusCode), @@ -25,17 +37,17 @@ export const CommonHttpException = { httpStatusCode, ), notFound: ( - notFoundField: string, + notFoundItem: string, httpStatusCode: HttpStatus = HttpStatus.NOT_FOUND, error?: string, ) => new HttpException( { error: error || getHttpStatusMessage(httpStatusCode), - ...(notFoundField + ...(notFoundItem ? { details: { - [notFoundField]: 'not found', + [notFoundItem]: 'not found', }, } : {}), diff --git a/src/utils/payment-date-utils.ts b/src/utils/payment-date-utils.ts index c81bd722..dca77a0a 100644 --- a/src/utils/payment-date-utils.ts +++ b/src/utils/payment-date-utils.ts @@ -18,6 +18,9 @@ export const PAYMENT_START_WEEKDAY = WeekdayEnum._4_THURSDAY; export const PAYMENT_END_WEEKDAY = WeekdayEnum._3_WEDNESDAY; export type PaymentEndpointType = 'bank-statements' | 'ticket-revenues'; +/** + * From friday get starting thursday and ending wednesday + */ export function getPaymentWeek( fridayDate: Date, endpoint: PaymentEndpointType = 'ticket-revenues', diff --git a/src/utils/types/invalid-rows.type.ts b/src/utils/types/invalid-rows.type.ts index af988b4d..900042b3 100644 --- a/src/utils/types/invalid-rows.type.ts +++ b/src/utils/types/invalid-rows.type.ts @@ -11,4 +11,4 @@ * } * ``` */ -export type InvalidRowsType = { [field: string]: string }; +export type InvalidRows = { [field: string]: string }; diff --git a/src/utils/validation-utils.ts b/src/utils/validation-utils.ts new file mode 100644 index 00000000..174d2b9e --- /dev/null +++ b/src/utils/validation-utils.ts @@ -0,0 +1,44 @@ +import { HttpException, HttpStatus, ValidationError } from '@nestjs/common'; +import { plainToInstance } from 'class-transformer'; +import { validate } from 'class-validator'; +import { getHttpStatusMessage } from './http-exception/http-exception-utils'; +import { InvalidRows } from './types/invalid-rows.type'; + +const SEPARATOR = '; '; + +export async function validateDTO( + dto: any, + object: any, + throwOnError = true, +): Promise { + const schema = plainToInstance(dto, object); + const errors = await validate(schema as Record, { + stopAtFirstError: true, + }); + const invalidRows = getInvalidRows(errors); + if (errors.length > 0 && throwOnError) { + const code = HttpStatus.UNPROCESSABLE_ENTITY; + throw new HttpException( + { + error: getHttpStatusMessage(code), + details: { + message: 'Object failed passing through DTO', + errors: invalidRows, + }, + }, + code, + ); + } else { + return invalidRows; + } +} + +export function getInvalidRows(errors: ValidationError[]): InvalidRows { + return errors.reduce((result, error) => { + const { property, constraints } = error; + if (property && constraints) { + result[property] = Object.values(constraints).join(SEPARATOR); + } + return result; + }, {}); +} diff --git a/yarn.lock b/yarn.lock index 7445cb19..80d45ad6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4080,7 +4080,12 @@ "resolved" "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz" "version" "10.0.0" -"dotenv@^16.0.3", "dotenv@16.0.3": +"dotenv@^16.0.3", "dotenv@^16.4.5": + "integrity" "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" + "resolved" "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz" + "version" "16.4.5" + +"dotenv@16.0.3": "integrity" "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" "resolved" "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz" "version" "16.0.3"