@final-commerce/command-frame 0.5.0-preprod.4 → 0.5.0-preprod.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,6 +3,6 @@
3
3
  * Calls the calculateRefundTotal action on the parent window
4
4
  */
5
5
  import { commandFrameClient } from "../../client";
6
- export const calculateRefundTotal = async () => {
7
- return await commandFrameClient.call("calculateRefundTotal");
6
+ export const calculateRefundTotal = async (params) => {
7
+ return await commandFrameClient.call("calculateRefundTotal", params);
8
8
  };
@@ -1,6 +1,6 @@
1
1
  import type { CFStatePair, CFTransitionResult } from "../../common-types/order-state";
2
2
  export interface CanTransitionParams {
3
- /** Order to evaluate. If omitted, evaluates against a new order (from = null). */
3
+ /** Order to evaluate. Defaults to the active order; if there is no active order (or none matches), evaluates as a brand-new order (from = null). */
4
4
  orderId?: string;
5
5
  /** Target state pair to transition to. */
6
6
  to: CFStatePair;
@@ -3,14 +3,17 @@ export interface CashPaymentParams {
3
3
  /**
4
4
  * The amount to pay with this tender, in integer MINOR currency units
5
5
  * (e.g. 1575 = $15.75 — see `getContext().minorUnits` for the currency's
6
- * exponent). Required. Semantics against the cart's balance due:
7
- * - missing → error
6
+ * exponent). Required whenever the balance due is greater than $0; may be
7
+ * omitted only on a cart that already nets to a $0 balance due (e.g. fully
8
+ * discounted), where it defaults to 0. Semantics against the cart's
9
+ * balance due:
10
+ * - missing → error, unless the balance due is $0 (→ 0)
8
11
  * - less than balance → partial payment (the POS enters a fixed
9
12
  * split-payment leg for this amount)
10
13
  * - equal to balance → full payment
11
14
  * - more than balance → error (overpayment is `tenderedAmount`'s job)
12
15
  */
13
- amount: number;
16
+ amount?: number;
14
17
  /**
15
18
  * Cash physically handed over by the customer, in integer MINOR currency
16
19
  * units. When provided, the POS computes the change itself (after applying
@@ -3,7 +3,7 @@ export interface GetRefundsParams {
3
3
  orderId?: string;
4
4
  sessionId?: string;
5
5
  outletId?: string;
6
- /** Default: 50. */
6
+ /** No default — when omitted, all matching refunds are returned. */
7
7
  limit?: number;
8
8
  /** Default: 0. */
9
9
  offset?: number;
@@ -3,6 +3,6 @@
3
3
  * Calls the getRemainingRefundableQuantities action on the parent window
4
4
  */
5
5
  import { commandFrameClient } from "../../client";
6
- export const getRemainingRefundableQuantities = async () => {
7
- return await commandFrameClient.call("getRemainingRefundableQuantities");
6
+ export const getRemainingRefundableQuantities = async (params) => {
7
+ return await commandFrameClient.call("getRemainingRefundableQuantities", params);
8
8
  };
@@ -1,12 +1,20 @@
1
1
  export const mockProcessPartialRefund = async (params) => {
2
2
  // The mock has no split-payment modal or order engine, so `openUI` (default
3
- // true on the real command), `legs` (the headless per-tender allocation) and
4
- // any per-leg `giftCard` destination (mixed returns) are inert here — the
5
- // shape is accepted and echoed, nothing else. No gift card is credited.
3
+ // true on the real command), `legs` (the headless per-tender allocation), a
4
+ // per-leg `giftCard` destination (mixed returns) and the top-level `giftCard`
5
+ // routing are all inert here — the shape is accepted and echoed, nothing
6
+ // else. No gift card is credited.
7
+ //
8
+ // The one rule worth mirroring is the mutual exclusion, so a flow built
9
+ // against the mock fails the same way it will against the runtime.
10
+ if (params?.legs && params?.giftCard) {
11
+ throw new Error('refund.giftCardAndLegs: pass either `legs` (you allocate) or `giftCard` (the engine allocates), not both');
12
+ }
6
13
  console.log("[Mock] processPartialRefund called", {
7
14
  ...params,
8
15
  openUI: params?.openUI ?? true,
9
16
  legs: params?.legs ?? null,
17
+ giftCard: params?.giftCard ?? null,
10
18
  });
11
19
  return {
12
20
  success: true,
@@ -2,10 +2,11 @@ export interface ProcessPartialRefundParams {
2
2
  /**
3
3
  * Optional refund reason.
4
4
  *
5
- * KNOWN LIMITATION: not currently persisted on the `Refund` doc or the
6
- * state-event audit row via this command the runtime falls back to a
7
- * fixed 'partial-refund' label instead. Unlike `redeemRefund`, whose
8
- * `reason` IS recorded. See the README's "Known limitation" section.
5
+ * Recorded verbatim on the persisted `Refund` doc's `reason` field and on
6
+ * the state-event audit row — same as `redeemRefund`. When omitted, the
7
+ * refund doc's `reason` stays unset and only the audit row carries the
8
+ * 'partial-refund' fallback label. See the README's "`reason` persistence"
9
+ * section.
9
10
  */
10
11
  reason?: string;
11
12
  /** Optional: specify which order to refund (sets it as active). */
@@ -87,6 +88,47 @@ export interface ProcessPartialRefundParams {
87
88
  label?: string;
88
89
  };
89
90
  }[];
91
+ /**
92
+ * Route part (or all) of the refund onto ONE gift-card / store-credit tender
93
+ * and let the engine send whatever is left back to the original payments.
94
+ *
95
+ * This is the declarative alternative to hand-building `legs`: state the card
96
+ * and how much lands on it, and the engine does the allocation — it already
97
+ * owns that math for every other refund path. Prefer it over `legs` for a
98
+ * gift-card destination; a flow that computes its own split is duplicating
99
+ * engine arithmetic that will drift (see "Query, never recompute").
100
+ *
101
+ * - `amount` omitted → the WHOLE refund lands on the card (what an
102
+ * all-`giftCard` `legs` staging does today).
103
+ * - `amount` set → that much lands on the card, in minor units; the
104
+ * remainder returns to the original payments, allocated by the engine.
105
+ *
106
+ * DRAWING ORDER — the card is filled from the tenders that cannot be
107
+ * refunded to source first (a redeem tender has nowhere to return to), then
108
+ * proportionally from the rest. So `amount` can never be lower than what
109
+ * those tenders must contribute: below that the call throws
110
+ * `REFUND_GIFT_AMOUNT_BELOW_MINIMUM`, naming the minimum, and nothing is
111
+ * committed. Surface that message — it is the number to clamp the field to,
112
+ * so the flow never has to derive it.
113
+ *
114
+ * Exactly one destination card, therefore exactly ONE credit for the caller
115
+ * to place and one to reverse. **Credit-first:** credit `referenceId` for
116
+ * `amount` (or the full refund total when omitted) BEFORE calling; on any
117
+ * throw nothing was recorded — reverse it.
118
+ *
119
+ * Requires `openUI: false`. Mutually exclusive with `legs` — passing both
120
+ * throws, since they are two answers to the same question.
121
+ */
122
+ giftCard?: {
123
+ /** Card/account id the flow already credited (stored raw). */
124
+ referenceId: string;
125
+ /** Minor units landing on the card. Omit for the whole refund. */
126
+ amount?: number;
127
+ /** Provider/program name. Defaults to `giftCard`. */
128
+ processor?: string;
129
+ /** Human label for the destination tender. */
130
+ label?: string;
131
+ };
90
132
  /** Optional items to refund. */
91
133
  items?: {
92
134
  /** internalId or variantId or customSaleId. */
@@ -3,6 +3,6 @@
3
3
  * Calls the selectAllRefundItems action on the parent window
4
4
  */
5
5
  import { commandFrameClient } from "../../client";
6
- export const selectAllRefundItems = async () => {
7
- return await commandFrameClient.call("selectAllRefundItems");
6
+ export const selectAllRefundItems = async (params) => {
7
+ return await commandFrameClient.call("selectAllRefundItems", params);
8
8
  };
@@ -7,4 +7,4 @@ export interface SetActiveRefundResponse {
7
7
  refund: CFActiveRefundDetails;
8
8
  timestamp: string;
9
9
  }
10
- export type SetActiveRefund = (params?: SetActiveRefundParams) => Promise<SetActiveRefundResponse>;
10
+ export type SetActiveRefund = (params: SetActiveRefundParams) => Promise<SetActiveRefundResponse>;
@@ -1,6 +1,6 @@
1
1
  export interface SetRefundStockActionParams {
2
2
  orderId?: string;
3
- /** The 'key' field from getLineItemsByOrder response (internalId || variantId || productId). */
3
+ /** The 'key' field from getLineItemsByOrder response (internalId, falling back to variantId). */
4
4
  itemKey: string;
5
5
  action: 'RESTOCK' | 'REFUND_DAMAGE';
6
6
  }
@@ -2,14 +2,17 @@ import { CFOrder } from "../../CommonTypes";
2
2
  export interface TapToPayPaymentParams {
3
3
  /**
4
4
  * The amount to pay with this tender, in integer MINOR currency units
5
- * (e.g. 1575 = $15.75). Required. Semantics against the cart's balance due:
6
- * - missing → error
5
+ * (e.g. 1575 = $15.75). Required whenever the balance due is greater than
6
+ * $0; may be omitted only on a cart that already nets to a $0 balance due
7
+ * (e.g. fully discounted), where it defaults to 0. Semantics against the
8
+ * cart's balance due:
9
+ * - missing → error, unless the balance due is $0 (→ 0)
7
10
  * - less than balance → partial payment (the POS enters a fixed
8
11
  * split-payment leg for this amount)
9
12
  * - equal to balance → full payment
10
13
  * - more than balance → error
11
14
  */
12
- amount: number;
15
+ amount?: number;
13
16
  /** Override the fulfillment state after full payment. kaching resolves the cascade. */
14
17
  checkoutFulfillmentTarget?: string;
15
18
  }
@@ -3,9 +3,10 @@ export interface VoidOrderParams {
3
3
  /** Order to void; defaults to the active order. */
4
4
  orderId?: string;
5
5
  /**
6
- * Optional cashier-facing reason. On a pure void, recorded on the void audit
7
- * row and carried on the `order-voided` event. On the refund branch it rides
8
- * the event only the refund dispatcher does not consume it.
6
+ * Optional cashier-facing reason. Recorded on both branches the void audit
7
+ * trail on a pure void, and (verbatim) on the persisted refund plus its own
8
+ * audit trail on the refund branch and always carried on the
9
+ * `order-voided` event either way.
9
10
  */
10
11
  reason?: string;
11
12
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@final-commerce/command-frame",
3
- "version": "0.5.0-preprod.4",
3
+ "version": "0.5.0-preprod.6",
4
4
  "description": "Commands Frame library",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",