From 26be13294588bd50c48e9d6e0e20216fcac51be8 Mon Sep 17 00:00:00 2001 From: laxmanhalaki Date: Mon, 16 Mar 2026 11:03:28 +0530 Subject: [PATCH] implemented archive mechanism for the incoming files for dealer calim and form-16 --- env.example | 18 ++++++++- package.json | 4 +- src/scripts/test-wfm-archive.ts | 65 +++++++++++++++++++++++++++++++ src/services/wfmFile.service.ts | 69 ++++++++++++++++++++++++++++----- 4 files changed, 141 insertions(+), 15 deletions(-) create mode 100644 src/scripts/test-wfm-archive.ts diff --git a/env.example b/env.example index 5a5306d..daa321a 100644 --- a/env.example +++ b/env.example @@ -79,6 +79,16 @@ WFM_INCOMING_GST_CLAIMS_PATH=WFM-QRE\\INCOMING\\WFM_MAIN\\DLR_INC_CLAIMS_GST WFM_INCOMING_NON_GST_CLAIMS_PATH=WFM-QRE\\INCOMING\\WFM_MAIN\\DLR_INC_CLAIMS_NON_GST WFM_OUTGOING_GST_CLAIMS_PATH=WFM-QRE\\OUTGOING\\WFM_SAP_MAIN\\DLR_INC_CLAIMS_GST WFM_OUTGOING_NON_GST_CLAIMS_PATH=WFM-QRE\\OUTGOING\\WFM_SAP_MAIN\\DLR_INC_CLAIMS_NON_GST +WFM_FORM16_CREDIT_INCOMING_PATH=WFM-QRE\\INCOMING\\WFM_MAIN\\FORM16_CRDT +WFM_FORM16_DEBIT_INCOMING_PATH=WFM-QRE\\INCOMING\\WFM_MAIN\\FORM16_DBT +WFM_FORM16_CREDIT_OUTGOING_PATH=WFM-QRE\\OUTGOING\\WFM_SAP_MAIN\\FORM16_CRDT +WFM_FORM16_DEBIT_OUTGOING_PATH=WFM-QRE\\OUTGOING\\WFM_SAP_MAIN\\FORM16_DBT + +# WFM Archive Configuration (INCOMING) +WFM_ARCHIVE_GST_CLAIMS_PATH=WFM-QRE\\INCOMING\\WFM_ARACHIVE\\DLR_INC_CLAIMS_GST +WFM_ARCHIVE_NON_GST_CLAIMS_PATH=WFM-QRE\\INCOMING\\WFM_ARACHIVE\\DLR_INC_CLAIMS_NON_GST +WFM_FORM16_CREDIT_ARCHIVE_PATH=WFM-QRE\\INCOMING\\WFM_ARACHIVE\\FORM16_CRDT +WFM_FORM16_DEBIT_ARCHIVE_PATH=WFM-QRE\\INCOMING\\WFM_ARACHIVE\\FORM16_DBT # TAT Monitoring TAT_CHECK_INTERVAL_MINUTES=30 @@ -119,9 +129,13 @@ SAP_DISABLE_SSL_VERIFY=false # WFM_INCOMING_CLAIMS_PATH=WFM-QRE\INCOMING\WFM_MAIN\DLR_INC_CLAIMS # WFM_OUTGOING_CLAIMS_PATH=WFM-QRE\OUTGOING\WFM_SAP_MAIN\DLR_INC_CLAIMS # Form 16 credit note CSV (incoming): INCOMING/WFM_MAIN/FORM16_CRDT -# Form 16 debit note CSV (incoming): INCOMING/WFM_MAIN/FORM16_DEBT +# Form 16 debit note CSV (incoming): INCOMING/WFM_MAIN/FORM16_DBT # Form 16 SAP responses (outgoing): OUTGOING/WFM_SAP_MAIN/FORM16_CRDT # WFM_FORM16_CREDIT_INCOMING_PATH=WFM-QRE\INCOMING\WFM_MAIN\FORM16_CRDT -# WFM_FORM16_DEBIT_INCOMING_PATH=WFM-QRE\INCOMING\WFM_MAIN\FORM16_DEBT +# WFM_FORM16_DEBIT_INCOMING_PATH=WFM-QRE\INCOMING\WFM_MAIN\FORM16_DBT # WFM_FORM16_OUTGOING_PATH=WFM-QRE\OUTGOING\WFM_SAP_MAIN\FORM16_CRDT +# WFM Archive configuration examples (if overrides are needed) +# WFM_ARCHIVE_GST_CLAIMS_PATH=WFM-QRE\INCOMING\WFM_ARACHIVE\DLR_INC_CLAIMS_GST +# WFM_FORM16_CREDIT_ARCHIVE_PATH=WFM-QRE\INCOMING\WFM_ARACHIVE\FORM16_CRDT + diff --git a/package.json b/package.json index 51db05a..6e6728b 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,6 @@ "seed:demo-requests": "ts-node -r tsconfig-paths/register src/scripts/seed-demo-requests.ts", "seed:demo-dealers": "ts-node -r tsconfig-paths/register src/scripts/seed-demo-dealers.ts", "cleanup:dealer-claims": "ts-node -r tsconfig-paths/register src/scripts/cleanup-dealer-claims.ts", - // "clear:form16-and-demo": "ts-node -r tsconfig-paths/register src/scripts/clear-form16-and-demo-data.ts", - // "clear:26as": "ts-node -r tsconfig-paths/register src/scripts/clear-26as-data.ts", "redis:start": "docker run -d --name redis-workflow -p 6379:6379 redis:7-alpine", "redis:stop": "docker rm -f redis-workflow", "test": "jest --passWithNoTests --forceExit", @@ -110,4 +108,4 @@ "node": ">=22.0.0", "npm": ">=10.0.0" } -} +} \ No newline at end of file diff --git a/src/scripts/test-wfm-archive.ts b/src/scripts/test-wfm-archive.ts new file mode 100644 index 0000000..8106ac3 --- /dev/null +++ b/src/scripts/test-wfm-archive.ts @@ -0,0 +1,65 @@ +import { wfmFileService } from '../services/wfmFile.service'; +import logger from '../utils/logger'; +import dotenv from 'dotenv'; +import fs from 'fs'; +import path from 'path'; + +// Load environment variables +dotenv.config(); + +async function testWfmArchiveFinal() { + try { + console.log('Starting WFM Final Verification Test...'); + + // 1. Test Claim CSV Archiving (GST) + const claimData = [{ + TRNS_UNIQ_NO: 'TEST_FINAL_123', + CLAIM_NUMBER: 'CLI_FINAL_001', + DEALER_CODE: '6059', + CLAIM_AMT: 1000.00 + }]; + + const claimFileName = `ARCHIVE_FINAL_CLAIM_${Date.now()}.csv`; + console.log(`Testing Claim CSV: ${claimFileName}`); + const claimFilePath = await wfmFileService.generateIncomingClaimCSV(claimData, claimFileName, false); // false = GST + + console.log(`Main Claim CSV: ${claimFilePath}`); + const expectedArchivePath = claimFilePath.replace('WFM_MAIN', 'WFM_ARACHIVE'); + console.log(`Archive Claim CSV expected at: ${expectedArchivePath}`); + + if (fs.existsSync(claimFilePath) && fs.existsSync(expectedArchivePath)) { + console.log('✅ Claim CSV and Archive verified!'); + } else { + if (!fs.existsSync(claimFilePath)) console.error('❌ Main Claim CSV not found!'); + if (!fs.existsSync(expectedArchivePath)) console.error('❌ Archive Claim CSV not found!'); + } + + // 2. Test Form 16 CSV Archiving (Credit) + const form16Data = [{ + DEALER_CODE: '6059', + QUARTER: 'Q1', + YEAR: '2024-25', + AMOUNT: 500.00 + }]; + + const form16FileName = `ARCHIVE_FINAL_FORM16_${Date.now()}.csv`; + console.log(`\nTesting Form 16 CSV: ${form16FileName}`); + const form16FilePath = await wfmFileService.generateForm16IncomingCSV(form16Data, form16FileName, 'credit'); + + console.log(`Main Form 16 CSV: ${form16FilePath}`); + const expectedForm16ArchivePath = form16FilePath.replace('WFM_MAIN', 'WFM_ARACHIVE'); + console.log(`Archive Form 16 CSV expected at: ${expectedForm16ArchivePath}`); + + if (fs.existsSync(form16FilePath) && fs.existsSync(expectedForm16ArchivePath)) { + console.log('✅ Form 16 CSV and Archive verified!'); + } else { + if (!fs.existsSync(form16FilePath)) console.error('❌ Main Form 16 CSV not found!'); + if (!fs.existsSync(expectedForm16ArchivePath)) console.error('❌ Archive Form 16 CSV not found!'); + } + + } catch (error) { + console.error('❌ Verification failed:', error); + } +} + +testWfmArchiveFinal(); diff --git a/src/services/wfmFile.service.ts b/src/services/wfmFile.service.ts index 03f45fb..556703b 100644 --- a/src/services/wfmFile.service.ts +++ b/src/services/wfmFile.service.ts @@ -20,14 +20,24 @@ const DEFAULT_FORM16_DEBIT_OUTGOING = path.join('WFM-QRE', 'OUTGOING', 'WFM_SAP_ */ export class WFMFileService { private basePath: string; + + // --- INCOMING PATHS (WFM_MAIN / WFM_ARACHIVE) --- private incomingGstClaimsPath: string; + private incomingArchiveGstClaimsPath: string; + private incomingNonGstClaimsPath: string; + private incomingArchiveNonGstClaimsPath: string; + + private form16IncomingCreditPath: string; + private incomingArchiveForm16CreditPath: string; + + private form16IncomingDebitPath: string; + private incomingArchiveForm16DebitPath: string; + + // --- OUTGOING PATHS (WFM_SAP_MAIN) --- private outgoingGstClaimsPath: string; private outgoingNonGstClaimsPath: string; - /** Form 16 credit notes: INCOMING/WFM_MAIN/FORM16_CRDT */ - private form16IncomingCreditPath: string; - /** Form 16 debit notes: INCOMING/WFM_MAIN/FORM16_DEBT */ - private form16IncomingDebitPath: string; + /** Form 16 credit responses: OUTGOING/WFM_SAP_MAIN/FORM16_CRDT */ private form16OutgoingCreditPath: string; /** Form 16 debit responses: OUTGOING/WFM_SAP_MAIN/FORM16_DBT */ @@ -35,17 +45,28 @@ export class WFMFileService { constructor() { this.basePath = process.env.WFM_BASE_PATH || 'C:\\WFM'; - this.incomingGstClaimsPath = process.env.WFM_INCOMING_GST_CLAIMS_PATH || 'WFM-QRE\\INCOMING\\WFM_MAIN\\DLR_INC_CLAIMS_GST'; - this.incomingNonGstClaimsPath = process.env.WFM_INCOMING_NON_GST_CLAIMS_PATH || 'WFM-QRE\\INCOMING\\WFM_MAIN\\DLR_INC_CLAIMS_NON_GST'; - this.outgoingGstClaimsPath = process.env.WFM_OUTGOING_GST_CLAIMS_PATH || 'WFM-QRE\\OUTGOING\\WFM_SAP_MAIN\\DLR_INC_CLAIMS_GST'; - this.outgoingNonGstClaimsPath = process.env.WFM_OUTGOING_NON_GST_CLAIMS_PATH || 'WFM-QRE\\OUTGOING\\WFM_SAP_MAIN\\DLR_INC_CLAIMS_NON_GST'; + + // Initialize Incoming Paths from .env or defaults + this.incomingGstClaimsPath = process.env.WFM_INCOMING_GST_CLAIMS_PATH || DEFAULT_CLAIMS_INCOMING + '_GST'; + this.incomingArchiveGstClaimsPath = process.env.WFM_ARCHIVE_GST_CLAIMS_PATH || path.join('WFM-QRE', 'INCOMING', 'WFM_ARACHIVE', 'DLR_INC_CLAIMS_GST'); + + this.incomingNonGstClaimsPath = process.env.WFM_INCOMING_NON_GST_CLAIMS_PATH || DEFAULT_CLAIMS_INCOMING + '_NON_GST'; + this.incomingArchiveNonGstClaimsPath = process.env.WFM_ARCHIVE_NON_GST_CLAIMS_PATH || path.join('WFM-QRE', 'INCOMING', 'WFM_ARACHIVE', 'DLR_INC_CLAIMS_NON_GST'); // Backwards-compatible: support legacy WFM_FORM16_INCOMING_PATH if specific credit/debit paths are not set const legacyForm16Incoming = process.env.WFM_FORM16_INCOMING_PATH; + this.form16IncomingCreditPath = process.env.WFM_FORM16_CREDIT_INCOMING_PATH || legacyForm16Incoming || DEFAULT_FORM16_CREDIT_INCOMING; + this.incomingArchiveForm16CreditPath = process.env.WFM_FORM16_CREDIT_ARCHIVE_PATH || path.join('WFM-QRE', 'INCOMING', 'WFM_ARACHIVE', 'FORM16_CRDT'); + this.form16IncomingDebitPath = process.env.WFM_FORM16_DEBIT_INCOMING_PATH || legacyForm16Incoming || DEFAULT_FORM16_DEBIT_INCOMING; + this.incomingArchiveForm16DebitPath = process.env.WFM_FORM16_DEBIT_ARCHIVE_PATH || path.join('WFM-QRE', 'INCOMING', 'WFM_ARACHIVE', 'FORM16_DBT'); + + // Initialize Outgoing Paths from .env or defaults + this.outgoingGstClaimsPath = process.env.WFM_OUTGOING_GST_CLAIMS_PATH || DEFAULT_CLAIMS_OUTGOING + '_GST'; + this.outgoingNonGstClaimsPath = process.env.WFM_OUTGOING_NON_GST_CLAIMS_PATH || DEFAULT_CLAIMS_OUTGOING + '_NON_GST'; // Outgoing: allow specific credit/debit overrides; fall back to legacy single path for credit const legacyForm16Outgoing = process.env.WFM_FORM16_OUTGOING_PATH; @@ -80,7 +101,8 @@ export class WFMFileService { const targetDir = path.join(this.basePath, targetPath); this.ensureDirectoryExists(targetDir); - const filePath = path.join(targetDir, fileName.endsWith('.csv') ? fileName : `${fileName}.csv`); + const fileNameWithExt = fileName.endsWith('.csv') ? fileName : `${fileName}.csv`; + const filePath = path.join(targetDir, fileNameWithExt); // Simple CSV generation logic with pipe separator and no quotes const headers = Object.keys(data[0] || {}).join('|'); @@ -90,6 +112,19 @@ export class WFMFileService { fs.writeFileSync(filePath, csvContent); logger.info(`[WFMFileService] Generated CSV at: ${filePath}`); + // Archive copy + try { + const archivePathPrefix = isNonGst ? this.incomingArchiveNonGstClaimsPath : this.incomingArchiveGstClaimsPath; + const archiveDir = path.join(this.basePath, archivePathPrefix); + this.ensureDirectoryExists(archiveDir); + const archivePath = path.join(archiveDir, fileNameWithExt); + fs.writeFileSync(archivePath, csvContent); + logger.info(`[WFMFileService] Archived CSV copy at: ${archivePath}`); + } catch (archiveError) { + logger.error('[WFMFileService] Error saving archive copy:', archiveError); + // Don't throw archive error to avoid failing the main process + } + return filePath; } catch (error: any) { if (error.code === 'EBUSY' && retryCount < maxRetries) { @@ -171,7 +206,8 @@ export class WFMFileService { const targetDir = path.join(this.basePath, targetPath); this.ensureDirectoryExists(targetDir); - const filePath = path.join(targetDir, fileName.endsWith('.csv') ? fileName : `${fileName}.csv`); + const fileNameWithExt = fileName.endsWith('.csv') ? fileName : `${fileName}.csv`; + const filePath = path.join(targetDir, fileNameWithExt); // Pipe separator, no double quotes (values as plain strings) const keys = Object.keys(data[0] || {}); @@ -187,6 +223,19 @@ export class WFMFileService { fs.writeFileSync(filePath, csvContent); logger.info(`[WFMFileService] Form 16 CSV generated at: ${filePath}`); + // Archive copy + try { + const archivePathPrefix = type === 'debit' ? this.incomingArchiveForm16DebitPath : this.incomingArchiveForm16CreditPath; + const archiveDir = path.join(this.basePath, archivePathPrefix); + this.ensureDirectoryExists(archiveDir); + const archivePath = path.join(archiveDir, fileNameWithExt); + fs.writeFileSync(archivePath, csvContent); + logger.info(`[WFMFileService] Form 16 archived copy at: ${archivePath}`); + } catch (archiveError) { + logger.error('[WFMFileService] Error saving Form 16 archive copy:', archiveError); + // Don't throw archive error to avoid failing the main process + } + return filePath; } catch (error: any) { if (error.code === 'EBUSY' && retryCount < maxRetries) {