feature/IO-3255-simplified-parts-management - Bump deps, add Change Request
This commit is contained in:
104
client/package-lock.json
generated
104
client/package-lock.json
generated
@@ -21,11 +21,11 @@
|
||||
"@jsreport/browser-client": "^3.1.0",
|
||||
"@reduxjs/toolkit": "^2.8.2",
|
||||
"@sentry/cli": "^2.46.0",
|
||||
"@sentry/react": "^9.34.0",
|
||||
"@sentry/react": "^9.35.0",
|
||||
"@sentry/vite-plugin": "^3.5.0",
|
||||
"@splitsoftware/splitio-react": "^2.3.1",
|
||||
"@tanem/react-nprogress": "^5.0.53",
|
||||
"antd": "^5.26.3",
|
||||
"antd": "^5.26.4",
|
||||
"apollo-link-logger": "^2.0.1",
|
||||
"apollo-link-sentry": "^4.3.0",
|
||||
"autosize": "^6.0.1",
|
||||
@@ -50,7 +50,7 @@
|
||||
"object-hash": "^3.0.0",
|
||||
"phone": "^3.1.62",
|
||||
"prop-types": "^15.8.1",
|
||||
"query-string": "^9.2.1",
|
||||
"query-string": "^9.2.2",
|
||||
"raf-schd": "^4.0.3",
|
||||
"react": "^18.3.1",
|
||||
"react-big-calendar": "^1.19.4",
|
||||
@@ -60,7 +60,7 @@
|
||||
"react-drag-listview": "^2.0.0",
|
||||
"react-grid-gallery": "^1.0.1",
|
||||
"react-grid-layout": "1.3.4",
|
||||
"react-i18next": "^15.5.3",
|
||||
"react-i18next": "^15.6.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-image-lightbox": "^5.1.4",
|
||||
"react-markdown": "^10.1.0",
|
||||
@@ -118,7 +118,7 @@
|
||||
"vite": "^6.3.5",
|
||||
"vite-plugin-babel": "^1.3.2",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-node-polyfills": "^0.23.0",
|
||||
"vite-plugin-node-polyfills": "^0.24.0",
|
||||
"vite-plugin-pwa": "^1.0.1",
|
||||
"vite-plugin-style-import": "^2.0.0",
|
||||
"vitest": "^3.2.4",
|
||||
@@ -4466,50 +4466,50 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@sentry-internal/browser-utils": {
|
||||
"version": "9.34.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.34.0.tgz",
|
||||
"integrity": "sha512-pXVznvP4CROejYtk6y7UQvPTieWz2vXjukGlO45fsnQa9nNo30lkQh3Ws2HZw2YbTxYZQYx75FBDezwKl2q0hQ==",
|
||||
"version": "9.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.35.0.tgz",
|
||||
"integrity": "sha512-75/zOArDQ4ASgndKGQo0m0v8P921eq/Q/sJvR14NopzwuwAchBhjziixWCwxKgvoA20eg3OGwMIkzztxmdp2Tw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "9.34.0"
|
||||
"@sentry/core": "9.35.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/feedback": {
|
||||
"version": "9.34.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.34.0.tgz",
|
||||
"integrity": "sha512-HT/EBRl1DR8XqlJk2wFNPJFcnIzNcEDjmW7C/o7K0GeP5jcSH0dKpcH7ykz2bi46gMRPrkO5EK2eXGK81KYI3g==",
|
||||
"version": "9.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.35.0.tgz",
|
||||
"integrity": "sha512-IKaZWUmqqqLucuJ5EGgwdrBdvP3l3STXvgKsLmW2l+s9WYbvfPPHukZhUULYRsXleQKXnOuz44WQmwNeZYQutw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "9.34.0"
|
||||
"@sentry/core": "9.35.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay": {
|
||||
"version": "9.34.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.34.0.tgz",
|
||||
"integrity": "sha512-joYSqWltmpkcqI8Gg8jwFtPv0F01whmuQfNGoGaL7Z6B/xO1vvkqEudrg1tmswUHhqtYpZYaEaCvrmv0sPGCfA==",
|
||||
"version": "9.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.35.0.tgz",
|
||||
"integrity": "sha512-veGNAXeHXULzkGPudMg5iFqkW4wFD/qVbQSr+s0q3+IZ7vJ+Eql+eBDZEKrfKYIBdNOf5POr+KaEBMpMGCbEkQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/browser-utils": "9.34.0",
|
||||
"@sentry/core": "9.34.0"
|
||||
"@sentry-internal/browser-utils": "9.35.0",
|
||||
"@sentry/core": "9.35.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay-canvas": {
|
||||
"version": "9.34.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.34.0.tgz",
|
||||
"integrity": "sha512-GCtqMFk9WwrU3JNz1tlCFAhzmNfgZhLRaS0cLzoTuxPbG3CC2VUIWYEOw7+AdCJZGm8ElTMxu+BkChgGb8qthQ==",
|
||||
"version": "9.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.35.0.tgz",
|
||||
"integrity": "sha512-nXxrEIkpn+FBxYsD4JPQStEGQWF0j0Rs0LoCyuB1e2QeEg6Pipqg4DIjWDjZyeUAsdoaUsIRhWbMK5OBWUuudw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/replay": "9.34.0",
|
||||
"@sentry/core": "9.34.0"
|
||||
"@sentry-internal/replay": "9.35.0",
|
||||
"@sentry/core": "9.35.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -4525,16 +4525,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/browser": {
|
||||
"version": "9.34.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.34.0.tgz",
|
||||
"integrity": "sha512-6oJxU7JEA/RCgMTVlHXT54U9d0DWg61GgzyLTM+FUa8OUrAoK/t+CZGSMc/13nYN8xs7vcpiORdRx0ogch9zGw==",
|
||||
"version": "9.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.35.0.tgz",
|
||||
"integrity": "sha512-m1fRwMa1vik6VFAAz6RlJUUU+0+Uo+QIKJWWOx9calb11Zt4wIg9wvox7TOgMd8KPt3sefPXIPM38A+uixyXYw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/browser-utils": "9.34.0",
|
||||
"@sentry-internal/feedback": "9.34.0",
|
||||
"@sentry-internal/replay": "9.34.0",
|
||||
"@sentry-internal/replay-canvas": "9.34.0",
|
||||
"@sentry/core": "9.34.0"
|
||||
"@sentry-internal/browser-utils": "9.35.0",
|
||||
"@sentry-internal/feedback": "9.35.0",
|
||||
"@sentry-internal/replay": "9.35.0",
|
||||
"@sentry-internal/replay-canvas": "9.35.0",
|
||||
"@sentry/core": "9.35.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -4911,22 +4911,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "9.34.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.34.0.tgz",
|
||||
"integrity": "sha512-M/zikVaE3KLkhCFDyrHB35sF7pVkB2RPy07BcRsdFsSsdpjoG+Zq2Sxth2tMTbjd0x9Vtb/X6LVjyCj9GSEvVg==",
|
||||
"version": "9.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.35.0.tgz",
|
||||
"integrity": "sha512-bdAtzVQZ/wn4L/m8r2OUCCG/NWr0Q8dyZDwdwvINJaMbyhDRUdQh/MWjrz+id/3JoOL1LigAyTV1h4FJDGuwUQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/react": {
|
||||
"version": "9.34.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.34.0.tgz",
|
||||
"integrity": "sha512-xrai0g8qBS0AyiAytHlrBiTPu1zG7DNNh4GodAkHcd1j2iVti2c+AR7KgUY7UrsrjXd8Fpy7c+qo+5DnHLpulw==",
|
||||
"version": "9.35.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.35.0.tgz",
|
||||
"integrity": "sha512-zoLcucRYhSLKGYJ0b06MBVF+s3DvLK3YY651sf9boV071tWZs6Q8FDDD3E+pgw8t+ngL+6kB989Ns2HhyLyYIQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/browser": "9.34.0",
|
||||
"@sentry/core": "9.34.0",
|
||||
"@sentry/browser": "9.35.0",
|
||||
"@sentry/core": "9.35.0",
|
||||
"hoist-non-react-statics": "^3.3.2"
|
||||
},
|
||||
"engines": {
|
||||
@@ -6120,9 +6120,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/antd": {
|
||||
"version": "5.26.3",
|
||||
"resolved": "https://registry.npmjs.org/antd/-/antd-5.26.3.tgz",
|
||||
"integrity": "sha512-M/s9Q39h/+G7AWnS6fbNxmAI9waTH4ti022GVEXBLq2j810V1wJ3UOQps13nEilzDNcyxnFN/EIbqIgS7wSYaA==",
|
||||
"version": "5.26.4",
|
||||
"resolved": "https://registry.npmjs.org/antd/-/antd-5.26.4.tgz",
|
||||
"integrity": "sha512-e1EnOvEkvvqcQ18dxfzChBJyJACyih13WpNf2OtnP9z2POh/SF0fXL+ynUemT1zfr+p+P1po/tmHXaMc5PMghg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^7.2.1",
|
||||
@@ -13610,9 +13610,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/query-string": {
|
||||
"version": "9.2.1",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-9.2.1.tgz",
|
||||
"integrity": "sha512-3jTGGLRzlhu/1ws2zlr4Q+GVMLCQTLFOj8CMX5x44cdZG9FQE07x2mQhaNxaKVPNmIDu0mvJ/cEwtY7Pim7hqA==",
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-9.2.2.tgz",
|
||||
"integrity": "sha512-pDSIZJ9sFuOp6VnD+5IkakSVf+rICAuuU88Hcsr6AKL0QtxSIfVuKiVP2oahFI7tk3CRSexwV+Ya6MOoTxzg9g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"decode-uri-component": "^0.4.1",
|
||||
@@ -14441,9 +14441,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-i18next": {
|
||||
"version": "15.5.3",
|
||||
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.5.3.tgz",
|
||||
"integrity": "sha512-ypYmOKOnjqPEJZO4m1BI0kS8kWqkBNsKYyhVUfij0gvjy9xJNoG/VcGkxq5dRlVwzmrmY1BQMAmpbbUBLwC4Kw==",
|
||||
"version": "15.6.0",
|
||||
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.6.0.tgz",
|
||||
"integrity": "sha512-W135dB0rDfiFmbMipC17nOhGdttO5mzH8BivY+2ybsQBbXvxWIwl3cmeH3T9d+YPBSJu/ouyJKFJTtkK7rJofw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.27.6",
|
||||
@@ -17680,9 +17680,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite-plugin-node-polyfills": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.23.0.tgz",
|
||||
"integrity": "sha512-4n+Ys+2bKHQohPBKigFlndwWQ5fFKwaGY6muNDMTb0fSQLyBzS+jjUNRZG9sKF0S/Go4ApG6LFnUGopjkILg3w==",
|
||||
"version": "0.24.0",
|
||||
"resolved": "https://registry.npmjs.org/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.24.0.tgz",
|
||||
"integrity": "sha512-GA9QKLH+vIM8NPaGA+o2t8PDfFUl32J8rUp1zQfMKVJQiNkOX4unE51tR6ppl6iKw5yOrDAdSH7r/UIFLCVhLw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -17693,7 +17693,7 @@
|
||||
"url": "https://github.com/sponsors/davidmyersdev"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0"
|
||||
"vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vite-plugin-pwa": {
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
"@jsreport/browser-client": "^3.1.0",
|
||||
"@reduxjs/toolkit": "^2.8.2",
|
||||
"@sentry/cli": "^2.46.0",
|
||||
"@sentry/react": "^9.34.0",
|
||||
"@sentry/react": "^9.35.0",
|
||||
"@sentry/vite-plugin": "^3.5.0",
|
||||
"@splitsoftware/splitio-react": "^2.3.1",
|
||||
"@tanem/react-nprogress": "^5.0.53",
|
||||
"antd": "^5.26.3",
|
||||
"antd": "^5.26.4",
|
||||
"apollo-link-logger": "^2.0.1",
|
||||
"apollo-link-sentry": "^4.3.0",
|
||||
"autosize": "^6.0.1",
|
||||
@@ -49,7 +49,7 @@
|
||||
"object-hash": "^3.0.0",
|
||||
"phone": "^3.1.62",
|
||||
"prop-types": "^15.8.1",
|
||||
"query-string": "^9.2.1",
|
||||
"query-string": "^9.2.2",
|
||||
"raf-schd": "^4.0.3",
|
||||
"react": "^18.3.1",
|
||||
"react-big-calendar": "^1.19.4",
|
||||
@@ -59,7 +59,7 @@
|
||||
"react-drag-listview": "^2.0.0",
|
||||
"react-grid-gallery": "^1.0.1",
|
||||
"react-grid-layout": "1.3.4",
|
||||
"react-i18next": "^15.5.3",
|
||||
"react-i18next": "^15.6.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-image-lightbox": "^5.1.4",
|
||||
"react-markdown": "^10.1.0",
|
||||
@@ -158,7 +158,7 @@
|
||||
"vite": "^6.3.5",
|
||||
"vite-plugin-babel": "^1.3.2",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-node-polyfills": "^0.23.0",
|
||||
"vite-plugin-node-polyfills": "^0.24.0",
|
||||
"vite-plugin-pwa": "^1.0.1",
|
||||
"vite-plugin-style-import": "^2.0.0",
|
||||
"vitest": "^3.2.4",
|
||||
|
||||
54
server/integrations/partsManagement/partsManagementUtils.js
Normal file
54
server/integrations/partsManagement/partsManagementUtils.js
Normal file
@@ -0,0 +1,54 @@
|
||||
const xml2js = require("xml2js");
|
||||
|
||||
/**
|
||||
* Parses XML string into a JavaScript object.
|
||||
* @param {string} xml - The XML string to parse.
|
||||
* @param {object} logger - The logger instance.
|
||||
* @returns {Promise<object>} The parsed XML object.
|
||||
* @throws {Error} If XML parsing fails.
|
||||
*/
|
||||
const parseXml = async (xml, logger) => {
|
||||
try {
|
||||
return await xml2js.parseStringPromise(xml, {
|
||||
explicitArray: false,
|
||||
tagNameProcessors: [xml2js.processors.stripPrefix],
|
||||
attrNameProcessors: [xml2js.processors.stripPrefix]
|
||||
});
|
||||
} catch (err) {
|
||||
logger.log("parts-xml-parse-error", "error", null, null, { error: err });
|
||||
throw new Error("Invalid XML");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Recursively strip `xml2js`-style { _: 'value', $: { ... } } nodes into plain strings.
|
||||
* @param {*} obj - Parsed XML object
|
||||
* @returns {*} Normalized object
|
||||
*/
|
||||
const normalizeXmlObject = (obj) => {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map(normalizeXmlObject);
|
||||
}
|
||||
|
||||
if (typeof obj === "object" && obj !== null) {
|
||||
if (Object.keys(obj).length === 2 && "_" in obj && "$" in obj) {
|
||||
return normalizeXmlObject(obj._); // unwrap {_:"value",$:{...}} to just "value"
|
||||
}
|
||||
if (Object.keys(obj).length === 1 && "_" in obj) {
|
||||
return normalizeXmlObject(obj._); // unwrap {_:"value"}
|
||||
}
|
||||
|
||||
const normalized = {};
|
||||
for (const key in obj) {
|
||||
normalized[key] = normalizeXmlObject(obj[key]);
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
parseXml,
|
||||
normalizeXmlObject
|
||||
};
|
||||
@@ -1,8 +1,8 @@
|
||||
// no-dd-sa:javascript-code-style/assignment-name
|
||||
// CamelCase is used for GraphQL and database fields.
|
||||
|
||||
const xml2js = require("xml2js");
|
||||
const client = require("../../graphql-client/graphql-client").client;
|
||||
const { parseXml, normalizeXmlObject } = require("./partsManagementUtils");
|
||||
|
||||
// GraphQL Queries and Mutations
|
||||
const {
|
||||
@@ -34,55 +34,6 @@ const KNOWN_PART_RATE_TYPES = [
|
||||
"CCM",
|
||||
"CCDR"
|
||||
];
|
||||
|
||||
/**
|
||||
* Parses XML string into a JavaScript object.
|
||||
* @param {string} xml - The XML string to parse.
|
||||
* @param {object} logger - The logger instance.
|
||||
* @returns {Promise<object>} The parsed XML object.
|
||||
* @throws {Error} If XML parsing fails.
|
||||
*/
|
||||
const parseXml = async (xml, logger) => {
|
||||
try {
|
||||
return await xml2js.parseStringPromise(xml, {
|
||||
explicitArray: false,
|
||||
tagNameProcessors: [xml2js.processors.stripPrefix],
|
||||
attrNameProcessors: [xml2js.processors.stripPrefix]
|
||||
});
|
||||
} catch (err) {
|
||||
logger.log("parts-xml-parse-error", "error", null, null, { error: err });
|
||||
throw new Error("Invalid XML");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Recursively strip `xml2js`-style { _: 'value', $: { ... } } nodes into plain strings.
|
||||
* @param {*} obj - Parsed XML object
|
||||
* @returns {*} Normalized object
|
||||
*/
|
||||
const normalizeXmlObject = (obj) => {
|
||||
if (Array.isArray(obj)) {
|
||||
return obj.map(normalizeXmlObject);
|
||||
}
|
||||
|
||||
if (typeof obj === "object" && obj !== null) {
|
||||
if (Object.keys(obj).length === 2 && "_" in obj && "$" in obj) {
|
||||
return normalizeXmlObject(obj._); // unwrap {_:"value",$:{...}} to just "value"
|
||||
}
|
||||
if (Object.keys(obj).length === 1 && "_" in obj) {
|
||||
return normalizeXmlObject(obj._); // unwrap {_:"value"}
|
||||
}
|
||||
|
||||
const normalized = {};
|
||||
for (const key in obj) {
|
||||
normalized[key] = normalizeXmlObject(obj[key]);
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetches the default order status for a bodyshop.
|
||||
* @param {string} shopId - The bodyshop UUID.
|
||||
@@ -508,7 +459,7 @@ const insertOwner = async (ownerInput, logger) => {
|
||||
* @param {object} res - The HTTP response object.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const partsManagementVehicleDamageEstimateAddRq = async (req, res) => {
|
||||
const vehicleDamageEstimateAddRq = async (req, res) => {
|
||||
const { logger } = req;
|
||||
|
||||
try {
|
||||
@@ -617,4 +568,4 @@ const partsManagementVehicleDamageEstimateAddRq = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = partsManagementVehicleDamageEstimateAddRq;
|
||||
module.exports = vehicleDamageEstimateAddRq;
|
||||
@@ -0,0 +1,106 @@
|
||||
// no-dd-sa:javascript-code-style/assignment-name
|
||||
// Handler for VehicleDamageEstimateChgRq
|
||||
|
||||
const client = require("../../graphql-client/graphql-client").client;
|
||||
const { parseXml, normalizeXmlObject } = require("./partsManagementUtils");
|
||||
|
||||
const {
|
||||
GET_JOB_BY_CLAIM_OR_DOCID,
|
||||
UPDATE_JOB_BY_PK,
|
||||
UPSERT_JOBLINES,
|
||||
DELETE_JOBLINES_BY_IDS
|
||||
} = require("./partsManagement.queries");
|
||||
|
||||
const findJob = async (claimNum, documentId, logger) => {
|
||||
try {
|
||||
const { jobs } = await client.request(GET_JOB_BY_CLAIM_OR_DOCID, { claimNum, documentId });
|
||||
return jobs?.[0] || null;
|
||||
} catch (err) {
|
||||
logger.log("parts-job-lookup-failed", "error", null, null, { error: err });
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const extractUpdatedJobData = (rq) => {
|
||||
const doc = rq.DocumentInfo || {};
|
||||
const claim = rq.ClaimInfo || {};
|
||||
|
||||
return {
|
||||
comment: doc.Comment || null,
|
||||
clm_no: claim.ClaimNum || null,
|
||||
status: claim.ClaimStatus || null,
|
||||
policy_no: claim.PolicyInfo?.PolicyNum || null
|
||||
};
|
||||
};
|
||||
|
||||
const extractUpdatedJobLines = (addsChgs = {}) => {
|
||||
const lines = Array.isArray(addsChgs.DamageLineInfo) ? addsChgs.DamageLineInfo : [addsChgs.DamageLineInfo || []];
|
||||
|
||||
return lines.map((line) => ({
|
||||
line_no: parseInt(line.LineNum, 10),
|
||||
unq_seq: parseInt(line.UniqueSequenceNum, 10),
|
||||
status: line.LineStatusCode || null,
|
||||
line_desc: line.LineDesc || null,
|
||||
part_type: line.PartInfo?.PartType || null,
|
||||
part_qty: parseFloat(line.PartInfo?.Quantity || 0),
|
||||
oem_partno: line.PartInfo?.OEMPartNum || null,
|
||||
db_price: parseFloat(line.PartInfo?.PartPrice || 0),
|
||||
act_price: parseFloat(line.PartInfo?.PartPrice || 0),
|
||||
mod_lbr_ty: line.LaborInfo?.LaborType || null,
|
||||
mod_lb_hrs: parseFloat(line.LaborInfo?.LaborHours || 0),
|
||||
lbr_op: line.LaborInfo?.LaborOperation || null,
|
||||
lbr_amt: parseFloat(line.LaborInfo?.LaborAmt || 0),
|
||||
notes: line.LineMemo || null,
|
||||
manual_line: line.ManualLineInd || null
|
||||
}));
|
||||
};
|
||||
|
||||
const extractDeletions = (deletions = {}) => {
|
||||
const lines = Array.isArray(deletions.DamageLineInfo) ? deletions.DamageLineInfo : [deletions.DamageLineInfo || []];
|
||||
|
||||
return lines.map((line) => parseInt(line.UniqueSequenceNum, 10)).filter((id) => !isNaN(id));
|
||||
};
|
||||
|
||||
const partsManagementVehicleDamageEstimateChgRq = async (req, res) => {
|
||||
const { logger } = req;
|
||||
|
||||
try {
|
||||
const payload = await parseXml(req.body, logger);
|
||||
const rq = normalizeXmlObject(payload.VehicleDamageEstimateChgRq);
|
||||
if (!rq) return res.status(400).send("Missing <VehicleDamageEstimateChgRq>");
|
||||
|
||||
const shopId = rq.ShopID;
|
||||
const claimNum = rq.ClaimInfo?.ClaimNum;
|
||||
const documentId = rq.DocumentInfo?.DocumentID;
|
||||
|
||||
if (!shopId || !claimNum) return res.status(400).send("Missing ShopID or ClaimNum");
|
||||
|
||||
const job = await findJob(claimNum, documentId, logger);
|
||||
if (!job) return res.status(404).send("Job not found");
|
||||
|
||||
const updatedJobData = extractUpdatedJobData(rq);
|
||||
const updatedLines = extractUpdatedJobLines(rq.AddsChgs);
|
||||
const deletedLineIds = extractDeletions(rq.Deletions);
|
||||
|
||||
await client.request(UPDATE_JOB_BY_PK, { id: job.id, changes: updatedJobData });
|
||||
|
||||
if (updatedLines.length > 0) {
|
||||
await client.request(UPSERT_JOBLINES, {
|
||||
jobid: job.id,
|
||||
joblines: updatedLines
|
||||
});
|
||||
}
|
||||
|
||||
if (deletedLineIds.length > 0) {
|
||||
await client.request(DELETE_JOBLINES_BY_IDS, { jobid: job.id, unqSeqs: deletedLineIds });
|
||||
}
|
||||
|
||||
logger.log("parts-job-changed", "info", job.id, null);
|
||||
return res.status(200).json({ success: true, jobId: job.id });
|
||||
} catch (err) {
|
||||
logger.log("parts-chgrq-error", "error", null, null, { error: err });
|
||||
return res.status(err.status || 500).json({ error: err.message || "Internal error" });
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = partsManagementVehicleDamageEstimateChgRq;
|
||||
@@ -1,6 +1,6 @@
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
const bodyParser = require("body-parser"); // Add body-parser dependency
|
||||
const bodyParser = require("body-parser");
|
||||
|
||||
// Pull secrets from env
|
||||
const { VSSTA_INTEGRATION_SECRET, PARTS_MANAGEMENT_INTEGRATION_SECRET } = process.env;
|
||||
@@ -17,18 +17,36 @@ if (typeof VSSTA_INTEGRATION_SECRET === "string" && VSSTA_INTEGRATION_SECRET.len
|
||||
|
||||
// Only load Parts Management routes if that secret is set
|
||||
if (typeof PARTS_MANAGEMENT_INTEGRATION_SECRET === "string" && PARTS_MANAGEMENT_INTEGRATION_SECRET.length > 0) {
|
||||
const XML_BODY_LIMIT = "10mb"; // Set a limit for XML body size
|
||||
|
||||
const partsManagementProvisioning = require("../integrations/partsManagement/partsManagementProvisioning");
|
||||
const partsManagementIntegrationMiddleware = require("../middleware/partsManagementIntegrationMiddleware");
|
||||
const partsManagementVehicleDamageEstimateAddRq = require("../integrations/partsManagement/partsManagementVehicleDamageEstimateAddRq");
|
||||
const partsManagementVehicleDamageEstimateAddRq = require("../integrations/partsManagement/vehicleDamageEstimateAddRq");
|
||||
const partsManagementVehicleDamageEstimateChqRq = require("../integrations/partsManagement/vehicleDamageEstimateChgRq");
|
||||
|
||||
// Add XML parsing middleware for the VehicleDamageEstimateAddRq route
|
||||
/**
|
||||
* Route to handle Vehicle Damage Estimate Add Request
|
||||
*/
|
||||
router.post(
|
||||
"/parts-management/VehicleDamageEstimateAddRq",
|
||||
bodyParser.raw({ type: "application/xml", limit: "10mb" }), // Parse XML body
|
||||
bodyParser.raw({ type: "application/xml", limit: XML_BODY_LIMIT }), // Parse XML body
|
||||
partsManagementIntegrationMiddleware,
|
||||
partsManagementVehicleDamageEstimateAddRq
|
||||
);
|
||||
|
||||
/**
|
||||
* Route to handle Vehicle Damage Estimate Change Request
|
||||
*/
|
||||
router.post(
|
||||
"/parts-management/VehicleDamageEstimateChgRq",
|
||||
bodyParser.raw({ type: "application/xml", limit: XML_BODY_LIMIT }), // Parse XML body
|
||||
partsManagementIntegrationMiddleware,
|
||||
partsManagementVehicleDamageEstimateChqRq
|
||||
);
|
||||
|
||||
/**
|
||||
* Route to handle Parts Management Provisioning
|
||||
*/
|
||||
router.post("/parts-management/provision", partsManagementIntegrationMiddleware, partsManagementProvisioning);
|
||||
} else {
|
||||
console.warn("PARTS_MANAGEMENT_INTEGRATION_SECRET is not set — skipping /parts-management/provision route");
|
||||
|
||||
Reference in New Issue
Block a user