Merged in feature/IO-3390-parts-management-2 (pull request #2615)
feature/IO-3390-Parts-Management-2 - Add Job status patch route, Bodyshop Patch route, remove PAO from simplified parts filter.
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
# PATCH /integrations/parts-management/job/:id/status
|
||||
|
||||
Update (patch) the status of a job created under parts management. This endpoint is only available
|
||||
for jobs whose parent bodyshop has an `external_shop_id` (i.e., is provisioned for parts
|
||||
management).
|
||||
|
||||
## Endpoint
|
||||
|
||||
```
|
||||
PATCH /integrations/parts-management/job/:id/status
|
||||
```
|
||||
|
||||
- `:id` is the UUID of the job to update.
|
||||
|
||||
## Request Headers
|
||||
|
||||
- `Authorization`: (if required by your integration middleware)
|
||||
- `Content-Type: application/json`
|
||||
|
||||
## Request Body
|
||||
|
||||
Send a JSON object with the following field:
|
||||
|
||||
- `status` (string, required): The new status for the job.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
PATCH /integrations/parts-management/job/123e4567-e89b-12d3-a456-426614174000/status
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"status": "IN_PROGRESS"
|
||||
}
|
||||
```
|
||||
|
||||
## Success Response
|
||||
|
||||
- **200 OK**
|
||||
- Returns the updated job object with the new status.
|
||||
|
||||
```
|
||||
{
|
||||
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"status": "IN_PROGRESS",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Error Responses
|
||||
|
||||
- **400 Bad Request**: Missing status field, or parent bodyshop does not have an `external_shop_id`.
|
||||
- **404 Not Found**: No job found with the given ID.
|
||||
- **500 Internal Server Error**: Unexpected error.
|
||||
|
||||
## Notes
|
||||
|
||||
- Only jobs whose parent bodyshop has an `external_shop_id` can be patched via this route.
|
||||
- Fields other than `status` will be ignored if included in the request body.
|
||||
- The route is protected by the same middleware as other parts management endpoints.
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
# PATCH /integrations/parts-management/provision/:id
|
||||
|
||||
Update (patch) select fields for a parts management bodyshop. Only available for shops that have an
|
||||
`external_shop_id` (i.e., are provisioned for parts management).
|
||||
|
||||
## Endpoint
|
||||
|
||||
```
|
||||
PATCH /integrations/parts-management/provision/:id
|
||||
```
|
||||
|
||||
- `:id` is the UUID of the bodyshop to update.
|
||||
|
||||
## Request Headers
|
||||
|
||||
- `Authorization`: (if required by your integration middleware)
|
||||
- `Content-Type: application/json`
|
||||
|
||||
## Request Body
|
||||
|
||||
Send a JSON object with one or more of the following fields to update:
|
||||
|
||||
- `shopname` (string)
|
||||
- `address1` (string)
|
||||
- `address2` (string, optional)
|
||||
- `city` (string)
|
||||
- `state` (string)
|
||||
- `zip_post` (string)
|
||||
- `country` (string)
|
||||
- `email` (string, shop's email, not user email)
|
||||
- `timezone` (string)
|
||||
- `phone` (string)
|
||||
- `logo_img_path` (object, e.g. `{ src, width, height, headerMargin }`)
|
||||
|
||||
Any fields not included in the request body will remain unchanged.
|
||||
|
||||
## Example Request
|
||||
|
||||
```
|
||||
PATCH /integrations/parts-management/provision/123e4567-e89b-12d3-a456-426614174000
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"shopname": "New Shop Name",
|
||||
"address1": "123 Main St",
|
||||
"city": "Springfield",
|
||||
"state": "IL",
|
||||
"zip_post": "62704",
|
||||
"country": "USA",
|
||||
"email": "shop@example.com",
|
||||
"timezone": "America/Chicago",
|
||||
"phone": "555-123-4567",
|
||||
"logo_img_path": {
|
||||
"src": "https://example.com/logo.png",
|
||||
"width": "200",
|
||||
"height": "100",
|
||||
"headerMargin": 10
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Success Response
|
||||
|
||||
- **200 OK**
|
||||
- Returns the updated shop object with the patched fields.
|
||||
|
||||
```
|
||||
{
|
||||
"id": "123e4567-e89b-12d3-a456-426614174000",
|
||||
"shopname": "New Shop Name",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Error Responses
|
||||
|
||||
- **400 Bad Request**: No valid fields provided, or shop does not have an `external_shop_id`.
|
||||
- **404 Not Found**: No shop found with the given ID.
|
||||
- **500 Internal Server Error**: Unexpected error.
|
||||
|
||||
## Notes
|
||||
|
||||
- Only shops with an `external_shop_id` can be patched via this route.
|
||||
- Fields not listed above will be ignored if included in the request body.
|
||||
- The route is protected by the same middleware as other parts management endpoints.
|
||||
|
||||
728
client/package-lock.json
generated
728
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -8,56 +8,56 @@
|
||||
"private": true,
|
||||
"proxy": "http://localhost:4000",
|
||||
"dependencies": {
|
||||
"@amplitude/analytics-browser": "^2.23.5",
|
||||
"@amplitude/analytics-browser": "^2.25.2",
|
||||
"@ant-design/pro-layout": "^7.22.6",
|
||||
"@apollo/client": "^3.13.9",
|
||||
"@emotion/is-prop-valid": "^1.4.0",
|
||||
"@fingerprintjs/fingerprintjs": "^4.6.1",
|
||||
"@firebase/analytics": "^0.10.17",
|
||||
"@firebase/app": "^0.14.2",
|
||||
"@firebase/app": "^0.14.3",
|
||||
"@firebase/auth": "^1.10.8",
|
||||
"@firebase/firestore": "^4.9.1",
|
||||
"@firebase/firestore": "^4.9.2",
|
||||
"@firebase/messaging": "^0.12.22",
|
||||
"@jsreport/browser-client": "^3.1.0",
|
||||
"@reduxjs/toolkit": "^2.9.0",
|
||||
"@sentry/cli": "^2.53.0",
|
||||
"@sentry/cli": "^2.56.0",
|
||||
"@sentry/react": "^9.43.0",
|
||||
"@sentry/vite-plugin": "^4.3.0",
|
||||
"@splitsoftware/splitio-react": "^2.3.1",
|
||||
"@splitsoftware/splitio-react": "^2.5.0",
|
||||
"@tanem/react-nprogress": "^5.0.53",
|
||||
"antd": "^5.27.3",
|
||||
"antd": "^5.27.4",
|
||||
"apollo-link-logger": "^2.0.1",
|
||||
"apollo-link-sentry": "^4.4.0",
|
||||
"autosize": "^6.0.1",
|
||||
"axios": "^1.11.0",
|
||||
"axios": "^1.12.2",
|
||||
"classnames": "^2.5.1",
|
||||
"css-box-model": "^1.2.1",
|
||||
"dayjs": "^1.11.18",
|
||||
"dayjs-business-days2": "^1.3.0",
|
||||
"dinero.js": "^1.9.1",
|
||||
"dotenv": "^17.2.2",
|
||||
"dotenv": "^17.2.3",
|
||||
"env-cmd": "^10.1.0",
|
||||
"exifr": "^7.1.3",
|
||||
"graphql": "^16.11.0",
|
||||
"i18next": "^25.5.2",
|
||||
"i18next": "^25.5.3",
|
||||
"i18next-browser-languagedetector": "^8.2.0",
|
||||
"immutability-helper": "^3.1.1",
|
||||
"libphonenumber-js": "^1.12.15",
|
||||
"libphonenumber-js": "^1.12.23",
|
||||
"lightningcss": "^1.30.2",
|
||||
"logrocket": "^9.0.2",
|
||||
"markerjs2": "^2.32.6",
|
||||
"markerjs2": "^2.32.7",
|
||||
"memoize-one": "^6.0.0",
|
||||
"normalize-url": "^8.0.2",
|
||||
"normalize-url": "^8.1.0",
|
||||
"object-hash": "^3.0.0",
|
||||
"phone": "^3.1.67",
|
||||
"posthog-js": "^1.261.7",
|
||||
"posthog-js": "^1.271.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"query-string": "^9.2.2",
|
||||
"query-string": "^9.3.1",
|
||||
"raf-schd": "^4.0.3",
|
||||
"react": "^18.3.1",
|
||||
"react-big-calendar": "^1.19.4",
|
||||
"react-color": "^2.19.3",
|
||||
"react-cookie": "^8.0.1",
|
||||
"lightningcss": "^1.30.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-drag-listview": "^2.0.0",
|
||||
"react-grid-gallery": "^1.0.1",
|
||||
@@ -73,7 +73,7 @@
|
||||
"react-resizable": "^3.0.5",
|
||||
"react-router-dom": "^6.30.0",
|
||||
"react-sticky": "^6.0.3",
|
||||
"react-virtuoso": "^4.14.0",
|
||||
"react-virtuoso": "^4.14.1",
|
||||
"recharts": "^2.15.2",
|
||||
"redux": "^5.0.1",
|
||||
"redux-actions": "^3.0.3",
|
||||
@@ -81,7 +81,7 @@
|
||||
"redux-saga": "^1.3.0",
|
||||
"redux-state-sync": "^3.1.4",
|
||||
"reselect": "^5.1.1",
|
||||
"sass": "^1.92.0",
|
||||
"sass": "^1.93.2",
|
||||
"socket.io-client": "^4.8.1",
|
||||
"styled-components": "^6.1.19",
|
||||
"subscriptions-transport-ws": "^0.11.0",
|
||||
@@ -133,33 +133,33 @@
|
||||
"@rollup/rollup-linux-x64-gnu": "4.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ant-design/icons": "^6.0.0",
|
||||
"@ant-design/icons": "^6.1.0",
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"@babel/preset-react": "^7.27.1",
|
||||
"@dotenvx/dotenvx": "^1.49.0",
|
||||
"@dotenvx/dotenvx": "^1.51.0",
|
||||
"@emotion/babel-plugin": "^11.13.5",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@eslint/js": "^9.33.0",
|
||||
"@playwright/test": "^1.55.0",
|
||||
"@sentry/webpack-plugin": "^4.1.1",
|
||||
"@eslint/js": "^9.37.0",
|
||||
"@playwright/test": "^1.56.0",
|
||||
"@sentry/webpack-plugin": "^4.3.0",
|
||||
"@testing-library/dom": "^10.4.1",
|
||||
"@testing-library/jest-dom": "^6.8.0",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"@vitejs/plugin-react": "^4.6.0",
|
||||
"browserslist": "^4.25.3",
|
||||
"browserslist": "^4.26.3",
|
||||
"browserslist-to-esbuild": "^2.1.1",
|
||||
"chalk": "^5.6.0",
|
||||
"eslint": "^9.33.0",
|
||||
"chalk": "^5.6.2",
|
||||
"eslint": "^9.37.0",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"globals": "^15.15.0",
|
||||
"jsdom": "^26.0.0",
|
||||
"memfs": "^4.36.3",
|
||||
"memfs": "^4.48.1",
|
||||
"os-browserify": "^0.3.0",
|
||||
"playwright": "^1.55.0",
|
||||
"playwright": "^1.56.0",
|
||||
"react-error-overlay": "^6.1.0",
|
||||
"redux-logger": "^3.0.6",
|
||||
"source-map-explorer": "^2.5.3",
|
||||
"vite": "^7.1.3",
|
||||
"vite": "^7.1.9",
|
||||
"vite-plugin-babel": "^1.3.2",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-node-polyfills": "^0.24.0",
|
||||
|
||||
@@ -97,7 +97,7 @@ export function JobLinesComponent({
|
||||
filteredInfo: {
|
||||
...(isPartsEntry
|
||||
? {
|
||||
part_type: ["PAN", "PAC", "PAR", "PAL", "PAA", "PAM", "PAP", "PAS", "PASL", "PAG", "PAO"]
|
||||
part_type: ["PAN", "PAC", "PAR", "PAL", "PAA", "PAM", "PAP", "PAS", "PASL", "PAG"] //"PAO" Removed by request
|
||||
}
|
||||
: {})
|
||||
}
|
||||
|
||||
2155
package-lock.json
generated
2155
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
40
package.json
40
package.json
@@ -18,40 +18,40 @@
|
||||
"job-totals-fixtures:local": "docker exec node-app /usr/bin/node /app/download-job-totals-fixtures.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-cloudwatch-logs": "^3.882.0",
|
||||
"@aws-sdk/client-elasticache": "^3.882.0",
|
||||
"@aws-sdk/client-s3": "^3.882.0",
|
||||
"@aws-sdk/client-secrets-manager": "^3.882.0",
|
||||
"@aws-sdk/client-ses": "^3.882.0",
|
||||
"@aws-sdk/credential-provider-node": "^3.882.0",
|
||||
"@aws-sdk/lib-storage": "^3.882.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.882.0",
|
||||
"@aws-sdk/client-cloudwatch-logs": "^3.901.0",
|
||||
"@aws-sdk/client-elasticache": "^3.901.0",
|
||||
"@aws-sdk/client-s3": "^3.901.0",
|
||||
"@aws-sdk/client-secrets-manager": "^3.901.0",
|
||||
"@aws-sdk/client-ses": "^3.901.0",
|
||||
"@aws-sdk/credential-provider-node": "^3.901.0",
|
||||
"@aws-sdk/lib-storage": "^3.903.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.901.0",
|
||||
"@opensearch-project/opensearch": "^2.13.0",
|
||||
"@socket.io/admin-ui": "^0.5.1",
|
||||
"@socket.io/redis-adapter": "^8.3.0",
|
||||
"archiver": "^7.0.1",
|
||||
"aws4": "^1.13.2",
|
||||
"axios": "^1.11.0",
|
||||
"axios": "^1.12.2",
|
||||
"better-queue": "^3.8.12",
|
||||
"bullmq": "^5.58.5",
|
||||
"bullmq": "^5.61.0",
|
||||
"chart.js": "^4.5.0",
|
||||
"cloudinary": "^2.7.0",
|
||||
"compression": "^1.8.1",
|
||||
"cookie-parser": "^1.4.7",
|
||||
"cors": "^2.8.5",
|
||||
"crisp-status-reporter": "^1.2.2",
|
||||
"dd-trace": "^5.65.0",
|
||||
"dd-trace": "^5.70.0",
|
||||
"dinero.js": "^1.9.1",
|
||||
"dotenv": "^17.2.2",
|
||||
"dotenv": "^17.2.3",
|
||||
"express": "^4.21.1",
|
||||
"firebase-admin": "^13.5.0",
|
||||
"graphql": "^16.11.0",
|
||||
"graphql-request": "^6.1.0",
|
||||
"intuit-oauth": "^4.2.0",
|
||||
"ioredis": "^5.7.0",
|
||||
"ioredis": "^5.8.1",
|
||||
"json-2-csv": "^5.5.9",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"juice": "^11.0.1",
|
||||
"juice": "^11.0.3",
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.30.1",
|
||||
"moment-timezone": "^0.6.0",
|
||||
@@ -62,22 +62,22 @@
|
||||
"query-string": "7.1.3",
|
||||
"recursive-diff": "^1.0.9",
|
||||
"rimraf": "^6.0.1",
|
||||
"skia-canvas": "^3.0.6",
|
||||
"soap": "^1.3.0",
|
||||
"skia-canvas": "^3.0.8",
|
||||
"soap": "^1.5.0",
|
||||
"socket.io": "^4.8.1",
|
||||
"socket.io-adapter": "^2.5.5",
|
||||
"ssh2-sftp-client": "^11.0.0",
|
||||
"twilio": "^5.9.0",
|
||||
"twilio": "^5.10.2",
|
||||
"uuid": "^11.1.0",
|
||||
"winston": "^3.17.0",
|
||||
"winston": "^3.18.3",
|
||||
"winston-cloudwatch": "^6.3.0",
|
||||
"xml2js": "^0.6.2",
|
||||
"xmlbuilder2": "^3.1.1",
|
||||
"yazl": "^3.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.35.0",
|
||||
"eslint": "^9.35.0",
|
||||
"@eslint/js": "^9.37.0",
|
||||
"eslint": "^9.37.0",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"globals": "^15.15.0",
|
||||
"mock-require": "^3.0.3",
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
const logger = require("../utils/logger");
|
||||
|
||||
const GraphQLClient = require("graphql-request").GraphQLClient;
|
||||
|
||||
//New bug introduced with Graphql Request.
|
||||
@@ -14,17 +12,18 @@ const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {
|
||||
});
|
||||
|
||||
const rpsClient =
|
||||
process.env.RPS_GRAPHQL_ENDPOINT && process.env.RPS_HASURA_ADMIN_SECRET ?
|
||||
new GraphQLClient(process.env.RPS_GRAPHQL_ENDPOINT, {
|
||||
headers: {
|
||||
"x-hasura-admin-secret": process.env.RPS_HASURA_ADMIN_SECRET
|
||||
}
|
||||
}) : null;
|
||||
process.env.RPS_GRAPHQL_ENDPOINT && process.env.RPS_HASURA_ADMIN_SECRET
|
||||
? new GraphQLClient(process.env.RPS_GRAPHQL_ENDPOINT, {
|
||||
headers: {
|
||||
"x-hasura-admin-secret": process.env.RPS_HASURA_ADMIN_SECRET
|
||||
}
|
||||
})
|
||||
: null;
|
||||
|
||||
if (!rpsClient) {
|
||||
//System log to disable RPS functions
|
||||
logger.log(`RPS secrets are not set. Client is not configured.`, "WARN", "redis", "api", {
|
||||
});
|
||||
|
||||
console.log(`RPS secrets are not set. Client is not configured.`, "WARN", "redis", "api", {});
|
||||
}
|
||||
|
||||
const unauthorizedClient = new GraphQLClient(process.env.GRAPHQL_ENDPOINT);
|
||||
|
||||
@@ -7,7 +7,8 @@ const {
|
||||
CREATE_SHOP,
|
||||
DELETE_VENDORS_BY_SHOP,
|
||||
DELETE_SHOP,
|
||||
CREATE_USER
|
||||
CREATE_USER,
|
||||
UPDATE_BODYSHOP_BY_ID
|
||||
} = require("../partsManagement.queries");
|
||||
|
||||
/**
|
||||
@@ -131,6 +132,61 @@ const insertUserAssociation = async (uid, email, shopId) => {
|
||||
return resp.insert_users_one;
|
||||
};
|
||||
|
||||
/**
|
||||
* PATCH handler for updating bodyshop fields.
|
||||
* Allows patching: shopname, address1, address2, city, state, zip_post, country, email, timezone, phone, logo_img_path
|
||||
* @param req
|
||||
* @param res
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const patchPartsManagementProvisioning = async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const allowedFields = [
|
||||
"shopname",
|
||||
"address1",
|
||||
"address2",
|
||||
"city",
|
||||
"state",
|
||||
"zip_post",
|
||||
"country",
|
||||
"email",
|
||||
"timezone",
|
||||
"phone",
|
||||
"logo_img_path"
|
||||
];
|
||||
const updateFields = {};
|
||||
for (const field of allowedFields) {
|
||||
if (req.body[field] !== undefined) {
|
||||
updateFields[field] = req.body[field];
|
||||
}
|
||||
}
|
||||
if (Object.keys(updateFields).length === 0) {
|
||||
return res.status(400).json({ error: "No valid fields provided for update." });
|
||||
}
|
||||
// Check that the bodyshop has an external_shop_id before allowing patch
|
||||
try {
|
||||
// Fetch the bodyshop by id
|
||||
const shopResp = await client.request(
|
||||
`query GetBodyshop($id: uuid!) { bodyshops_by_pk(id: $id) { id external_shop_id } }`,
|
||||
{ id }
|
||||
);
|
||||
if (!shopResp.bodyshops_by_pk?.external_shop_id) {
|
||||
return res.status(400).json({ error: "Cannot patch: bodyshop does not have an external_shop_id." });
|
||||
}
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: "Failed to validate bodyshop external_shop_id.", detail: err });
|
||||
}
|
||||
try {
|
||||
const resp = await client.request(UPDATE_BODYSHOP_BY_ID, { id, fields: updateFields });
|
||||
if (!resp.update_bodyshops_by_pk) {
|
||||
return res.status(404).json({ error: "Bodyshop not found." });
|
||||
}
|
||||
return res.json(resp.update_bodyshops_by_pk);
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: "Failed to update bodyshop.", detail: err });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles provisioning a new shop for parts management.
|
||||
* @param req
|
||||
@@ -259,4 +315,4 @@ const partsManagementProvisioning = async (req, res) => {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = partsManagementProvisioning;
|
||||
module.exports = { partsManagementProvisioning, patchPartsManagementProvisioning };
|
||||
|
||||
@@ -298,6 +298,25 @@ const UPDATE_JOBLINE_BY_PK = `
|
||||
}
|
||||
`;
|
||||
|
||||
const UPDATE_BODYSHOP_BY_ID = `
|
||||
mutation UpdateBodyshopById($id: uuid!, $fields: bodyshops_set_input!) {
|
||||
update_bodyshops_by_pk(pk_columns: { id: $id }, _set: $fields) {
|
||||
id
|
||||
shopname
|
||||
address1
|
||||
address2
|
||||
city
|
||||
state
|
||||
zip_post
|
||||
country
|
||||
email
|
||||
timezone
|
||||
phone
|
||||
logo_img_path
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
module.exports = {
|
||||
GET_BODYSHOP_STATUS,
|
||||
GET_VEHICLE_BY_SHOP_VIN,
|
||||
@@ -329,5 +348,6 @@ module.exports = {
|
||||
DELETE_PARTS_ORDERS_BY_JOB_IDS,
|
||||
UPSERT_JOBLINES,
|
||||
GET_JOBLINE_IDS_BY_JOBID_UNQSEQ,
|
||||
UPDATE_JOBLINE_BY_PK
|
||||
UPDATE_JOBLINE_BY_PK,
|
||||
UPDATE_BODYSHOP_BY_ID
|
||||
};
|
||||
|
||||
40
server/job/patchJobStatus.js
Normal file
40
server/job/patchJobStatus.js
Normal file
@@ -0,0 +1,40 @@
|
||||
const client = require("../graphql-client/graphql-client").client;
|
||||
const { UPDATE_JOB_BY_ID } = require("../integrations/partsManagement/partsManagement.queries");
|
||||
|
||||
/**
|
||||
* PATCH handler to update job status (parts management only)
|
||||
* @param req
|
||||
* @param res
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
module.exports = async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const { status } = req.body;
|
||||
if (!status) {
|
||||
return res.status(400).json({ error: "Missing required field: status" });
|
||||
}
|
||||
try {
|
||||
// Fetch job to get shopid
|
||||
const jobResp = await client.request(`query GetJob($id: uuid!) { jobs_by_pk(id: $id) { id shopid } }`, { id });
|
||||
const job = jobResp.jobs_by_pk;
|
||||
if (!job) {
|
||||
return res.status(404).json({ error: "Job not found" });
|
||||
}
|
||||
// Fetch bodyshop to check external_shop_id
|
||||
const shopResp = await client.request(
|
||||
`query GetBodyshop($id: uuid!) { bodyshops_by_pk(id: $id) { id external_shop_id } }`,
|
||||
{ id: job.shopid }
|
||||
);
|
||||
if (!shopResp.bodyshops_by_pk || !shopResp.bodyshops_by_pk.external_shop_id) {
|
||||
return res.status(400).json({ error: "Cannot patch: parent bodyshop does not have an external_shop_id." });
|
||||
}
|
||||
// Update job status
|
||||
const updateResp = await client.request(UPDATE_JOB_BY_ID, { id, job: { status } });
|
||||
if (!updateResp.update_jobs_by_pk) {
|
||||
return res.status(404).json({ error: "Job not found after update" });
|
||||
}
|
||||
return res.json(updateResp.update_jobs_by_pk);
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: "Failed to update job status.", detail: err });
|
||||
}
|
||||
};
|
||||
@@ -19,11 +19,15 @@ if (typeof VSSTA_INTEGRATION_SECRET === "string" && VSSTA_INTEGRATION_SECRET.len
|
||||
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/endpoints/partsManagementProvisioning");
|
||||
const {
|
||||
partsManagementProvisioning,
|
||||
patchPartsManagementProvisioning
|
||||
} = require("../integrations/partsManagement/endpoints/partsManagementProvisioning");
|
||||
const partsManagementDeprovisioning = require("../integrations/partsManagement/endpoints/partsManagementDeprovisioning");
|
||||
const partsManagementIntegrationMiddleware = require("../middleware/partsManagementIntegrationMiddleware");
|
||||
const partsManagementVehicleDamageEstimateAddRq = require("../integrations/partsManagement/endpoints/vehicleDamageEstimateAddRq");
|
||||
const partsManagementVehicleDamageEstimateChqRq = require("../integrations/partsManagement/endpoints/vehicleDamageEstimateChgRq");
|
||||
const patchJobStatus = require("../job/patchJobStatus");
|
||||
|
||||
/**
|
||||
* Route to handle Vehicle Damage Estimate Add Request
|
||||
@@ -55,6 +59,20 @@ if (typeof PARTS_MANAGEMENT_INTEGRATION_SECRET === "string" && PARTS_MANAGEMENT_
|
||||
* Route to handle Parts Management Provisioning
|
||||
*/
|
||||
router.post("/parts-management/provision", partsManagementIntegrationMiddleware, partsManagementProvisioning);
|
||||
|
||||
/**
|
||||
* PATCH route to update Parts Management Provisioning info
|
||||
*/
|
||||
router.patch(
|
||||
"/parts-management/provision/:id",
|
||||
partsManagementIntegrationMiddleware,
|
||||
patchPartsManagementProvisioning
|
||||
);
|
||||
|
||||
/**
|
||||
* PATCH route to update job status (parts management only)
|
||||
*/
|
||||
router.patch("/parts-management/job/:id/status", partsManagementIntegrationMiddleware, patchJobStatus);
|
||||
} else {
|
||||
logger.logger.warn("PARTS_MANAGEMENT_INTEGRATION_SECRET is not set — skipping /parts-management/provision route");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user