From 88f4ee75d73fd7229da4a31d0b8755c5fa00c36f Mon Sep 17 00:00:00 2001 From: Michael Czechowski Date: Thu, 8 Oct 2026 22:54:59 +0200 Subject: [PATCH] feat(order): lock an order for the customer once its payment is authorised Refs https://git.librete.ch/libretech/mp/issues/71 --- src/checkout/order-state.ts | 10 ++++++++++ tests/unit/order-state.test.ts | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/checkout/order-state.ts create mode 100644 tests/unit/order-state.test.ts diff --git a/src/checkout/order-state.ts b/src/checkout/order-state.ts new file mode 100644 index 0000000..7c66128 --- /dev/null +++ b/src/checkout/order-state.ts @@ -0,0 +1,10 @@ +/** The fields of an order that decide whether the customer may still change it. */ +export type OrderLockState = { + paymentAuthorised?: boolean | null; +}; + +/** + * Once its payment is authorised, the order is what the customer paid for and what the invoice is generated from, + * so the customer can no longer change its contact details, addresses, delivery method or cart. + */ +export const isLockedForCustomer = (order: OrderLockState): boolean => Boolean(order.paymentAuthorised); diff --git a/tests/unit/order-state.test.ts b/tests/unit/order-state.test.ts new file mode 100644 index 0000000..3274d24 --- /dev/null +++ b/tests/unit/order-state.test.ts @@ -0,0 +1,26 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { isLockedForCustomer } from "../../src/checkout/order-state.ts"; + +// Shaped like the row PUT /orders/:uuid/cart reads with strapi.db.query("api::order.order").findOne before it updates. +const order = (overrides = {}) => ({ + id: 4711, + uuid: "11111111-2222-4333-8444-555555555555", + email: "erika@example.org", + paymentAuthorised: false, + paymentStatus: null, + invoiceSent: false, + ...overrides +}); + +test("an order is open for the customer until its payment is authorised", () => { + assert.equal(isLockedForCustomer(order()), false); + // false is the schema's default, but a row can hold null + assert.equal(isLockedForCustomer(order({ paymentAuthorised: null })), false); + assert.equal(isLockedForCustomer({}), false); +}); + +test("an order is locked once its payment is authorised", () => { + // what capturePayment writes once PayPal reports the capture COMPLETED + assert.equal(isLockedForCustomer(order({ paymentAuthorised: true, paymentStatus: "authorised" })), true); +});