From b24b14061d24d9167a2c967a94747e5b2d8dc7a1 Mon Sep 17 00:00:00 2001 From: Max Edell Date: Wed, 27 May 2026 10:45:50 -0700 Subject: [PATCH] fix: order status cancelled --- src/actions/submit/index.js | 15 ++++++- test/submit.test.js | 79 +++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/src/actions/submit/index.js b/src/actions/submit/index.js index d9c1413..02796cf 100644 --- a/src/actions/submit/index.js +++ b/src/actions/submit/index.js @@ -218,8 +218,21 @@ async function handleOrderStatus(ctx, formId, data) { return errorResponse(status, message, { error: message }); } - // remove PII from data const body = transformSoapKeys(response); + + // Detect cancellation from line item statuses. Cancelled orders may have no + // delivery items; each cancelled line item shows Status="Closed". + const lineItems = [].concat(body.order?.lineItem ?? []); + if (lineItems.length > 0) { + const closedCount = lineItems.filter(item => item?.status === 'Closed').length; + if (closedCount === lineItems.length) { + body.outcome = 'Cancelled'; + } else if (closedCount > 0) { + body.outcome = 'Partially Cancelled'; + } + } + + // remove PII from data delete body.order?.customer; delete body.order?.lineItem; delete body.order?.systemOfRecordKey; diff --git a/test/submit.test.js b/test/submit.test.js index 434d62a..ff35d6f 100644 --- a/test/submit.test.js +++ b/test/submit.test.js @@ -366,6 +366,85 @@ describe('submit action', () => { expect(typeof result.body.succeeded).toBe('boolean'); expect(result.body.succeeded).toBe(true); }); + + test('reports outcome=Cancelled when all line items are Closed', async () => { + // Sample EBS response for a fully cancelled single-item order. + // Cancelled orders may have no Delivery elements; each cancelled + // LineItem carries Status="Closed". + const cancelledBody = { + Response: { + '@_Id': '123456654321', + '@_Outcome': 'Success', + '@_Succeeded': 'true', + 'Order': { + '@_Shipping': 'Standard', + '@_Source': 'US', + '@_Currency': 'USD', + '@_Type': 'Household', + '@_Key': 'om2101502620', + '@_SystemOfRecordKey': '14207540', + '@_Created': '2026-04-07T16:49:26', + 'Customer': { + '@_Key': '12285360', + '@_SystemOfRecordKey': '7929814', + 'First': 'KATHLEEN', + 'Last': 'RUMME', + 'Middle': '', + }, + 'LineItem': { + '@_Sku': '001811', + '@_Quantity': '0', + '@_UnitSellingPrice': '349.95', + '@_UnitOfMeasure': 'Each', + '@_Status': 'Closed', + '@_Key': '19329252', + }, + }, + }, + }; + + mockMakeContext.mockResolvedValue(makeOrderCtx('om2101502620')); + mockQueryOrder.mockResolvedValue({ status: 200, body: cancelledBody }); + + const result = await main({}); + expect(result.statusCode).toBe(200); + expect(result.body.outcome).toBe('Cancelled'); + expect(result.body.order.key).toBe('om2101502620'); + expect(result.body.order).not.toHaveProperty('delivery'); + expect(result.body.order).not.toHaveProperty('lineItem'); + }); + + test('reports outcome=Partially Cancelled when some line items are Closed', async () => { + const partialBody = { + Response: { + '@_Id': 'abc', + '@_Outcome': 'Success', + '@_Succeeded': 'true', + 'Order': { + '@_Key': 'om-partial', + 'LineItem': [ + { '@_Key': '1', '@_Status': 'Closed' }, + { '@_Key': '2', '@_Status': 'Shipped' }, + ], + }, + }, + }; + + mockMakeContext.mockResolvedValue(makeOrderCtx('om-partial')); + mockQueryOrder.mockResolvedValue({ status: 200, body: partialBody }); + + const result = await main({}); + expect(result.statusCode).toBe(200); + expect(result.body.outcome).toBe('Partially Cancelled'); + }); + + test('preserves original outcome when no line items are Closed', async () => { + mockMakeContext.mockResolvedValue(makeOrderCtx()); + mockQueryOrder.mockResolvedValue({ status: 200, body: successBody }); + + const result = await main({}); + expect(result.body.outcome).toBe('Success'); + }); }); // -- product-registration ------------------------------------------------