From 312448f597960b437f9f82eba8d04bd8065dd17b Mon Sep 17 00:00:00 2001 From: jmcqueen Date: Wed, 1 Jul 2026 16:30:13 -0400 Subject: [PATCH] Fix #5: createSSRequest fails fast when storeNumber is missing - New SUBTYPES_REQUIRING_STORE_NUMBER set (seeded with every current subType, all of which mark Store Number required in JSM). Adding a future subType that does NOT require Store Number is a one-line omit. - createSSRequest now trims storeNumber (rejects whitespace-only) and throws a 400 with a clear message ("storeNumber is required for subType ...") before making any Jira API call. - Validation errors now carry err.status = 400 so future non-route callers can distinguish client errors from Jira failures. Co-authored-by: Cursor --- src/services/jiraService.js | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/services/jiraService.js b/src/services/jiraService.js index f70b1f5..da225c0 100644 --- a/src/services/jiraService.js +++ b/src/services/jiraService.js @@ -683,6 +683,12 @@ const REQUEST_TYPE_MAP = { 'Store Transportation Request': 493, }; +// SubTypes that require a storeNumber. Every currently-supported subType maps +// to a request type whose Store Number field is `required: true` in JSM (see +// ss-fields-*.json). Kept as an explicit set so a future subType that does NOT +// require Store Number can be added by simply omitting it from this set. +const SUBTYPES_REQUIRING_STORE_NUMBER = new Set(Object.keys(REQUEST_TYPE_MAP)); + /** * Create a Store Support ticket (JSM request) using the Service Desk API. * @param {Object} params @@ -1350,12 +1356,29 @@ export async function createSSRequest(params = {}) { } = params; if (!subType || !summary) { - throw new Error('subType and summary are required'); + const err = new Error('subType and summary are required'); + err.status = 400; + throw err; } const requestTypeId = REQUEST_TYPE_MAP[subType]; if (!requestTypeId) { - throw new Error(`Unknown subType: "${subType}". Must be one of the supported values.`); + const err = new Error(`Unknown subType: "${subType}". Must be one of the supported values.`); + err.status = 400; + throw err; + } + + // Fail-fast: every current subType requires Store Number. Catching this + // client-side gives a clean API error instead of forwarding to Jira and + // getting back an opaque "Please provide a value for required field + // 'Store Number'" that references Jira internals. + const normalizedStoreNumber = storeNumber != null && String(storeNumber).trim() !== '' + ? String(storeNumber).trim() + : null; + if (SUBTYPES_REQUIRING_STORE_NUMBER.has(subType) && !normalizedStoreNumber) { + const err = new Error(`storeNumber is required for subType "${subType}"`); + err.status = 400; + throw err; } const serviceDeskId = config.jira.serviceDeskId || '170'; @@ -1369,9 +1392,9 @@ export async function createSSRequest(params = {}) { ...additional }; - if (storeNumber) { + if (normalizedStoreNumber) { // Resolve to proper Assets object reference: [ { "objectId": "82288" } ] - const storeRef = await resolveStoreAssetReference(storeNumber); + const storeRef = await resolveStoreAssetReference(normalizedStoreNumber); if (storeRef) { requestFieldValues[storeCustomField] = storeRef; }