BE/src/utils/helper.ts

1572 lines
63 KiB
TypeScript
Raw Normal View History

2025-02-24 10:32:41 +05:30
import {
BadRequestException,
InternalServerErrorException,
Logger,
} from '@nestjs/common';
import * as oracledb from 'oracledb';
2025-08-12 15:27:32 +05:30
const PDFDocument = require('pdfkit');
const fs = require('fs');
const path = require('path');
const PDFMerger = require('pdf-merger-js').default;
import * as fsPromises from 'fs/promises';
import { BadRequestException as BR } from 'src/exceptions/badRequest.exception';
import { existsSync, readFileSync } from 'fs';
import { PDFDocument as pdfl, TextAlignment, PDFTextField, PDFCheckBox, PDFRadioGroup, PDFDropdown, PDFOptionList } from 'pdf-lib';
import { PrintCarnetDTO } from 'src/dto/property.dto';
2025-02-24 10:32:41 +05:30
const logger = new Logger('Helper');
export const handleError = (error: any, context: string = 'UnknownService'): never => {
2025-08-12 15:27:32 +05:30
if (error instanceof BadRequestException || error instanceof BR) {
2025-02-24 10:32:41 +05:30
logger.warn(`[${context}] ${error.message}`);
throw error;
}
if (error.message?.includes('NJS-107')) {
logger.warn(`[${context}] Invalid cursor encountered: ${error.message}`);
throw new BadRequestException('Invalid database response.');
}
if (error.message?.includes('ORA-')) {
logger.error(`[${context}] Oracle error occurred: ${error.message}`);
throw new InternalServerErrorException(error.message);
}
logger.error(`[${context}] Unexpected error:`, error.stack || error);
throw new InternalServerErrorException(error.message || 'Internal error');
};
export const closeOracleDbConnection = async (connection: any, context: string = 'UnknownService'): Promise<void> => {
if (connection) {
try {
await connection.close();
} catch (closeErr) {
logger.error(`[${context}] Failed to close DB connection`, closeErr.stack || closeErr);
}
}
};
export const fetchCursor = async <T>(cursor: oracledb.ResultSet<T>, context: string = 'UnknownService'): Promise<T[]> => {
try {
const rows = await cursor.getRows();
await cursor.close();
return rows;
} catch (err) {
logger.error(`[${context}] Failed to fetch from cursor`, err.stack || err);
throw new InternalServerErrorException('Error reading data from database.');
}
};
export const setEmptyStringsToNull = (obj: any): void => {
Object.keys(obj).forEach((key) => {
if (typeof obj[key] === 'object' && obj[key] !== null) {
setEmptyStringsToNull(obj[key]);
} else if (obj[key] === '') {
obj[key] = null;
}
});
}
2025-08-12 15:27:32 +05:30
export interface pdfGLData {
itemNo: number;
description: string;
noOfPieces: number;
weight: string;
itemValue: number;
countryOfOrigin: string
}
export interface pdfCarnetData {
carnetNo: string;
ISSUEDBY: string;
ISSUEDATE: string;
EXPDATE: string;
AUTHREP: string;
NOOFUSSETS: number;
NOOFFOREIGNSETS: number;
NOOFTRANSITSETS: number;
PRINTGOODSTOBEEXPORTED: string;
HOLDERDATATOPRINT: string;
CONTINUATIONSHEETS: number;
NEXTUSCFNO: number;
NEXTFOREIGNCFNO: number;
NEXTTRANSITCFNO: number;
contPageNo: number; // for GL table only
}
function formatNumber(num) {
if (isNaN(num)) return 'N/A';
return num.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
function toUSDateTime(isoString) {
const date = new Date(isoString);
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const year = date.getFullYear();
let hours = date.getHours();
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
const ampm = hours >= 12 ? 'PM' : 'AM';
hours = hours % 12 || 12;
// return `${month}-${day}-${year}, ${hours}:${minutes}:${seconds} ${ampm}`;
return `${year}-${month}-${day}`;
}
export function replaceSlashWithDash(input) {
return input.replace(/\//g, '-');
}
const PDF_LOCAL_PATH: string = "../../../public/carnet-pdf";
const PDF_SERVER_PATH: string = "../../public/carnet-pdf";
const PDF_URL = PDF_SERVER_PATH
export const generateGreenCoverPDF = (carnetData: pdfCarnetData) => {
return new Promise(async (resolve, reject) => {
try {
const templatePath = path.join(__dirname, PDF_URL, '1GreenCover.pdf');
const existingPdfBytes = fs.readFileSync(templatePath);
const pdfDoc = await pdfl.load(existingPdfBytes);
const form = pdfDoc.getForm();
const CURRENT_FONT = 11;
const fields = form.getFields();
const fieldInfo = fields.map(f => {
let type = 'unknown';
if (f instanceof PDFTextField) type = 'text';
else if (f instanceof PDFCheckBox) type = 'checkbox';
else if (f instanceof PDFRadioGroup) type = 'radio';
else if (f instanceof PDFDropdown) type = 'dropdown';
else if (f instanceof PDFOptionList) type = 'option-list';
return { name: f.getName(), type };
});
fieldInfo.forEach(x => {
if (x.type === "text" && x.name === 'CarnetNo') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.carnetNo);
}
else if (x.type === "text" && x.name === 'AuthBy') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.AUTHREP);
}
else if (x.type === "text" && x.name === 'ContnSheetNo') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.CONTINUATIONSHEETS + "");
}
else if (x.type === "text" && x.name === 'GoodstobeExportedas') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.PRINTGOODSTOBEEXPORTED);
}
else if (x.type === "text" && x.name === 'IssuedOn') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
const formattedDate = toUSDateTime(carnetData.ISSUEDATE)
nameField.setText(formattedDate);
}
else if (x.type === "text" && x.name === 'IssuedBy') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.ISSUEDBY);
}
else if (x.type === "text" && x.name === 'ValidUntil') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
const formattedDate = toUSDateTime(carnetData.EXPDATE)
nameField.setText(formattedDate);
}
else if (x.type === "text" && x.name === 'HolderNameAddress') {
const nameField = form.getTextField(x.name);
nameField.enableMultiline();
nameField.setFontSize(CURRENT_FONT);
const multilineAddress = carnetData.HOLDERDATATOPRINT.replace(/~/g, "\n");
nameField.setText(multilineAddress);
}
});
form.flatten();
const filledPdfBytes = await pdfDoc.save();
const outputPath = path.join(__dirname, PDF_URL, `${replaceSlashWithDash(carnetData.carnetNo)}p1.pdf`);
const writeStream = fs.createWriteStream(outputPath);
writeStream.write(filledPdfBytes);
writeStream.end();
writeStream.on('finish', () => {
// console.log("PDF has been successfully created and saved.");
resolve("p1 done"); // wait until file fully written
});
writeStream.on('error', err => {
console.error("Error writing PDF to file:", err);
reject(err);
});
} catch (err) {
reject(err);
}
});
};
export const generateUSCounterFoilFront = (carnetData: pdfCarnetData, t1: string, t2: string, dn: number, pn: number): Promise<number | any> => {
return new Promise(async (resolve, reject) => {
try {
const templatePath = path.join(__dirname, PDF_URL, '3USCounterFoilFront.pdf');
const existingPdfBytes = fs.readFileSync(templatePath);
const pdfDoc = await pdfl.load(existingPdfBytes);
const form = pdfDoc.getForm();
const CURRENT_FONT = 11;
const fields = form.getFields();
const fieldInfo = fields.map(f => {
let type = 'unknown';
if (f instanceof PDFTextField) type = 'text';
else if (f instanceof PDFCheckBox) type = 'checkbox';
else if (f instanceof PDFRadioGroup) type = 'radio';
else if (f instanceof PDFDropdown) type = 'dropdown';
else if (f instanceof PDFOptionList) type = 'option-list';
return { name: f.getName(), type };
});
// console.log(fieldInfo);
fieldInfo.forEach(x => {
if (x.type === "text" && x.name === 'Document No1') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t1 === "VALUE") {
nameField.setText(dn + "");
dn++;
}
else {
nameField.setText("VOID");
}
}
else if (x.type === "text" && x.name === 'CarnetNo') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.carnetNo);
}
else if (x.type === "text" && x.name === 'Document No2') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t2 === "VALUE") {
nameField.setText(dn + "");
dn++;
}
else {
nameField.setText("VOID");
}
}
else if (x.type === "text" && x.name === 'PrintVoidText1') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t1 === "VOID") {
nameField.setAlignment(TextAlignment.Center);
nameField.setText(t1);
}
}
else if (x.type === "text" && x.name === 'PrintVoidText2') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t2 === "VOID") {
nameField.setAlignment(TextAlignment.Center);
nameField.setText(t2);
}
}
});
form.flatten();
const filledPdfBytes = await pdfDoc.save();
const outputPath = path.join(__dirname, PDF_URL, `${replaceSlashWithDash(carnetData.carnetNo)}${pn}USFront.pdf`);
const writeStream = fs.createWriteStream(outputPath);
writeStream.write(filledPdfBytes);
writeStream.end();
pn++;
writeStream.on('finish', () => {
// console.log(`${dn}USFront.pdf has been successfully created and saved.`);
resolve(Number(dn)); // wait until file fully written
});
writeStream.on('error', err => {
console.error("Error writing PDF to file:", err);
reject(err);
});
} catch (err) {
reject(err);
}
});
}
export const generateUSCounterFoilBack = (carnetData: pdfCarnetData, t1: string, t2: string, dn: number, pn: number): Promise<number | any> => {
return new Promise(async (resolve, reject) => {
try {
const templatePath = path.join(__dirname, PDF_URL, '4USCounterFoilBack.pdf');
const existingPdfBytes = fs.readFileSync(templatePath);
const pdfDoc = await pdfl.load(existingPdfBytes);
const form = pdfDoc.getForm();
const CURRENT_FONT = 11;
const fields = form.getFields();
const fieldInfo = fields.map(f => {
let type = 'unknown';
if (f instanceof PDFTextField) type = 'text';
else if (f instanceof PDFCheckBox) type = 'checkbox';
else if (f instanceof PDFRadioGroup) type = 'radio';
else if (f instanceof PDFDropdown) type = 'dropdown';
else if (f instanceof PDFOptionList) type = 'option-list';
return { name: f.getName(), type };
});
fieldInfo.forEach(x => {
if (x.type === "text" && x.name === 'Document No1') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t1 === "VALUE") {
nameField.setText(dn + "");
dn++;
}
else {
nameField.setText("VOID");
}
}
else if (x.type === "text" && x.name === 'CarnetNo') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.carnetNo);
}
else if (x.type === "text" && x.name === 'Document No2') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t2 === "VALUE") {
nameField.setText(dn + "");
dn++;
}
else {
nameField.setText("VOID");
}
}
else if (x.type === "text" && x.name === 'PrintVoidText1') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t1 === "VOID") {
nameField.setAlignment(TextAlignment.Center);
nameField.setText(t1);
}
}
else if (x.type === "text" && x.name === 'PrintVoidText2') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t2 === "VOID") {
nameField.setAlignment(TextAlignment.Center);
nameField.setText(t2);
}
}
});
form.flatten();
const filledPdfBytes = await pdfDoc.save();
const outputPath = path.join(__dirname, PDF_URL, `${replaceSlashWithDash(carnetData.carnetNo)}${pn}USBack.pdf`);
const writeStream = fs.createWriteStream(outputPath);
writeStream.write(filledPdfBytes);
writeStream.end();
pn++
writeStream.on('finish', () => {
// console.log(`${pn}USBack.pdf` + " has been successfully created and saved.");
resolve(Number(dn)); // wait until file fully written
});
writeStream.on('error', err => {
console.error("Error writing PDF to file:", err);
reject(err);
});
} catch (err) {
reject(err);
}
});
}
export const generateFNCounterFoilFront = (carnetData: pdfCarnetData, t1: string, t2: string, dn: number, pn: number): Promise<number | any> => {
return new Promise(async (resolve, reject) => {
try {
const templatePath = path.join(__dirname, PDF_URL, '6ForeignCounterfoilFront.pdf');
const existingPdfBytes = fs.readFileSync(templatePath);
const pdfDoc = await pdfl.load(existingPdfBytes);
const form = pdfDoc.getForm();
const CURRENT_FONT = 11;
const fields = form.getFields();
const fieldInfo = fields.map(f => {
let type = 'unknown';
if (f instanceof PDFTextField) type = 'text';
else if (f instanceof PDFCheckBox) type = 'checkbox';
else if (f instanceof PDFRadioGroup) type = 'radio';
else if (f instanceof PDFDropdown) type = 'dropdown';
else if (f instanceof PDFOptionList) type = 'option-list';
return { name: f.getName(), type };
});
// console.log(fieldInfo);
fieldInfo.forEach(x => {
if (x.type === "text" && x.name === 'DocumentNo1') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t1 === "VALUE") {
nameField.setText(dn + "");
dn++;
}
else {
nameField.setText("VOID");
}
}
else if (x.type === "text" && x.name === 'CarnetNo') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.carnetNo);
}
else if (x.type === "text" && x.name === 'DocumentNo2') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t2 === "VALUE") {
nameField.setText(dn + "");
dn++;
}
else {
nameField.setText("VOID");
}
}
else if (x.type === "text" && x.name === 'PrintVoidText1') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t1 === "VOID") {
nameField.setAlignment(TextAlignment.Center);
nameField.setText(t1);
}
}
else if (x.type === "text" && x.name === 'PrintVoidText2') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t2 === "VOID") {
nameField.setAlignment(TextAlignment.Center);
nameField.setText(t2);
}
}
});
form.flatten();
const filledPdfBytes = await pdfDoc.save();
const outputPath = path.join(__dirname, PDF_URL, `${replaceSlashWithDash(carnetData.carnetNo)}${pn}FNFront.pdf`);
const writeStream = fs.createWriteStream(outputPath);
writeStream.write(filledPdfBytes);
writeStream.end();
pn++;
writeStream.on('finish', () => {
// console.log(`${dn}FNFront.pdf has been successfully created and saved.`);
resolve(Number(dn)); // wait until file fully written
});
writeStream.on('error', err => {
console.error("Error writing PDF to file:", err);
reject(err);
});
} catch (err) {
reject(err);
}
});
}
export const generateFNCounterFoilBack = (carnetData: pdfCarnetData, t1: string, t2: string, dn: number, pn: number): Promise<number | any> => {
return new Promise(async (resolve, reject) => {
try {
const templatePath = path.join(__dirname, PDF_URL, '7ForeignCounterFoilBack.pdf');
const existingPdfBytes = fs.readFileSync(templatePath);
const pdfDoc = await pdfl.load(existingPdfBytes);
const form = pdfDoc.getForm();
const CURRENT_FONT = 11;
const fields = form.getFields();
const fieldInfo = fields.map(f => {
let type = 'unknown';
if (f instanceof PDFTextField) type = 'text';
else if (f instanceof PDFCheckBox) type = 'checkbox';
else if (f instanceof PDFRadioGroup) type = 'radio';
else if (f instanceof PDFDropdown) type = 'dropdown';
else if (f instanceof PDFOptionList) type = 'option-list';
return { name: f.getName(), type };
});
fieldInfo.forEach(x => {
if (x.type === "text" && x.name === 'DocumentNo1') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t1 === "VALUE") {
nameField.setText(dn + "");
dn++;
}
else {
nameField.setText("VOID");
}
}
else if (x.type === "text" && x.name === 'CarnetNo') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.carnetNo);
}
else if (x.type === "text" && x.name === 'DocumentNo2') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t2 === "VALUE") {
nameField.setText(dn + "");
dn++;
}
else {
nameField.setText("VOID");
}
}
else if (x.type === "text" && x.name === 'PrintVoidText1') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t1 === "VOID") {
nameField.setAlignment(TextAlignment.Center);
nameField.setText(t1);
}
}
else if (x.type === "text" && x.name === 'PrintVoidText2') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t2 === "VOID") {
nameField.setAlignment(TextAlignment.Center);
nameField.setText(t2);
}
}
});
form.flatten();
const filledPdfBytes = await pdfDoc.save();
const outputPath = path.join(__dirname, PDF_URL, `${replaceSlashWithDash(carnetData.carnetNo)}${pn}FNBack.pdf`);
const writeStream = fs.createWriteStream(outputPath);
writeStream.write(filledPdfBytes);
writeStream.end();
pn++
writeStream.on('finish', () => {
// console.log(`${pn}FNBack.pdf` + " has been successfully created and saved.");
resolve(Number(dn)); // wait until file fully written
});
writeStream.on('error', err => {
console.error("Error writing PDF to file:", err);
reject(err);
});
} catch (err) {
reject(err);
}
});
}
export const generateTSCounterFoilFront = (carnetData: pdfCarnetData, t1: string, t2: string, dn: number, pn: number): Promise<number | any> => {
return new Promise(async (resolve, reject) => {
try {
const templatePath = path.join(__dirname, PDF_URL, '8TransitCounterFoilFront.pdf');
const existingPdfBytes = fs.readFileSync(templatePath);
const pdfDoc = await pdfl.load(existingPdfBytes);
const form = pdfDoc.getForm();
const CURRENT_FONT = 11;
const fields = form.getFields();
const fieldInfo = fields.map(f => {
let type = 'unknown';
if (f instanceof PDFTextField) type = 'text';
else if (f instanceof PDFCheckBox) type = 'checkbox';
else if (f instanceof PDFRadioGroup) type = 'radio';
else if (f instanceof PDFDropdown) type = 'dropdown';
else if (f instanceof PDFOptionList) type = 'option-list';
return { name: f.getName(), type };
});
// console.log(fieldInfo);
fieldInfo.forEach(x => {
if (x.type === "text" && x.name === 'DocumentNo1') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t1 === "VALUE") {
nameField.setText(dn + "");
dn++;
}
else {
nameField.setText("VOID");
}
}
else if (x.type === "text" && x.name === 'CarnetNo') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.carnetNo);
}
else if (x.type === "text" && x.name === 'DocumentNo2') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t2 === "VALUE") {
nameField.setText(dn + "");
dn++;
}
else {
nameField.setText("VOID");
}
}
else if (x.type === "text" && x.name === 'PrintVoidText1') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t1 === "VOID") {
nameField.setAlignment(TextAlignment.Center);
nameField.setText(t1);
}
}
else if (x.type === "text" && x.name === 'PrintVoidText2') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t2 === "VOID") {
nameField.setAlignment(TextAlignment.Center);
nameField.setText(t2);
}
}
});
form.flatten();
const filledPdfBytes = await pdfDoc.save();
const outputPath = path.join(__dirname, PDF_URL, `${replaceSlashWithDash(carnetData.carnetNo)}${pn}TSFront.pdf`);
const writeStream = fs.createWriteStream(outputPath);
writeStream.write(filledPdfBytes);
writeStream.end();
pn++;
writeStream.on('finish', () => {
// console.log(`${dn}TSFront.pdf has been successfully created and saved.`);
resolve(Number(dn)); // wait until file fully written
});
writeStream.on('error', err => {
console.error("Error writing PDF to file:", err);
reject(err);
});
} catch (err) {
reject(err);
}
});
}
export const generateTSCounterFoilBack = (carnetData: pdfCarnetData, t1: string, t2: string, dn: number, pn: number): Promise<number | any> => {
return new Promise(async (resolve, reject) => {
try {
const templatePath = path.join(__dirname, PDF_URL, '9TransitCounterfoilBack.pdf');
const existingPdfBytes = fs.readFileSync(templatePath);
const pdfDoc = await pdfl.load(existingPdfBytes);
const form = pdfDoc.getForm();
const CURRENT_FONT = 11;
const fields = form.getFields();
const fieldInfo = fields.map(f => {
let type = 'unknown';
if (f instanceof PDFTextField) type = 'text';
else if (f instanceof PDFCheckBox) type = 'checkbox';
else if (f instanceof PDFRadioGroup) type = 'radio';
else if (f instanceof PDFDropdown) type = 'dropdown';
else if (f instanceof PDFOptionList) type = 'option-list';
return { name: f.getName(), type };
});
fieldInfo.forEach(x => {
if (x.type === "text" && x.name === 'DocumentNo1') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t1 === "VALUE") {
nameField.setText(dn + "");
dn++;
}
else {
nameField.setText("VOID");
}
}
else if (x.type === "text" && x.name === 'CarnetNo') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.carnetNo);
}
else if (x.type === "text" && x.name === 'DocumentNo2') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t2 === "VALUE") {
nameField.setText(dn + "");
dn++;
}
else {
nameField.setText("VOID");
}
}
else if (x.type === "text" && x.name === 'PrintVoidText1') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t1 === "VOID") {
nameField.setAlignment(TextAlignment.Center);
nameField.setText(t1);
}
}
else if (x.type === "text" && x.name === 'PrintVoidText2') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
if (t1 === "VOID") {
nameField.setAlignment(TextAlignment.Center);
nameField.setText(t1);
}
}
});
form.flatten();
const filledPdfBytes = await pdfDoc.save();
const outputPath = path.join(__dirname, PDF_URL, `${replaceSlashWithDash(carnetData.carnetNo)}${pn}TSBack.pdf`);
const writeStream = fs.createWriteStream(outputPath);
writeStream.write(filledPdfBytes);
writeStream.end();
pn++
writeStream.on('finish', () => {
// console.log(`${pn}TSBack.pdf` + " has been successfully created and saved.");
resolve(Number(dn)); // wait until file fully written
});
writeStream.on('error', err => {
console.error("Error writing PDF to file:", err);
reject(err);
});
} catch (err) {
reject(err);
}
});
}
export const generateFNImportV = (carnetData: pdfCarnetData, dn: number, pn: number): Promise<number | any> => {
return new Promise(async (resolve, reject) => {
try {
const templatePath = path.join(__dirname, PDF_URL, '10ImportVoucher.pdf');
const existingPdfBytes = fs.readFileSync(templatePath);
const pdfDoc = await pdfl.load(existingPdfBytes);
const form = pdfDoc.getForm();
const CURRENT_FONT = 11;
const fields = form.getFields();
const fieldInfo = fields.map(f => {
let type = 'unknown';
if (f instanceof PDFTextField) type = 'text';
else if (f instanceof PDFCheckBox) type = 'checkbox';
else if (f instanceof PDFRadioGroup) type = 'radio';
else if (f instanceof PDFDropdown) type = 'dropdown';
else if (f instanceof PDFOptionList) type = 'option-list';
return { name: f.getName(), type };
});
// console.log(fieldInfo);
fieldInfo.forEach(x => {
if (x.type === "text" && x.name === 'Valid Until') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
const formattedDate = toUSDateTime(carnetData.EXPDATE)
nameField.setText(formattedDate);
}
else if (x.type === "text" && x.name === 'CarnetNo') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.carnetNo);
}
else if (x.type === "text" && x.name === 'VoucherNo') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(dn + "");
dn++;
}
else if (x.type === "text" && x.name === 'AuthorizedBy') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.AUTHREP);
}
else if (x.type === "text" && x.name === 'GoodsDescription') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.PRINTGOODSTOBEEXPORTED);
}
else if (x.type === "text" && x.name === 'IssuedBy') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.ISSUEDBY);
}
else if (x.type === "text" && x.name === 'Issued') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
const formattedDate = toUSDateTime(carnetData.ISSUEDATE)
nameField.setText(formattedDate);
}
});
form.flatten();
const filledPdfBytes = await pdfDoc.save();
const outputPath = path.join(__dirname, PDF_URL, `${replaceSlashWithDash(carnetData.carnetNo)}${pn}FNImportV.pdf`);
const writeStream = fs.createWriteStream(outputPath);
writeStream.write(filledPdfBytes);
writeStream.end();
pn++;
writeStream.on('finish', () => {
// console.log(`${dn}FNImportV.pdf has been successfully created and saved.`);
resolve(Number(dn)); // wait until file fully written
});
writeStream.on('error', err => {
console.error("Error writing PDF to file:", err);
reject(err);
});
} catch (err) {
reject(err);
}
});
}
export const generateFNExportV = (carnetData: pdfCarnetData, dn: number, pn: number): Promise<number | any> => {
return new Promise(async (resolve, reject) => {
try {
const templatePath = path.join(__dirname, PDF_URL, '11ExportVoucher.pdf');
const existingPdfBytes = fs.readFileSync(templatePath);
const pdfDoc = await pdfl.load(existingPdfBytes);
const form = pdfDoc.getForm();
const CURRENT_FONT = 11;
const fields = form.getFields();
const fieldInfo = fields.map(f => {
let type = 'unknown';
if (f instanceof PDFTextField) type = 'text';
else if (f instanceof PDFCheckBox) type = 'checkbox';
else if (f instanceof PDFRadioGroup) type = 'radio';
else if (f instanceof PDFDropdown) type = 'dropdown';
else if (f instanceof PDFOptionList) type = 'option-list';
return { name: f.getName(), type };
});
// console.log(fieldInfo);
fieldInfo.forEach(x => {
if (x.type === "text" && x.name === 'Valid Until') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
const formattedDate = toUSDateTime(carnetData.EXPDATE)
nameField.setText(formattedDate);
}
else if (x.type === "text" && x.name === 'CarnetNo') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.carnetNo);
}
else if (x.type === "text" && x.name === 'VoucherNo') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(dn + "");
dn++;
}
else if (x.type === "text" && x.name === 'AuthorizedBy') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.AUTHREP);
}
else if (x.type === "text" && x.name === 'GoodsDescription') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.PRINTGOODSTOBEEXPORTED);
}
else if (x.type === "text" && x.name === 'IssuedBy') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.ISSUEDBY);
}
else if (x.type === "text" && x.name === 'Issued') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
const formattedDate = toUSDateTime(carnetData.ISSUEDATE)
nameField.setText(formattedDate);
}
});
form.flatten();
const filledPdfBytes = await pdfDoc.save();
const outputPath = path.join(__dirname, PDF_URL, `${replaceSlashWithDash(carnetData.carnetNo)}${pn}FNExportV.pdf`);
const writeStream = fs.createWriteStream(outputPath);
writeStream.write(filledPdfBytes);
writeStream.end();
pn++;
writeStream.on('finish', () => {
// console.log(`${dn}FNExportV.pdf has been successfully created and saved.`);
resolve(Number(dn)); // wait until file fully written
});
writeStream.on('error', err => {
console.error("Error writing PDF to file:", err);
reject(err);
});
} catch (err) {
reject(err);
}
});
}
export const generateTNV = (carnetData: pdfCarnetData, dn: number, pn: number): Promise<number | any> => {
return new Promise(async (resolve, reject) => {
try {
const templatePath = path.join(__dirname, PDF_URL, '12TransitVoucher.pdf');
const existingPdfBytes = fs.readFileSync(templatePath);
const pdfDoc = await pdfl.load(existingPdfBytes);
const form = pdfDoc.getForm();
const CURRENT_FONT = 11;
const fields = form.getFields();
const fieldInfo = fields.map(f => {
let type = 'unknown';
if (f instanceof PDFTextField) type = 'text';
else if (f instanceof PDFCheckBox) type = 'checkbox';
else if (f instanceof PDFRadioGroup) type = 'radio';
else if (f instanceof PDFDropdown) type = 'dropdown';
else if (f instanceof PDFOptionList) type = 'option-list';
return { name: f.getName(), type };
});
// console.log(fieldInfo);
fieldInfo.forEach(x => {
if (x.type === "text" && x.name === 'Valid Until') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
const formattedDate = toUSDateTime(carnetData.EXPDATE)
nameField.setText(formattedDate);
}
else if (x.type === "text" && x.name === 'CarnetNo') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.carnetNo);
}
else if (x.type === "text" && x.name === 'VoucherNo') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(dn + "");
dn++;
}
else if (x.type === "text" && x.name === 'AuthorizedBy') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.AUTHREP);
}
else if (x.type === "text" && x.name === 'GoodsDescription') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.PRINTGOODSTOBEEXPORTED);
}
else if (x.type === "text" && x.name === 'IssuedBy') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(carnetData.ISSUEDBY);
}
else if (x.type === "text" && x.name === 'Issued') {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
const formattedDate = toUSDateTime(carnetData.ISSUEDATE)
nameField.setText(formattedDate);
}
});
form.flatten();
const filledPdfBytes = await pdfDoc.save();
const outputPath = path.join(__dirname, PDF_URL, `${replaceSlashWithDash(carnetData.carnetNo)}${pn}TNV.pdf`);
const writeStream = fs.createWriteStream(outputPath);
writeStream.write(filledPdfBytes);
writeStream.end();
pn++;
writeStream.on('finish', () => {
// console.log(`${dn}TNV.pdf has been successfully created and saved.`);
resolve(Number(dn)); // wait until file fully written
});
writeStream.on('error', err => {
console.error("Error writing PDF to file:", err);
reject(err);
});
} catch (err) {
reject(err);
}
});
}
function getPatternArray(n) {
if (n < 1) {
return [];
}
const numFours = Math.floor((n - 1) / 4);
// Create an array with the leading 4s
const result = Array(numFours).fill(4);
// Calculate and add the final number
const lastNumber = (n - 1) % 4 + 1;
result.push(lastNumber);
return result;
}
export function generateGL1(carnetData: pdfCarnetData): Promise<any> {
return new Promise(async (resolve, reject) => {
try {
const templatePath = path.join(__dirname, PDF_URL, '2GeneralListSeeattached.pdf');
const existingPdfBytes = fs.readFileSync(templatePath);
const outputPath = path.join(__dirname, PDF_URL, `${replaceSlashWithDash(carnetData.carnetNo)}p2.pdf`);
const writeStream = fs.createWriteStream(outputPath);
writeStream.write(existingPdfBytes);
writeStream.end();
writeStream.on('finish', () => {
// console.log("PDF has been successfully created and saved.");
resolve("p2 done"); // wait until file fully written
});
writeStream.on('error', err => {
console.error("Error writing PDF to file:", err);
reject(err);
});
} catch (err) {
reject(err);
}
});
}
export async function processGlDataInBatches(
glDataArray: pdfGLData[],
batchSize: number,
carnetData: pdfCarnetData, // carnetData is a parameter here
batchCallback: (batch: pdfGLData[], batchNumber: number, startIndex: number, endIndex: number) => Promise<void>
): Promise<number> {
if (!Array.isArray(glDataArray)) {
throw new Error("Input 'glDataArray' must be an array.");
}
const totalLength: number = glDataArray.length;
console.log(`✨ [Batch Processor] Starting batch processing for ${totalLength} items.`);
console.log(`📦 [Batch Processor] Batch size set to ${batchSize} items.`);
if (totalLength === 0) {
console.log(" [Batch Processor] Array is empty. No batches to process.");
return 0;
}
let batchNumber: number = 1;
for (let i: number = 0; i < totalLength; i += batchSize) {
const startIndex: number = i;
const endIndex: number = Math.min(i + batchSize, totalLength);
// console.log("item i : ", i);
// Extract the current batch using slice, creating a new array for the batch
const currentBatch: pdfGLData[] = glDataArray.slice(startIndex, endIndex);
// Log the particular batch data here
// console.log(`🔍 [Batch Processor] Details for Batch ${batchNumber} (Items ${startIndex} to ${endIndex - 1}):`, JSON.stringify(currentBatch, null, 2));
// Define pdfGeneration function *inside* the loop for each iteration
// Modified to accept and log batchNumber for clearer output
async function pdfGeneration(data: pdfCarnetData, currentBatchNumber: number) {
// console.log(`📄 [PDF Generation] Calling PDF generation for Batch ${currentBatchNumber}. Carnet Data:`, JSON.stringify(data, null, 2));
// Added a small delay to ensure logs are flushed
// await new Promise(resolve => setTimeout(resolve, 50));
// return;
function transformGlDataForDisplay(glDataArray: any[]): any[] {
if (!Array.isArray(glDataArray)) {
console.error("Input for transformGlDataForDisplay must be an array.");
return [];
}
const transformedData: any[] = [];
glDataArray.forEach((item, index) => {
const rowNumber = index + 1; // 1-based index for "RowX"
transformedData.push(
{ name: `Item NoRow${rowNumber}`, value: item.itemNo, type: "text" },
{ name: `DescriptionRow${rowNumber}`, value: item.description, type: "text" },
{ name: `No of piecesRow${rowNumber}`, value: item.noOfPieces, type: "text" },
{ name: `WeightRow${rowNumber}`, value: item.weight, type: "text" },
{ name: `Item ValueRow${rowNumber}`, value: item.itemValue, type: "text" },
{ name: `Origin CountryRow${rowNumber}`, value: item.countryOfOrigin, type: "text" }
);
});
return transformedData;
}
function calculateTotalItemValue(glDataArray: any[]): number {
if (!Array.isArray(glDataArray)) {
console.error("Input for calculateTotalItemValue must be an array.");
return 0;
}
let totalItemValue = 0;
for (const item of glDataArray) {
if (typeof item.itemValue === 'number') {
totalItemValue += item.itemValue;
} else {
console.warn(`Non-numeric itemValue encountered for itemNo: ${item.itemNo}. Skipping value.`);
}
}
let value = formatNumber(totalItemValue)
// console.log(`total for batch ${batchNumber} : `, value);
return value;
}
return new Promise(async (resolve, reject) => {
try {
const templatePath = path.join(__dirname, PDF_URL, '2GeneralList.pdf');
const existingPdfBytes = fs.readFileSync(templatePath);
const pdfDoc = await pdfl.load(existingPdfBytes);
const form = pdfDoc.getForm();
const CURRENT_FONT = 11;
const fields = form.getFields();
const fieldInfo = fields.map(f => {
let type = 'unknown';
if (f instanceof PDFTextField) type = 'text';
else if (f instanceof PDFCheckBox) type = 'checkbox';
else if (f instanceof PDFRadioGroup) type = 'radio';
else if (f instanceof PDFDropdown) type = 'dropdown';
else if (f instanceof PDFOptionList) type = 'option-list';
return { name: f.getName(), type };
});
// console.log(fieldInfo);
const fdata = transformGlDataForDisplay(currentBatch);
fdata.forEach(x => {
// if (x.type === "text" && x.name === 'CarnetNo') {
// const nameField = form.getTextField(x.name);
// nameField.setFontSize(CURRENT_FONT);
// nameField.setText(carnetData.carnetNo);
// }
if (/^Item ValueRow\d+$/.test(x.name)) {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
let ThousandSeparatorValue = formatNumber(x.value);
nameField.setAlignment(TextAlignment.Right);
nameField.setText(ThousandSeparatorValue + "");
}
else {
const nameField = form.getTextField(x.name);
nameField.setFontSize(CURRENT_FONT);
nameField.setText(x.value + "");
}
});
const TotPageItemValue = form.getTextField('TotPageItemValue');
TotPageItemValue.setFontSize(CURRENT_FONT);
let totalValue = calculateTotalItemValue(currentBatch);
TotPageItemValue.setAlignment(TextAlignment.Right);
TotPageItemValue.setText(totalValue + "");
const carnetNoField = form.getTextField('Carnet No');
carnetNoField.setFontSize(CURRENT_FONT);
carnetNoField.setText(carnetData.carnetNo);
const contnSheetNoField = form.getTextField('ContnSheet No');
contnSheetNoField.setFontSize(CURRENT_FONT);
contnSheetNoField.setText((batchNumber - 1) + "");
form.flatten();
const filledPdfBytes = await pdfDoc.save();
const outputPath = path.join(__dirname, PDF_URL, `${replaceSlashWithDash(carnetData.carnetNo)}p2gl${batchNumber}.pdf`);
const writeStream = fs.createWriteStream(outputPath);
writeStream.write(filledPdfBytes);
writeStream.end();
writeStream.on('finish', () => {
// console.log("PDF has been successfully created and saved.");
resolve("p1 done"); // wait until file fully written
});
writeStream.on('error', err => {
console.error("Error writing PDF to file:", err);
reject(err);
});
} catch (err) {
reject(err);
}
});
}
// Call pdfGeneration for *each* batch, passing the carnetData and current batch number
await pdfGeneration(carnetData, batchNumber);
// Await the processing of the current batch to ensure sequential execution.
await batchCallback(currentBatch, batchNumber, startIndex, endIndex);
batchNumber++; // Increment batch number for the next iteration
}
console.log(`✅ [Batch Processor] Batch processing complete. Total batches processed: ${batchNumber - 1}`);
return batchNumber
}
export async function generateGL(glData: pdfGLData[], carnetData: pdfCarnetData): Promise<any> {
const BATCH_SIZE = 38;
const totalLength = glData.length;
console.log(`--- Initiating generateGL for ${totalLength} items ---`);
// The inner function that logs the received array length
// This is passed as the batchCallback to processGlDataInBatches
const innerLogFunction = async (batch: pdfGLData[], batchNumber: number) => {
console.log(`Received batch ${batchNumber}. Array length: ${batch.length}`);
// Added a small delay to ensure logs are flushed
await new Promise(resolve => setTimeout(resolve, 50));
};
// Call the existing processGlDataInBatches function and await its completion
try {
const loop = await processGlDataInBatches(glData, BATCH_SIZE, carnetData, innerLogFunction);
console.log("--- generateGL function completed ---");
let fileArray: string[] = []
for (let i = 1; i < loop; i++) {
fileArray.push(`${replaceSlashWithDash(carnetData.carnetNo)}p2gl${i}.pdf`)
}
return { fileArray, batch: loop - 1 };
} catch (error) {
console.error("Error in generateGL batch processing:", error);
throw error; // Re-throw the error for the caller to handle
}
}
export function generateMockGlData(count: number): any[] {
const mockData: any[] = [];
for (let i: number = 1; i <= count; i++) {
mockData.push({
ITEMNO: i,
ITEMDESCRIPTION: `Product Component ${i}`,
NOOFPIECES: Math.floor(Math.random() * 20) + 1,
WEIGHT: `${(Math.random() * 100).toFixed(2)} kg`,
ITEMVALUE: parseFloat((Math.random() * 5000).toFixed(2)),
GOODSORIGINCOUNTRY: ['USA', 'Canada', 'Germany', 'China', 'Japan'][
Math.floor(Math.random() * 5)
],
});
}
return mockData;
}
// console.log(generateMockGlData(40))
export async function usCounterFoil(carnetData: pdfCarnetData) {
let documentNo = carnetData.NEXTUSCFNO;
let fpdf = 1;
const set = getPatternArray(carnetData.NOOFUSSETS)
const generatedFiles: any = [];
for (const s of set) {
// console.log(" Current pattern value (s): ", s);
// This is where you would use the 's' value to determine arguments
// For now, let's keep the arguments constant as per your example
const funFrontSecondArg = s > 1 ? "VALUE" : "VOID";
const funBackFirstArg = s > 2 ? "VALUE" : "VOID";
const funBackSecondArg = s > 3 ? "VALUE" : "VOID";
// Step 1: Await front PDF generation
let inc1: number = await generateUSCounterFoilFront(carnetData, "VALUE", funFrontSecondArg, documentNo, fpdf);
documentNo = inc1;
generatedFiles.push(`${replaceSlashWithDash(carnetData.carnetNo)}${fpdf}USFront.pdf`);
// Step 2: Await back PDF generation
let inc2: number = await generateUSCounterFoilBack(carnetData, funBackFirstArg, funBackSecondArg, documentNo, fpdf);
documentNo = inc2;
generatedFiles.push(`${replaceSlashWithDash(carnetData.carnetNo)}${fpdf}USBack.pdf`);
// Increment fpdf for the next loop
fpdf++;
}
// console.log("All US Counter Foil PDFs have been completely generated.");
// console.log(generatedFiles);
// Return the list of generated filenames
return generatedFiles;
}
export async function fnCounterFoil(carnetData: pdfCarnetData) {
let documentNo = carnetData.NEXTFOREIGNCFNO;
let fpdf = 1;
const set = getPatternArray(carnetData.NOOFFOREIGNSETS)
const generatedFiles: any = [];
for (const s of set) {
// This is where you would use the 's' value to determine arguments
// For now, let's keep the arguments constant as per your example
const funFrontSecondArg = s > 1 ? "VALUE" : "VOID";
const funBackFirstArg = s > 2 ? "VALUE" : "VOID";
const funBackSecondArg = s > 3 ? "VALUE" : "VOID";
// Step 1: Await front PDF generation
let inc1: number = await generateFNCounterFoilFront(carnetData, "VALUE", funFrontSecondArg, documentNo, fpdf);
documentNo = inc1;
generatedFiles.push(`${replaceSlashWithDash(carnetData.carnetNo)}${fpdf}FNFront.pdf`);
// Step 2: Await back PDF generation
let inc2: number = await generateFNCounterFoilBack(carnetData, funBackFirstArg, funBackSecondArg, documentNo, fpdf);
documentNo = inc2;
generatedFiles.push(`${replaceSlashWithDash(carnetData.carnetNo)}${fpdf}FNBack.pdf`);
// Increment fpdf for the next loop
fpdf++;
}
// console.log("All US Counter Foil PDFs have been completely generated.");
// console.log(generatedFiles);
// Return the list of generated filenames
return generatedFiles;
}
export async function tsCounterFoil(carnetData: pdfCarnetData) {
let documentNo = carnetData.NEXTTRANSITCFNO;
let fpdf = 1;
const set = getPatternArray(carnetData.NOOFTRANSITSETS)
const generatedFiles: any = [];
for (const s of set) {
// console.log(" Current pattern value (s): ", s);
// This is where you would use the 's' value to determine arguments
// For now, let's keep the arguments constant as per your example
const funFrontSecondArg = s > 1 ? "VALUE" : "VOID";
const funBackFirstArg = s > 2 ? "VALUE" : "VOID";
const funBackSecondArg = s > 3 ? "VALUE" : "VOID";
// console.log("document no : ", s, " : ", documentNo);
// Step 1: Await front PDF generation
let inc1: number = await generateTSCounterFoilFront(carnetData, "VALUE", funFrontSecondArg, documentNo, fpdf);
documentNo = inc1;
generatedFiles.push(`${replaceSlashWithDash(carnetData.carnetNo)}${fpdf}TSFront.pdf`);
// Step 2: Await back PDF generation
let inc2: number = await generateTSCounterFoilBack(carnetData, funBackFirstArg, funBackSecondArg, documentNo, fpdf);
documentNo = inc2;
generatedFiles.push(`${replaceSlashWithDash(carnetData.carnetNo)}${fpdf}TSBack.pdf`);
// Increment fpdf for the next loop
fpdf++;
}
// console.log("All US Counter Foil PDFs have been completely generated.");
// console.log(generatedFiles);
// Return the list of generated filenames
return generatedFiles;
}
export async function fnVochers(carnetData: pdfCarnetData, body: PrintCarnetDTO) {
let importNo = 1;
let exportNo = 1;
let fpdf = 1;
const set = (carnetData.NOOFFOREIGNSETS)
const generatedFiles: any = [];
for (let i = 1; i <= set; i++) {
// Step 1: Await back PDF generation
let inc1: number = await generateFNImportV(carnetData, importNo, fpdf);
importNo = inc1;
generatedFiles.push(`${replaceSlashWithDash(carnetData.carnetNo)}${fpdf}FNImportV.pdf`);
if (body.P_PRINTGL === 'Y') {
generatedFiles.push(`${replaceSlashWithDash(carnetData.carnetNo)}p2.pdf`);
}
// Step 2: Await back PDF generation
let inc2: number = await generateFNExportV(carnetData, exportNo, fpdf);
exportNo = inc2;
generatedFiles.push(`${replaceSlashWithDash(carnetData.carnetNo)}${fpdf}FNExportV.pdf`);
if (body.P_PRINTGL === 'Y') {
generatedFiles.push(`${replaceSlashWithDash(carnetData.carnetNo)}p2.pdf`);
}
// Increment fpdf for the next loop
fpdf++;
}
// console.log("All US Counter Foil PDFs have been completely generated.");
// console.log(generatedFiles);
// Return the list of generated filenames
return generatedFiles;
}
export async function tnVochers(carnetData: pdfCarnetData, body: PrintCarnetDTO) {
let tnNo = 1;
let fpdf = 1;
const set = (carnetData.NOOFTRANSITSETS)
const generatedFiles: any = [];
for (let i = 1; i <= set; i++) {
// console.log(" Current pattern value (s): ", s);
let inc1: number = await generateTNV(carnetData, tnNo, fpdf);
tnNo = inc1;
generatedFiles.push(`${replaceSlashWithDash(carnetData.carnetNo)}${fpdf}TNV.pdf`);
if (body.P_PRINTGL === 'Y') {
generatedFiles.push(`${replaceSlashWithDash(carnetData.carnetNo)}p2.pdf`);
}
fpdf++;
}
// console.log("All US Counter Foil PDFs have been completely generated.");
// console.log(generatedFiles);
return generatedFiles;
}
export const generateFinalPDF = async (inputFiles: string[], outputFile: string) => {
const merger = new PDFMerger();
for (const fileName of inputFiles) {
const filePath = path.join(__dirname, PDF_URL, fileName);
// console.log(`Does the file exist? ${existsSync(filePath)}`);
// console.log(`📄 Adding: ${filePath}`);
try {
const fileData = readFileSync(filePath);
await merger.add(fileData);
} catch (err) {
console.error(`❌ Failed to add PDF: ${fileName}`, err);
}
}
const outputPath = path.join(__dirname, PDF_URL, outputFile);
try {
await merger.save(outputPath);
// console.log(`✅ Merged PDF saved to ${outputPath}`);
} catch (err) {
console.error(`❌ Failed to save merged PDF`, err);
throw new Error("Failed to save merged PDF");
}
};
export const deleteFilesAsync = async (relativeFilePaths: string[]): Promise<void> => {
for (const relativeFilePath of relativeFilePaths) {
const filePath = path.join(__dirname, PDF_URL, relativeFilePath);
if (fs.existsSync(filePath)) {
try {
await fsPromises.unlink(filePath);
// console.log(`🗑️ Deleted: ${filePath}`);
} catch (err) {
console.error(`❌ Error deleting file: ${filePath}`, err);
}
} else {
console.warn(`⚠️ File not found: ${filePath}`);
}
}
};