Generate PPC for CCC.

This commit is contained in:
Patrick Fic
2025-04-03 13:42:42 -07:00
parent b60d9b0f41
commit 85fcecf856
5 changed files with 233 additions and 20 deletions

View File

@@ -0,0 +1,191 @@
import { DBFFile, FieldDescriptor } from "dbffile";
import {
deleteEmsFileIfExists,
generatePpcFilePath,
} from "./ppc-generate-file";
import { PpcJob } from "./ppc-handler";
const GenerateEnvFile = async (job: PpcJob): Promise<boolean> => {
const records = [
{
EST_SYSTEM: "C",
RO_ID: job.ro_number,
ESTFILE_ID: job.ciecaid,
STATUS: false,
INCL_ADMIN: true,
INCL_VEH: true,
INCL_EST: true,
INCL_PROFL: true,
INCL_TOTAL: true,
INCL_VENDR: false,
},
];
//Check if it already exists, delete it if so.
await deleteEmsFileIfExists(generatePpcFilePath(`${job.ciecaid}.ENV`));
const dbf = await DBFFile.create(
generatePpcFilePath(`${job.ciecaid}.ENV`),
envFieldLineDescriptors,
);
await dbf.appendRecords(records);
console.log(`${records.length} LIN file records added.`);
return true;
};
export default GenerateEnvFile;
//Taken from a set of CCC ems files.
const envFieldLineDescriptors: FieldDescriptor[] = [
{
name: "EST_SYSTEM",
type: "C",
size: 1,
decimalPlaces: 0,
},
{
name: "SW_VERSION",
type: "C",
size: 10,
decimalPlaces: 0,
},
{
name: "DB_VERSION",
type: "C",
size: 12,
decimalPlaces: 0,
},
{
name: "DB_DATE",
type: "D",
size: 8,
decimalPlaces: 0,
},
{
name: "UNQFILE_ID",
type: "C",
size: 8,
decimalPlaces: 0,
},
{
name: "RO_ID",
type: "C",
size: 8,
decimalPlaces: 0,
},
{
name: "ESTFILE_ID",
type: "C",
size: 38,
decimalPlaces: 0,
},
{
name: "SUPP_NO",
type: "C",
size: 3,
decimalPlaces: 0,
},
{
name: "EST_CTRY",
type: "C",
size: 3,
decimalPlaces: 0,
},
{
name: "TOP_SECRET",
type: "C",
size: 80,
decimalPlaces: 0,
},
{
name: "H_TRANS_ID",
type: "C",
size: 9,
decimalPlaces: 0,
},
{
name: "H_CTRL_NO",
type: "C",
size: 9,
decimalPlaces: 0,
},
{
name: "TRANS_TYPE",
type: "C",
size: 1,
decimalPlaces: 0,
},
{
name: "STATUS",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "CREATE_DT",
type: "D",
size: 8,
decimalPlaces: 0,
},
{
name: "CREATE_TM",
type: "C",
size: 6,
decimalPlaces: 0,
},
{
name: "TRANSMT_DT",
type: "D",
size: 8,
decimalPlaces: 0,
},
{
name: "TRANSMT_TM",
type: "C",
size: 6,
decimalPlaces: 0,
},
{
name: "INCL_ADMIN",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_VEH",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_EST",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_PROFL",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_TOTAL",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_VENDR",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "EMS_VER",
type: "C",
size: 5,
decimalPlaces: 0,
},
];

View File

