From a597deea19cd6acf0f1fd27c4838dbecdbc6f60c Mon Sep 17 00:00:00 2001 From: Shashank Shekhar Date: Wed, 8 Jan 2025 15:02:17 -0800 Subject: [PATCH] #274 - Merge release v2.2.0 to v2.3.0 (#4216) **As a part of this PR, release v2.2.0 is merged to v2.3.0** --------- Co-authored-by: Bidyashish Co-authored-by: Andrew Boni Signori <61259237+andrewsignori-aot@users.noreply.github.com> --- ...-process-integration.scheduler.e2e-spec.ts | 14 ++++- .../e-cert-integration/e-cert-file-handler.ts | 58 ++++++++++++------- .../full-time-e-cert-file-handler.ts | 3 + .../part-time-e-cert-file-handler.ts | 5 +- 4 files changed, 57 insertions(+), 23 deletions(-) diff --git a/sources/packages/backend/apps/queue-consumers/src/processors/schedulers/esdc-integration/ecert-integration/_tests_/ecert-part-time-process-integration.scheduler.e2e-spec.ts b/sources/packages/backend/apps/queue-consumers/src/processors/schedulers/esdc-integration/ecert-integration/_tests_/ecert-part-time-process-integration.scheduler.e2e-spec.ts index f435d489bd..c8ac24ee7d 100644 --- a/sources/packages/backend/apps/queue-consumers/src/processors/schedulers/esdc-integration/ecert-integration/_tests_/ecert-part-time-process-integration.scheduler.e2e-spec.ts +++ b/sources/packages/backend/apps/queue-consumers/src/processors/schedulers/esdc-integration/ecert-integration/_tests_/ecert-part-time-process-integration.scheduler.e2e-spec.ts @@ -52,6 +52,7 @@ import { } from "./e-cert-utils"; import { SystemUsersService } from "@sims/services"; import * as faker from "faker"; +import { ECERT_PART_TIME_SENT_FILE_SEQUENCE_GROUP } from "@sims/integrations/esdc-integration"; describe( describeQueueProcessorRootTest(QueueNames.PartTimeECertIntegration), @@ -97,7 +98,7 @@ describe( ); // Reset sequence number to control the file name generated. await db.sequenceControl.update( - { sequenceName: Like("ECERT_PT_SENT_FILE_%") }, + { sequenceName: Like("ECERT_PT_SENT_FILE%") }, { sequenceNumber: "0" }, ); }); @@ -384,6 +385,14 @@ describe( }, }, ); + const eCertLifetimeSequence = 100000; + await db.sequenceControl.upsert( + { + sequenceName: ECERT_PART_TIME_SENT_FILE_SEQUENCE_GROUP, + sequenceNumber: eCertLifetimeSequence.toString(), + }, + ["sequenceName"], + ); // Queued job. const { job } = mockBullJob(); @@ -401,7 +410,10 @@ describe( expect(uploadedFile.fileLines).toHaveLength(3); const [header, record, footer] = uploadedFile.fileLines; + const headerSequence = header.substring(58, 64); // Validate header. + const expectedHeaderSequence = (eCertLifetimeSequence + 1).toString(); + expect(headerSequence).toBe(expectedHeaderSequence); expect(header).toContain("01BC NEW PT ENTITLEMENT"); // Validate footer. // Record Type. diff --git a/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/e-cert-file-handler.ts b/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/e-cert-file-handler.ts index 6a8186efaf..811242bae7 100644 --- a/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/e-cert-file-handler.ts +++ b/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/e-cert-file-handler.ts @@ -10,7 +10,7 @@ import { } from "../../services"; import { SequenceControlService, SystemUsersService } from "@sims/services"; import { getISODateOnlyString, processInParallel } from "@sims/utilities"; -import { EntityManager } from "typeorm"; +import { DataSource, EntityManager } from "typeorm"; import { ESDCFileHandler } from "../esdc-file-handler"; import { Award, @@ -22,6 +22,7 @@ import { ConfigService, ESDCIntegrationConfig } from "@sims/utilities/config"; import { ECertGenerationService } from "@sims/integrations/services"; import { ECertResponseRecord } from "./e-cert-files/e-cert-response-record"; import * as path from "path"; +import { CreateRequestFileNameResult } from "../models/esdc-integration.model"; /** * Error details: error id and block funding info @@ -41,6 +42,7 @@ type ECertFeedbackCodeMap = Record; export abstract class ECertFileHandler extends ESDCFileHandler { esdcConfig: ESDCIntegrationConfig; constructor( + private readonly dataSource: DataSource, configService: ConfigService, private readonly sequenceService: SequenceControlService, private readonly eCertGenerationService: ECertGenerationService, @@ -72,7 +74,7 @@ export abstract class ECertFileHandler extends ESDCFileHandler { * for the respective integration. * @param offeringIntensity disbursement offering intensity. * @param fileCode file code applicable for Part-Time or Full-Time. - * @param sequenceGroupPrefix sequence group prefix for Part-Time or Full-Time + * @param sequenceGroup sequence group for Part-Time or Full-Time * file sequence generation. * @param log cumulative process log. * @returns result of the file upload with the file generated and the @@ -82,30 +84,46 @@ export abstract class ECertFileHandler extends ESDCFileHandler { eCertIntegrationService: ECertIntegrationService, offeringIntensity: OfferingIntensity, fileCode: string, - sequenceGroupPrefix: string, + sequenceGroup: string, log: ProcessSummary, ): Promise { log.info( `Retrieving ${offeringIntensity} disbursements to generate the e-Cert file...`, ); - const sequenceGroup = `${sequenceGroupPrefix}_${getISODateOnlyString( + const sequenceGroupFileName = `${sequenceGroup}_${getISODateOnlyString( new Date(), )}`; let uploadResult: ECertUploadResult; - await this.sequenceService.consumeNextSequence( - sequenceGroup, - async (nextSequenceNumber: number, entityManager: EntityManager) => { - uploadResult = await this.processECert( - nextSequenceNumber, - entityManager, - eCertIntegrationService, - offeringIntensity, - fileCode, - log, - ); - }, - ); + let fileInfo: CreateRequestFileNameResult; + await this.dataSource.transaction(async (transactionalEntityManager) => { + // Consume the next sequence number for the e-Cert filename + // and execute the creation of the request filename. + await this.sequenceService.consumeNextSequenceWithExistingEntityManager( + sequenceGroupFileName, + transactionalEntityManager, + async (nextSequenceNumber: number) => { + // Create the request filename with the file path for the e-Cert File. + fileInfo = this.createRequestFileName(fileCode, nextSequenceNumber); + }, + ); + // Consume the next sequence number for the e-Cert file header + // and execute the processECert process. + await this.sequenceService.consumeNextSequenceWithExistingEntityManager( + sequenceGroup, + transactionalEntityManager, + async (nextSequenceNumber: number, entityManager: EntityManager) => { + uploadResult = await this.processECert( + nextSequenceNumber, + entityManager, + eCertIntegrationService, + offeringIntensity, + fileInfo, + log, + ); + }, + ); + }); return uploadResult; } @@ -116,7 +134,7 @@ export abstract class ECertFileHandler extends ESDCFileHandler { * @param eCertIntegrationService Full-Time/Part-Time integration responsible * for the respective integration. * @param offeringIntensity disbursement offering intensity. - * @param fileCode file code applicable for Part-Time or Full-Time. + * @param fileInfo e-Cert file information. * @param log cumulative process log. * @returns information of the uploaded e-Cert file. */ @@ -125,7 +143,7 @@ export abstract class ECertFileHandler extends ESDCFileHandler { entityManager: EntityManager, eCertIntegrationService: ECertIntegrationService, offeringIntensity: OfferingIntensity, - fileCode: string, + fileInfo: CreateRequestFileNameResult, log: ProcessSummary, ): Promise { const disbursements = @@ -146,8 +164,6 @@ export abstract class ECertFileHandler extends ESDCFileHandler { sequenceNumber, ); - // Create the request filename with the file path for the e-Cert File. - const fileInfo = this.createRequestFileName(fileCode, sequenceNumber); log.info(`Uploading ${offeringIntensity} content...`); await eCertIntegrationService.uploadContent(fileContent, fileInfo.filePath); // Mark all disbursements as sent. diff --git a/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/full-time-e-cert-file-handler.ts b/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/full-time-e-cert-file-handler.ts index c0991a39ad..36863c0773 100644 --- a/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/full-time-e-cert-file-handler.ts +++ b/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/full-time-e-cert-file-handler.ts @@ -15,6 +15,7 @@ import { ECertGenerationService } from "@sims/integrations/services"; import { ECertFileHandler } from "./e-cert-file-handler"; import { ECertFullTimeIntegrationService } from "./e-cert-full-time-integration/e-cert-full-time.integration.service"; import { ProcessSummary } from "@sims/utilities/logger"; +import { DataSource } from "typeorm"; const ECERT_FULL_TIME_SENT_FILE_SEQUENCE_GROUP = "ECERT_FT_SENT_FILE"; @@ -22,6 +23,7 @@ const ECERT_FULL_TIME_SENT_FILE_SEQUENCE_GROUP = "ECERT_FT_SENT_FILE"; export class FullTimeECertFileHandler extends ECertFileHandler { esdcConfig: ESDCIntegrationConfig; constructor( + dataSource: DataSource, configService: ConfigService, sequenceService: SequenceControlService, eCertGenerationService: ECertGenerationService, @@ -31,6 +33,7 @@ export class FullTimeECertFileHandler extends ECertFileHandler { private readonly eCertIntegrationService: ECertFullTimeIntegrationService, ) { super( + dataSource, configService, sequenceService, eCertGenerationService, diff --git a/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/part-time-e-cert-file-handler.ts b/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/part-time-e-cert-file-handler.ts index 2972db7bd1..ded868dbc0 100644 --- a/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/part-time-e-cert-file-handler.ts +++ b/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/part-time-e-cert-file-handler.ts @@ -15,13 +15,15 @@ import { ECertGenerationService } from "@sims/integrations/services"; import { ECertFileHandler } from "./e-cert-file-handler"; import { ECertPartTimeIntegrationService } from "./e-cert-part-time-integration/e-cert-part-time.integration.service"; import { ProcessSummary } from "@sims/utilities/logger"; +import { DataSource } from "typeorm"; -const ECERT_PART_TIME_SENT_FILE_SEQUENCE_GROUP = "ECERT_PT_SENT_FILE"; +export const ECERT_PART_TIME_SENT_FILE_SEQUENCE_GROUP = "ECERT_PT_SENT_FILE"; @Injectable() export class PartTimeECertFileHandler extends ECertFileHandler { esdcConfig: ESDCIntegrationConfig; constructor( + dataSource: DataSource, configService: ConfigService, sequenceService: SequenceControlService, eCertGenerationService: ECertGenerationService, @@ -31,6 +33,7 @@ export class PartTimeECertFileHandler extends ECertFileHandler { private readonly eCertIntegrationService: ECertPartTimeIntegrationService, ) { super( + dataSource, configService, sequenceService, eCertGenerationService,