CSV file upload to WFM folder implemeted
This commit is contained in:
parent
f679317d4a
commit
b6ca3c7f9f
@ -1 +1 @@
|
||||
import{a as s}from"./index-yOqi1S1C.js";import"./radix-vendor-CYvDqP9X.js";import"./charts-vendor-BVfwAPj-.js";import"./utils-vendor-BTBPSQfW.js";import"./ui-vendor-CX5oLBI_.js";import"./socket-vendor-TjCxX7sJ.js";import"./redux-vendor-tbZCm13o.js";import"./router-vendor-B_rK4TXr.js";async function m(n){return(await s.post(`/conclusions/${n}/generate`)).data.data}async function f(n,t){return(await s.post(`/conclusions/${n}/finalize`,{finalRemark:t})).data.data}async function d(n){var t;try{return(await s.get(`/conclusions/${n}`)).data.data}catch(o){if(((t=o.response)==null?void 0:t.status)===404)return null;throw o}}export{f as finalizeConclusion,m as generateConclusion,d as getConclusion};
|
||||
import{a as s}from"./index-CULgQ-8S.js";import"./radix-vendor-CYvDqP9X.js";import"./charts-vendor-BVfwAPj-.js";import"./utils-vendor-BTBPSQfW.js";import"./ui-vendor-CX5oLBI_.js";import"./socket-vendor-TjCxX7sJ.js";import"./redux-vendor-tbZCm13o.js";import"./router-vendor-B_rK4TXr.js";async function m(n){return(await s.post(`/conclusions/${n}/generate`)).data.data}async function f(n,t){return(await s.post(`/conclusions/${n}/finalize`,{finalRemark:t})).data.data}async function d(n){var t;try{return(await s.get(`/conclusions/${n}`)).data.data}catch(o){if(((t=o.response)==null?void 0:t.status)===404)return null;throw o}}export{f as finalizeConclusion,m as generateConclusion,d as getConclusion};
|
||||
File diff suppressed because one or more lines are too long
@ -13,7 +13,7 @@
|
||||
<!-- Preload essential fonts and icons -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<script type="module" crossorigin src="/assets/index-yOqi1S1C.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-CULgQ-8S.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/charts-vendor-BVfwAPj-.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/radix-vendor-CYvDqP9X.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/utils-vendor-BTBPSQfW.js">
|
||||
|
||||
@ -1082,4 +1082,31 @@ export class DealerClaimController {
|
||||
return ResponseHandler.error(res, 'Failed to download invoice CSV', 500, errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-trigger WFM CSV push (Step 7)
|
||||
* POST /api/v1/dealer-claims/:requestId/wfm/retrigger
|
||||
*/
|
||||
async retriggerWFMPush(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const { requestId: identifier } = req.params;
|
||||
|
||||
const workflow = await this.findWorkflowByIdentifier(identifier);
|
||||
if (!workflow) {
|
||||
return ResponseHandler.error(res, 'Workflow request not found', 404);
|
||||
}
|
||||
|
||||
const requestId = (workflow as any).id || (workflow as any).requestId;
|
||||
|
||||
await this.dealerClaimService.pushWFMCSV(requestId);
|
||||
|
||||
return ResponseHandler.success(res, {
|
||||
message: 'WFM CSV push re-triggered successfully'
|
||||
}, 'WFM push re-triggered');
|
||||
} catch (error: any) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
logger.error('[DealerClaimController] Error re-triggering WFM push:', error);
|
||||
return ResponseHandler.error(res, 'Failed to re-trigger WFM push', 500, errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
50
src/migrations/20260309-add-wfm-push-fields.ts
Normal file
50
src/migrations/20260309-add-wfm-push-fields.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import { QueryInterface, DataTypes } from 'sequelize';
|
||||
|
||||
/**
|
||||
* Helper function to check if a column exists in a table
|
||||
*/
|
||||
async function columnExists(
|
||||
queryInterface: QueryInterface,
|
||||
tableName: string,
|
||||
columnName: string
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const tableDescription = await queryInterface.describeTable(tableName);
|
||||
return columnName in tableDescription;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function up(queryInterface: QueryInterface): Promise<void> {
|
||||
const tableName = 'claim_invoices';
|
||||
|
||||
// Add wfm_push_status
|
||||
if (!(await columnExists(queryInterface, tableName, 'wfm_push_status'))) {
|
||||
await queryInterface.addColumn(tableName, 'wfm_push_status', {
|
||||
type: DataTypes.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: 'PENDING'
|
||||
});
|
||||
}
|
||||
|
||||
// Add wfm_push_error
|
||||
if (!(await columnExists(queryInterface, tableName, 'wfm_push_error'))) {
|
||||
await queryInterface.addColumn(tableName, 'wfm_push_error', {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(queryInterface: QueryInterface): Promise<void> {
|
||||
const tableName = 'claim_invoices';
|
||||
|
||||
if (await columnExists(queryInterface, tableName, 'wfm_push_status')) {
|
||||
await queryInterface.removeColumn(tableName, 'wfm_push_status');
|
||||
}
|
||||
|
||||
if (await columnExists(queryInterface, tableName, 'wfm_push_error')) {
|
||||
await queryInterface.removeColumn(tableName, 'wfm_push_error');
|
||||
}
|
||||
}
|
||||
@ -39,13 +39,15 @@ interface ClaimInvoiceAttributes {
|
||||
pwcResponse?: any;
|
||||
irpResponse?: any;
|
||||
errorMessage?: string;
|
||||
wfmPushStatus?: 'PENDING' | 'SUCCESS' | 'FAILED';
|
||||
wfmPushError?: string | null;
|
||||
generatedAt?: Date;
|
||||
description?: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
interface ClaimInvoiceCreationAttributes extends Optional<ClaimInvoiceAttributes, 'invoiceId' | 'invoiceNumber' | 'dmsNumber' | 'invoiceDate' | 'irn' | 'ackNo' | 'ackDate' | 'signedInvoice' | 'signedInvoiceUrl' | 'dealerClaimNumber' | 'dealerClaimDate' | 'billingNo' | 'billingDate' | 'taxableValue' | 'cgstTotal' | 'sgstTotal' | 'igstTotal' | 'utgstTotal' | 'cessTotal' | 'tcsAmt' | 'roundOffAmt' | 'placeOfSupply' | 'totalValueInWords' | 'taxValueInWords' | 'creditNature' | 'consignorGsin' | 'gstinDate' | 'filePath' | 'qrCode' | 'qrImage' | 'pwcResponse' | 'irpResponse' | 'errorMessage' | 'generatedAt' | 'description' | 'createdAt' | 'updatedAt'> { }
|
||||
interface ClaimInvoiceCreationAttributes extends Optional<ClaimInvoiceAttributes, 'invoiceId' | 'invoiceNumber' | 'dmsNumber' | 'invoiceDate' | 'irn' | 'ackNo' | 'ackDate' | 'signedInvoice' | 'signedInvoiceUrl' | 'dealerClaimNumber' | 'dealerClaimDate' | 'billingNo' | 'billingDate' | 'taxableValue' | 'cgstTotal' | 'sgstTotal' | 'igstTotal' | 'utgstTotal' | 'cessTotal' | 'tcsAmt' | 'roundOffAmt' | 'placeOfSupply' | 'totalValueInWords' | 'taxValueInWords' | 'creditNature' | 'consignorGsin' | 'gstinDate' | 'filePath' | 'qrCode' | 'qrImage' | 'pwcResponse' | 'irpResponse' | 'errorMessage' | 'wfmPushStatus' | 'wfmPushError' | 'generatedAt' | 'description' | 'createdAt' | 'updatedAt'> { }
|
||||
|
||||
class ClaimInvoice extends Model<ClaimInvoiceAttributes, ClaimInvoiceCreationAttributes> implements ClaimInvoiceAttributes {
|
||||
public invoiceId!: string;
|
||||
@ -84,6 +86,8 @@ class ClaimInvoice extends Model<ClaimInvoiceAttributes, ClaimInvoiceCreationAtt
|
||||
public pwcResponse?: any;
|
||||
public irpResponse?: any;
|
||||
public errorMessage?: string;
|
||||
public wfmPushStatus?: 'PENDING' | 'SUCCESS' | 'FAILED';
|
||||
public wfmPushError?: string | null;
|
||||
public generatedAt?: Date;
|
||||
public description?: string;
|
||||
public createdAt!: Date;
|
||||
@ -280,6 +284,17 @@ ClaimInvoice.init(
|
||||
allowNull: true,
|
||||
field: 'error_message',
|
||||
},
|
||||
wfmPushStatus: {
|
||||
type: DataTypes.STRING(20),
|
||||
allowNull: true,
|
||||
defaultValue: 'PENDING',
|
||||
field: 'wfm_push_status'
|
||||
},
|
||||
wfmPushError: {
|
||||
type: DataTypes.TEXT,
|
||||
allowNull: true,
|
||||
field: 'wfm_push_error'
|
||||
},
|
||||
generatedAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: true,
|
||||
|
||||
@ -98,6 +98,7 @@ router.put('/:requestId/io', authenticateToken, sapLimiter, validateParams(reque
|
||||
*/
|
||||
router.put('/:requestId/e-invoice', authenticateToken, sapLimiter, validateParams(requestIdParamsSchema), validateBody(updateEInvoiceSchema), asyncHandler(dealerClaimController.updateEInvoice.bind(dealerClaimController)));
|
||||
router.get('/:requestId/e-invoice/pdf', authenticateToken, validateParams(requestIdParamsSchema), asyncHandler(dealerClaimController.downloadInvoicePdf.bind(dealerClaimController)));
|
||||
router.post('/:requestId/wfm/retrigger', authenticateToken, validateParams(requestIdParamsSchema), asyncHandler(dealerClaimController.retriggerWFMPush.bind(dealerClaimController)));
|
||||
|
||||
/**
|
||||
* @route PUT /api/v1/dealer-claims/:requestId/credit-note
|
||||
|
||||
@ -162,6 +162,7 @@ async function runMigrations(): Promise<void> {
|
||||
const m47 = require('../migrations/20260216-create-api-tokens');
|
||||
const m48 = require('../migrations/20260216-add-qty-hsn-to-expenses'); // Added new migration
|
||||
const m49 = require('../migrations/20260302-refine-dealer-claim-schema');
|
||||
const m50 = require('../migrations/20260309-add-wfm-push-fields');
|
||||
|
||||
const migrations = [
|
||||
{ name: '2025103000-create-users', module: m0 },
|
||||
@ -216,6 +217,7 @@ async function runMigrations(): Promise<void> {
|
||||
{ name: '20260216-create-api-tokens', module: m47 },
|
||||
{ name: '20260216-add-qty-hsn-to-expenses', module: m48 }, // Added to array
|
||||
{ name: '20260302-refine-dealer-claim-schema', module: m49 },
|
||||
{ name: '20260309-add-wfm-push-fields', module: m50 },
|
||||
];
|
||||
|
||||
// Dynamically import sequelize after secrets are loaded
|
||||
|
||||
@ -52,6 +52,7 @@ import * as m46 from '../migrations/20260216-add-qty-hsn-to-expenses';
|
||||
import * as m47 from '../migrations/20260217-add-is-service-to-expenses';
|
||||
import * as m48 from '../migrations/20260217-create-claim-invoice-items';
|
||||
import * as m49 from '../migrations/20260302-refine-dealer-claim-schema';
|
||||
import * as m50 from '../migrations/20260309-add-wfm-push-fields';
|
||||
|
||||
interface Migration {
|
||||
name: string;
|
||||
@ -65,7 +66,8 @@ const migrations: Migration[] = [
|
||||
{ name: '20260216-add-qty-hsn-to-expenses', module: m46 },
|
||||
{ name: '20260217-add-is-service-to-expenses', module: m47 },
|
||||
{ name: '20260217-create-claim-invoice-items', module: m48 },
|
||||
{ name: '20260302-refine-dealer-claim-schema', module: m49 }
|
||||
{ name: '20260302-refine-dealer-claim-schema', module: m49 },
|
||||
{ name: '20260309-add-wfm-push-fields', module: m50 }
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
48
src/scripts/test-wfm-csv.ts
Normal file
48
src/scripts/test-wfm-csv.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { wfmFileService } from '../services/wfmFile.service';
|
||||
import logger from '../utils/logger';
|
||||
import dotenv from 'dotenv';
|
||||
import path from 'path';
|
||||
|
||||
// Load environment variables
|
||||
dotenv.config();
|
||||
|
||||
async function testOfficialCSVGeneration() {
|
||||
try {
|
||||
console.log('Starting WFM Official CSV Generation Test...');
|
||||
|
||||
const officialData = [{
|
||||
TRNS_UNIQ_NO: '1342774290',
|
||||
CLAIM_NUMBER: 'CLI000012833733',
|
||||
INV_NUMBER: 'INV007593742231',
|
||||
DEALER_CODE: '6059',
|
||||
IO_NUMBER: '439887',
|
||||
CLAIM_DOC_TYP: 'ZMBS',
|
||||
CLAIM_DATE: '20190627',
|
||||
CLAIM_AMT: 3931.539,
|
||||
GST_AMT: '185.00',
|
||||
GST_PERCENTAG: 18
|
||||
}];
|
||||
|
||||
const fileName = `OFFICIAL_TEST_${Date.now()}.csv`;
|
||||
const filePath = await wfmFileService.generateIncomingClaimCSV(officialData, fileName);
|
||||
|
||||
console.log(`✅ Success! Official CSV generated at: ${filePath}`);
|
||||
|
||||
// Verify file existence and content
|
||||
const fs = require('fs');
|
||||
if (fs.existsSync(filePath)) {
|
||||
console.log('File existence verified on disk.');
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
console.log('--- CSV Content ---');
|
||||
console.log(content);
|
||||
console.log('-------------------');
|
||||
} else {
|
||||
console.error('❌ Error: File not found on disk!');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Test failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
testOfficialCSVGeneration();
|
||||
@ -10,6 +10,7 @@ import { InternalOrder, IOStatus } from '../models/InternalOrder';
|
||||
import { ClaimBudgetTracking, BudgetStatus } from '../models/ClaimBudgetTracking';
|
||||
import { ClaimInvoice } from '../models/ClaimInvoice';
|
||||
import { ClaimCreditNote } from '../models/ClaimCreditNote';
|
||||
import { ClaimInvoiceItem } from '../models/ClaimInvoiceItem';
|
||||
import { DealerCompletionExpense } from '../models/DealerCompletionExpense';
|
||||
import { ApprovalLevel } from '../models/ApprovalLevel';
|
||||
import { Participant } from '../models/Participant';
|
||||
@ -24,6 +25,7 @@ import { generateRequestNumber } from '../utils/helpers';
|
||||
import { Priority, WorkflowStatus, ApprovalStatus, ParticipantType } from '../types/common.types';
|
||||
import { sapIntegrationService } from './sapIntegration.service';
|
||||
import { pwcIntegrationService } from './pwcIntegration.service';
|
||||
import { wfmFileService } from './wfmFile.service';
|
||||
import { findDealerLocally } from './dealer.service';
|
||||
import { notificationService } from './notification.service';
|
||||
import { activityService } from './activity.service';
|
||||
@ -2080,6 +2082,11 @@ export class DealerClaimService {
|
||||
logger.info(`[DealerClaimService] E-Invoice details manually updated for request: ${requestId}`);
|
||||
}
|
||||
|
||||
// Generate CSV for WFM system (INCOMING\WFM_MAIN\DLR_INC_CLAIMS)
|
||||
await this.pushWFMCSV(requestId).catch((err: Error) => {
|
||||
logger.error('[DealerClaimService] Initial WFM push failed:', err);
|
||||
});
|
||||
|
||||
// Generate PDF Invoice
|
||||
try {
|
||||
const { pdfService } = require('./pdf.service');
|
||||
@ -3563,5 +3570,81 @@ export class DealerClaimService {
|
||||
return plain;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Push CSV to WFM folder and track status
|
||||
* This is used by both auto-trigger and manual re-trigger
|
||||
*/
|
||||
async pushWFMCSV(requestId: string): Promise<void> {
|
||||
const invoice = await ClaimInvoice.findOne({ where: { requestId } });
|
||||
if (!invoice) {
|
||||
throw new Error('Invoice not found');
|
||||
}
|
||||
|
||||
try {
|
||||
const [invoiceItems, claimDetails, internalOrder] = await Promise.all([
|
||||
ClaimInvoiceItem.findAll({ where: { requestId } }),
|
||||
DealerClaimDetails.findOne({ where: { requestId } }),
|
||||
InternalOrder.findOne({ where: { requestId } })
|
||||
]);
|
||||
|
||||
if (!claimDetails) {
|
||||
throw new Error('Dealer claim details not found');
|
||||
}
|
||||
|
||||
const requestNumber = (await WorkflowRequest.findByPk(requestId))?.requestNumber || 'UNKNOWN';
|
||||
|
||||
if (invoiceItems.length > 0) {
|
||||
let sapRefNo = '';
|
||||
if (claimDetails.activityType) {
|
||||
const activity = await ActivityType.findOne({ where: { title: claimDetails.activityType } });
|
||||
sapRefNo = activity?.sapRefNo || '';
|
||||
}
|
||||
|
||||
const formatDate = (date: any) => {
|
||||
const d = new Date(date);
|
||||
const year = d.getFullYear();
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(d.getDate()).padStart(2, '0');
|
||||
return `${year}${month}${day}`;
|
||||
};
|
||||
|
||||
const csvData = invoiceItems.map((item: any) => {
|
||||
const totalTax = Number(item.igstAmt || 0) + Number(item.cgstAmt || 0) + Number(item.sgstAmt || 0) + Number(item.utgstAmt || 0);
|
||||
|
||||
return {
|
||||
TRNS_UNIQ_NO: item.transactionCode || '',
|
||||
CLAIM_NUMBER: requestNumber,
|
||||
INV_NUMBER: invoice.invoiceNumber || '',
|
||||
DEALER_CODE: claimDetails.dealerCode,
|
||||
IO_NUMBER: internalOrder?.ioNumber || '',
|
||||
CLAIM_DOC_TYP: sapRefNo,
|
||||
CLAIM_DATE: formatDate(invoice.invoiceDate || new Date()),
|
||||
CLAIM_AMT: item.assAmt,
|
||||
GST_AMT: totalTax.toFixed(2),
|
||||
GST_PERCENTAG: item.gstRt
|
||||
};
|
||||
});
|
||||
|
||||
await wfmFileService.generateIncomingClaimCSV(csvData, `CN_${claimDetails.dealerCode}_${requestNumber}.csv`);
|
||||
|
||||
await invoice.update({
|
||||
wfmPushStatus: 'SUCCESS',
|
||||
wfmPushError: null
|
||||
});
|
||||
|
||||
logger.info(`[DealerClaimService] WFM CSV successfully pushed for request ${requestNumber}`);
|
||||
} else {
|
||||
logger.warn(`[DealerClaimService] No invoice items found for WFM push: ${requestNumber}`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error pushing to WFM';
|
||||
await invoice.update({
|
||||
wfmPushStatus: 'FAILED',
|
||||
wfmPushError: errorMessage
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
83
src/services/wfmFile.service.ts
Normal file
83
src/services/wfmFile.service.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import logger from '../utils/logger';
|
||||
|
||||
/**
|
||||
* WFM File Service
|
||||
* Handles generation and storage of CSV files in the WFM folder structure
|
||||
*/
|
||||
export class WFMFileService {
|
||||
private basePath: string;
|
||||
private incomingClaimsPath: string;
|
||||
private outgoingClaimsPath: string;
|
||||
|
||||
constructor() {
|
||||
this.basePath = process.env.WFM_BASE_PATH || 'C:\\WFM';
|
||||
this.incomingClaimsPath = process.env.WFM_INCOMING_CLAIMS_PATH || 'WFM-QRE\\INCOMING\\WFM_MAIN\\DLR_INC_CLAIMS';
|
||||
this.outgoingClaimsPath = process.env.WFM_OUTGOING_CLAIMS_PATH || 'WFM-QRE\\OUTGOING\\WFM_SAP_MAIN\\DLR_INC_CLAIMS';
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the target directory exists
|
||||
*/
|
||||
private ensureDirectoryExists(dirPath: string): void {
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
fs.mkdirSync(dirPath, { recursive: true });
|
||||
logger.info(`[WFMFileService] Created directory: ${dirPath}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a CSV file for a credit note/claim and store it in the INCOMING folder
|
||||
* @param data The data to be written to the CSV
|
||||
* @param fileName The name of the file (e.g., CLAIM_12345.csv)
|
||||
*/
|
||||
async generateIncomingClaimCSV(data: any[], fileName: string): Promise<string> {
|
||||
const maxRetries = 3;
|
||||
let retryCount = 0;
|
||||
|
||||
while (retryCount <= maxRetries) {
|
||||
try {
|
||||
const targetDir = path.join(this.basePath, this.incomingClaimsPath);
|
||||
this.ensureDirectoryExists(targetDir);
|
||||
|
||||
const filePath = path.join(targetDir, fileName.endsWith('.csv') ? fileName : `${fileName}.csv`);
|
||||
|
||||
// Simple CSV generation logic
|
||||
const headers = Object.keys(data[0] || {}).join(',');
|
||||
const rows = data.map(item => Object.values(item).map(val => `"${val}"`).join(',')).join('\n');
|
||||
const csvContent = `${headers}\n${rows}`;
|
||||
|
||||
fs.writeFileSync(filePath, csvContent);
|
||||
logger.info(`[WFMFileService] Generated CSV at: ${filePath}`);
|
||||
|
||||
return filePath;
|
||||
} catch (error: any) {
|
||||
if (error.code === 'EBUSY' && retryCount < maxRetries) {
|
||||
retryCount++;
|
||||
const delay = retryCount * 1000;
|
||||
logger.warn(`[WFMFileService] File busy/locked, retrying in ${delay}ms (Attempt ${retryCount}/${maxRetries}): ${fileName}`);
|
||||
await new Promise(resolve => setTimeout(resolve, delay));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (error.code === 'EBUSY') {
|
||||
throw new Error(`File is locked or open in another program (e.g., Excel). Please close '${fileName}' and try again.`);
|
||||
}
|
||||
|
||||
logger.error('[WFMFileService] Error generating incoming claim CSV:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
throw new Error(`Failed to generate CSV after ${maxRetries} retries. Please ensure the file '${fileName}' is not open in any other application.`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the absolute path for an outgoing claim file
|
||||
*/
|
||||
getOutgoingPath(fileName: string): string {
|
||||
return path.join(this.basePath, this.outgoingClaimsPath, fileName);
|
||||
}
|
||||
}
|
||||
|
||||
export const wfmFileService = new WFMFileService();
|
||||
Loading…
Reference in New Issue
Block a user