BE/src/utils/helper.ts
2025-08-11 17:23:13 +05:30

1559 lines
62 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
BadRequestException,
InternalServerErrorException,
Logger,
} from '@nestjs/common';
import * as oracledb from 'oracledb';
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';
const logger = new Logger('Helper');
export const handleError = (error: any, context: string = 'UnknownService'): never => {
if (error instanceof BadRequestException || error instanceof BR) {
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;
}
});
}
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, '-');
}
export const generateGreenCoverPDF = (carnetData: pdfCarnetData) => {
return new Promise(async (resolve, reject) => {
try {
const templatePath = path.join(__dirname, '../..', 'public/carnet-pdf', '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, '../..', 'public/carnet-pdf', `${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, '../..', 'public/carnet-pdf', '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, '../..', 'public/carnet-pdf', `${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, '../..', 'public/carnet-pdf', '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 (t1 === "VOID") {
nameField.setAlignment(TextAlignment.Center);
nameField.setText(t1);
}
}
});
form.flatten();
const filledPdfBytes = await pdfDoc.save();
const outputPath = path.join(__dirname, '../..', 'public/carnet-pdf', `${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, '../..', 'public/carnet-pdf', '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, '../..', 'public/carnet-pdf', `${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, '../..', 'public/carnet-pdf', '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 (t1 === "VOID") {
nameField.setAlignment(TextAlignment.Center);
nameField.setText(t1);
}
}
});
form.flatten();
const filledPdfBytes = await pdfDoc.save();
const outputPath = path.join(__dirname, '../..', 'public/carnet-pdf', `${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, '../..', 'public/carnet-pdf', '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, '../..', 'public/carnet-pdf', `${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, '../..', 'public/carnet-pdf', '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, '../..', 'public/carnet-pdf', `${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, '../..', 'public/carnet-pdf', '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, '../..', 'public/carnet-pdf', `${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, '../..', 'public/carnet-pdf', '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, '../..', 'public/carnet-pdf', `${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, '../..', 'public/carnet-pdf', '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, '../..', 'public/carnet-pdf', `${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, '../..', 'public/carnet-pdf', '2GeneralListSeeattached.pdf');
const existingPdfBytes = fs.readFileSync(templatePath);
const outputPath = path.join(__dirname, '../..', 'public/carnet-pdf', `${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, '../..', 'public/carnet-pdf', '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);
// }
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.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, '../..', 'public/carnet-pdf', `${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 = getPatternArray(carnetData.NOOFFOREIGNSETS)
const generatedFiles: any = [];
for (const s of set) {
// 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 = getPatternArray(carnetData.NOOFTRANSITSETS)
const generatedFiles: any = [];
for (const s of set) {
// console.log(" Current pattern value (s): ", s);
await generateTNV(carnetData, tnNo, fpdf);
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, '../../public/carnet-pdf', 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, '../../public/carnet-pdf', 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, '../../public/carnet-pdf', 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}`);
}
}
};