135 lines
4.9 KiB
JavaScript
135 lines
4.9 KiB
JavaScript
const queries = require("../graphql-client/queries");
|
|
const logger = require("../utils/logger");
|
|
|
|
const predefinedPartTypes = ["PAN", "PAC", "PAR", "PAL", "PAA", "PAM", "PAP", "PAS", "PASL", "PAG"];
|
|
const predefinedModLbrTypes = [
|
|
"LAA",
|
|
"LAB",
|
|
"LAD",
|
|
"LAE",
|
|
"LAF",
|
|
"LAG",
|
|
"LAM",
|
|
"LAR",
|
|
"LAS",
|
|
"LAU",
|
|
"LA1",
|
|
"LA2",
|
|
"LA3",
|
|
"LA4"
|
|
];
|
|
|
|
exports.partsScan = async function (req, res) {
|
|
const { jobid } = req.body;
|
|
const BearerToken = req.BearerToken;
|
|
const client = req.userGraphQLClient;
|
|
|
|
logger.log("job-parts-scan", "DEBUG", req.user?.email, jobid, null);
|
|
|
|
try {
|
|
const data = await client
|
|
.setHeaders({ Authorization: BearerToken })
|
|
.request(queries.QUERY_PARTS_SCAN, { id: jobid });
|
|
|
|
const rules = data.jobs_by_pk.bodyshop.md_parts_scan || [];
|
|
if (!Array.isArray(rules)) {
|
|
// noinspection ExceptionCaughtLocallyJS
|
|
throw new Error("Invalid md_parts_scan format. Expected an array of rules.");
|
|
}
|
|
|
|
const compiledRules = rules.map((rule) => ({
|
|
...rule,
|
|
regex:
|
|
typeof rule.value === "string" && rule.caseInsensitive
|
|
? new RegExp(rule.value, "i")
|
|
: typeof rule.value === "string"
|
|
? new RegExp(rule.value)
|
|
: null
|
|
}));
|
|
|
|
const criticalIds = new Set();
|
|
|
|
for (const jobline of data.jobs_by_pk.joblines) {
|
|
for (const { field, regex, operation, value, mark_critical, update_field, update_value } of compiledRules) {
|
|
// IO-3077 - Remove skip as this is extended to include line updates.
|
|
// if (criticalIds.has(jobline.id)) break; // Skip further evaluation if already critical
|
|
|
|
let jobValue = jobline[field];
|
|
let match = false;
|
|
|
|
if (field === "part_number") {
|
|
match = regex
|
|
? regex.test(jobline.oem_partno || "") || regex.test(jobline.alt_partno || "")
|
|
: jobline.oem_partno === value || jobline.alt_partno === value;
|
|
} else if (field === "part_type") {
|
|
match = predefinedPartTypes.includes(value) && value === jobValue;
|
|
} else if (field === "mod_lbr_ty") {
|
|
match = predefinedModLbrTypes.includes(value) && value === jobValue;
|
|
} else if (regex && typeof jobValue === "string") {
|
|
if (operation === "contains") match = regex.test(jobValue);
|
|
if (operation === "startsWith") match = new RegExp(`^${value}`).test(jobValue);
|
|
if (operation === "endsWith") match = new RegExp(`${value}$`).test(jobValue);
|
|
if (operation === "equals") match = jobValue === value;
|
|
} else if (typeof jobValue === "number") {
|
|
if (operation === ">") match = jobValue > value;
|
|
if (operation === "<") match = jobValue < value;
|
|
if (operation === "=") match = jobValue === value;
|
|
}
|
|
|
|
if (match) {
|
|
if (mark_critical) {
|
|
//Could technically lead to duplicates, but they'd only be n positives, ultimately leading a positive.
|
|
criticalIds.add(jobline.id);
|
|
}
|
|
if (update_field && update_value) {
|
|
let actualUpdateField = update_field;
|
|
if (update_field === "part_number") {
|
|
// Determine which part number field to update based on the match
|
|
if (!jobline.oem_partno) {
|
|
actualUpdateField = "oem_partno";
|
|
} else {
|
|
if (regex) {
|
|
actualUpdateField = regex.test(jobline.oem_partno || "") ? "oem_partno" : "alt_partno";
|
|
} else {
|
|
actualUpdateField = jobline.oem_partno === value ? "oem_partno" : "alt_partno";
|
|
}
|
|
}
|
|
}
|
|
if (actualUpdateField) {
|
|
await client.setHeaders({ Authorization: BearerToken }).request(queries.UPDATE_JOB_LINE, {
|
|
lineId: jobline.id,
|
|
line: { [actualUpdateField]: update_value, manual_line: true }
|
|
});
|
|
}
|
|
|
|
await client.setHeaders({ Authorization: BearerToken }).request(queries.INSERT_AUDIT_TRAIL, {
|
|
auditObj: {
|
|
bodyshopid: data.jobs_by_pk.bodyshop.id,
|
|
jobid,
|
|
operation: `Jobline (#${jobline.line_no} ${jobline.line_desc}/${jobline.id}) ${update_field} updated from ${jobline[update_field]} to ${update_value}. Lined marked as manual line.`,
|
|
type: "partscanupdate",
|
|
useremail: req.user.email
|
|
}
|
|
});
|
|
}
|
|
|
|
//break; // No need to evaluate further rules for this jobline
|
|
}
|
|
}
|
|
}
|
|
|
|
const result = await client
|
|
.setHeaders({ Authorization: BearerToken })
|
|
.request(queries.UPDATE_PARTS_CRITICAL, { IdsToMarkCritical: Array.from(criticalIds), jobid });
|
|
|
|
res.status(200).json(result);
|
|
} catch (error) {
|
|
logger.log("job-parts-scan-error", "ERROR", req.user?.email, jobid, {
|
|
jobid,
|
|
error: error.message,
|
|
stack: error.stack
|
|
});
|
|
res.status(400).json(JSON.stringify({ message: error?.message }));
|
|
}
|
|
};
|