@@ -1,6 +1,6 @@
import path from "path"; import path from "path";
import store from "../store/store"; import store from "../store/store";
import fs from "fs";
const generatePpcFilePath = (filename: string): string => { const generatePpcFilePath = (filename: string): string => {
const ppcOutFilePath: string | null = store.get("settings.ppcFilePath"); const ppcOutFilePath: string | null = store.get("settings.ppcFilePath");
if (!ppcOutFilePath) { if (!ppcOutFilePath) {
@@ -9,4 +9,19 @@ const generatePpcFilePath = (filename: string): string => {
return path.resolve(ppcOutFilePath, filename); return path.resolve(ppcOutFilePath, filename);
}; };
export { generatePpcFilePath }; const deleteEmsFileIfExists = async (filename: string): Promise<void> => {
// Check if the file exists and delete it if it does
try {
await fs.promises.access(filename); // Check if the file exists
await fs.promises.unlink(filename); // Delete the file
console.log(`Existing file at ${filename} deleted.`);
} catch (err) {
if (err.code !== "ENOENT") {
// If the error is not "file not found", rethrow it
throw err;
}
console.log(`No existing file found at ${filename}.`);
}
};
export { generatePpcFilePath, deleteEmsFileIfExists };

View File

@@ -1,22 +1,28 @@
import { DBFFile, FieldDescriptor } from "dbffile"; import { DBFFile, FieldDescriptor } from "dbffile";
import { generatePpcFilePath } from "./ppc-generate-file"; import {
deleteEmsFileIfExists,
generatePpcFilePath,
} from "./ppc-generate-file";
import { PpcJob } from "./ppc-handler"; import { PpcJob } from "./ppc-handler";
const GenerateLinFile = async (job: PpcJob): Promise<boolean> => { const GenerateLinFile = async (job: PpcJob): Promise<boolean> => {
const records = job.joblines.map((line) => { const records = job.joblines.map((line) => {
return { return {
//TODO: There are missing types here. May require server side updates, but we are missing things like LINE_NO, LINE_IND, etc. //TODO: There are missing types here. May require server side updates, but we are missing things like LINE_NO, LINE_IND, etc.
TRAN_CODE: 2, TRAN_CODE: "2",
UNQ_SEQ: line.unq_seq, UNQ_SEQ: line.unq_seq,
ACT_PRICE: line.act_price, ACT_PRICE: line.act_price,
}; };
}); });
//Check if it already exists, delete it if so.
let dbf = await DBFFile.create( await deleteEmsFileIfExists(generatePpcFilePath(`${job.ciecaid}.LIN`));
const dbf = await DBFFile.create(
generatePpcFilePath(`${job.ciecaid}.LIN`), generatePpcFilePath(`${job.ciecaid}.LIN`),
linFieldDescriptors, linFieldDescriptors,
); );
console.log("DBF file created.");
await dbf.appendRecords(records); await dbf.appendRecords(records);
console.log(`${records.length} LIN file records added.`); console.log(`${records.length} LIN file records added.`);
return true; return true;

View File

@@ -7,6 +7,7 @@ import path from "path";
import errorTypeCheck from "../../util/errorTypeCheck"; import errorTypeCheck from "../../util/errorTypeCheck";
import store from "../store/store"; import store from "../store/store";
import GenerateLinFile from "./ppc-generate-lin"; import GenerateLinFile from "./ppc-generate-lin";
import GenerateEnvFile from "./ppc-generate-env";
const handlePartsPariceChangeRequest = async ( const handlePartsPariceChangeRequest = async (
req: express.Request, req: express.Request,
@@ -17,6 +18,7 @@ const handlePartsPariceChangeRequest = async (
const { job } = req.body as { job: PpcJob }; const { job } = req.body as { job: PpcJob };
try { try {
await generatePartsPriceChange(job); await generatePartsPriceChange(job);
res.status(200).json({ success: true });
} catch (error) { } catch (error) {
log.error("Error generating parts price change", errorTypeCheck(error)); log.error("Error generating parts price change", errorTypeCheck(error));
res.status(500).json({ res.status(500).json({
@@ -24,10 +26,7 @@ const handlePartsPariceChangeRequest = async (
error: "Error generating parts price change.", error: "Error generating parts price change.",
...errorTypeCheck(error), ...errorTypeCheck(error),
}); });
return;
} }
res.status(200).json({ success: true });
return; return;
}; };
@@ -40,18 +39,20 @@ const generatePartsPriceChange = async (job: PpcJob): Promise<void> => {
log.error("PPC file path is not set"); log.error("PPC file path is not set");
throw new Error("PPC file path is not set"); throw new Error("PPC file path is not set");
} }
try {
//If the directory doesn't exist, create it. //If the directory doesn't exist, create it.
const directoryPath = path.dirname(ppcOutFilePath); const directoryPath = path.dirname(ppcOutFilePath);
if (!fs.existsSync(directoryPath)) { if (!fs.existsSync(directoryPath)) {
log.info(`Directory does not exist. Creating: ${directoryPath}`); log.info(`Directory does not exist. Creating: ${directoryPath}`);
fs.mkdirSync(directoryPath, { recursive: true }); fs.mkdirSync(directoryPath, { recursive: true });
}
await GenerateLinFile(job);
await GenerateEnvFile(job);
} catch (error) {
log.error("Error generating parts price change", errorTypeCheck(error));
throw error;
} }
const LinFile = await GenerateLinFile(job);
//Generate the required file envelop to be sent back to CCC.
}; };
export interface PpcJob { export interface PpcJob {
id: UUID; id: UUID;
ciecaid: string; ciecaid: string;

View File

@@ -259,7 +259,7 @@
<translations> <translations>
<translation> <translation>
<language>en-US</language> <language>en-US</language>
<approved>false</approved> <approved>true</approved>
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>