@final-commerce/command-frame 0.1.73 → 0.1.75
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.
- package/README.md +50 -28
- package/dist/CommonTypes.d.ts +124 -7
- package/dist/CommonTypes.js +112 -0
- package/dist/actions/add-cart-discount/mock.js +6 -3
- package/dist/actions/add-cart-fee/mock.js +6 -6
- package/dist/actions/add-custom-sale/mock.js +7 -2
- package/dist/actions/add-order-note/mock.js +3 -1
- package/dist/actions/add-product-discount/mock.js +10 -3
- package/dist/actions/add-product-fee/mock.js +10 -1
- package/dist/actions/apply-transition/action.d.ts +2 -0
- package/dist/actions/apply-transition/action.js +4 -0
- package/dist/actions/apply-transition/mock.d.ts +6 -0
- package/dist/actions/apply-transition/mock.js +33 -0
- package/dist/actions/apply-transition/types.d.ts +17 -0
- package/dist/actions/apply-transition/types.js +1 -0
- package/dist/actions/can-transition/action.d.ts +2 -0
- package/dist/actions/can-transition/action.js +4 -0
- package/dist/actions/can-transition/mock.d.ts +6 -0
- package/dist/actions/can-transition/mock.js +28 -0
- package/dist/actions/can-transition/types.d.ts +11 -0
- package/dist/actions/can-transition/types.js +1 -0
- package/dist/actions/cash-payment/mock.js +12 -18
- package/dist/actions/cash-payment/types.d.ts +5 -0
- package/dist/actions/delete-parked-order/mock.js +3 -1
- package/dist/actions/delete-parked-order/types.d.ts +3 -0
- package/dist/actions/extension-payment/types.d.ts +5 -0
- package/dist/actions/get-available-transitions/action.d.ts +2 -0
- package/dist/actions/get-available-transitions/action.js +4 -0
- package/dist/actions/get-available-transitions/mock.d.ts +6 -0
- package/dist/actions/get-available-transitions/mock.js +26 -0
- package/dist/actions/get-available-transitions/types.d.ts +9 -0
- package/dist/actions/get-available-transitions/types.js +1 -0
- package/dist/actions/get-context/mock.js +1 -1
- package/dist/actions/get-orders/mock.js +3 -3
- package/dist/actions/initiate-refund/types.d.ts +3 -0
- package/dist/actions/open-extension-overlay/mock.d.ts +2 -0
- package/dist/actions/open-extension-overlay/mock.js +1 -0
- package/dist/actions/open-extension-overlay/types.d.ts +9 -0
- package/dist/actions/open-extension-overlay/types.js +1 -0
- package/dist/actions/park-order/mock.js +4 -1
- package/dist/actions/park-order/types.d.ts +3 -0
- package/dist/actions/partial-payment/mock.js +21 -3
- package/dist/actions/partial-payment/types.d.ts +5 -0
- package/dist/actions/process-partial-refund/types.d.ts +3 -0
- package/dist/actions/remove-custom-sale/mock.d.ts +2 -0
- package/dist/actions/remove-custom-sale/mock.js +29 -0
- package/dist/actions/remove-customer-from-cart/mock.js +3 -1
- package/dist/actions/remove-order-note/mock.d.ts +2 -0
- package/dist/actions/remove-order-note/mock.js +12 -0
- package/dist/actions/remove-product-discount/mock.d.ts +2 -0
- package/dist/actions/remove-product-discount/mock.js +17 -0
- package/dist/actions/remove-product-fee/mock.d.ts +2 -0
- package/dist/actions/remove-product-fee/mock.js +17 -0
- package/dist/actions/remove-product-from-cart/mock.js +5 -5
- package/dist/actions/resolve-extension-overlay/mock.d.ts +2 -0
- package/dist/actions/resolve-extension-overlay/mock.js +1 -0
- package/dist/actions/resolve-extension-overlay/types.d.ts +9 -0
- package/dist/actions/resolve-extension-overlay/types.js +1 -0
- package/dist/actions/resume-parked-order/mock.js +4 -1
- package/dist/actions/resume-parked-order/types.d.ts +3 -0
- package/dist/actions/tap-to-pay-payment/mock.js +5 -3
- package/dist/actions/tap-to-pay-payment/types.d.ts +5 -0
- package/dist/actions/terminal-payment/mock.js +4 -5
- package/dist/actions/terminal-payment/types.d.ts +5 -0
- package/dist/actions/update-cart-item-quantity/mock.js +9 -9
- package/dist/actions/vendara-payment/types.d.ts +5 -0
- package/dist/common-types/index.d.ts +1 -0
- package/dist/common-types/index.js +1 -0
- package/dist/common-types/order-state.d.ts +32 -0
- package/dist/common-types/order-state.js +6 -0
- package/dist/common-types/state-fragment.d.ts +77 -0
- package/dist/common-types/state-fragment.js +10 -0
- package/dist/demo/database.d.ts +10 -0
- package/dist/demo/database.js +169 -3
- package/dist/fragments/index.d.ts +1 -0
- package/dist/fragments/index.js +1 -0
- package/dist/fragments/preorder-no-deposit.d.ts +26 -0
- package/dist/fragments/preorder-no-deposit.js +166 -0
- package/dist/index.d.ts +14 -4
- package/dist/index.js +13 -3
- package/dist/interceptors/index.d.ts +21 -0
- package/dist/interceptors/index.js +53 -0
- package/dist/interceptors/types.d.ts +26 -0
- package/dist/interceptors/types.js +1 -0
- package/dist/projects/render/mocks.js +16 -4
- package/dist/projects/render/types.d.ts +7 -1
- package/dist/pubsub/topics/orders/index.js +10 -0
- package/dist/pubsub/topics/orders/state-transition-blocked/types.d.ts +16 -0
- package/dist/pubsub/topics/orders/state-transition-blocked/types.js +1 -0
- package/dist/pubsub/topics/orders/state-transition-completed/types.d.ts +15 -0
- package/dist/pubsub/topics/orders/state-transition-completed/types.js +1 -0
- package/dist/pubsub/topics/orders/types.d.ts +6 -2
- package/dist/pubsub/topics/orders/types.js +2 -0
- package/package.json +1 -1
- package/dist/actions/extension-refund/constants.d.ts +0 -2
- package/dist/actions/extension-refund/constants.js +0 -2
- package/dist/actions/extension-refund/extension-refund-listener.d.ts +0 -11
- package/dist/actions/extension-refund/extension-refund-listener.js +0 -60
- package/dist/actions/extension-refund/types.d.ts +0 -32
- package/dist/actions/extension-refund/types.js +0 -5
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { CFOrder } from "../../CommonTypes";
|
|
2
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
2
3
|
export interface TapToPayPaymentParams {
|
|
3
4
|
/** If not provided, uses the cart total. */
|
|
4
5
|
amount?: number;
|
|
6
|
+
/** Override the fulfillment state after full payment. Render resolves the cascade. */
|
|
7
|
+
checkoutFulfillmentTarget?: string;
|
|
5
8
|
}
|
|
6
9
|
export interface TapToPayPaymentResponse {
|
|
7
10
|
success: boolean;
|
|
@@ -9,5 +12,7 @@ export interface TapToPayPaymentResponse {
|
|
|
9
12
|
paymentType: string;
|
|
10
13
|
order: CFOrder | null;
|
|
11
14
|
timestamp: string;
|
|
15
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
16
|
+
transitionResult?: CFTransitionResult;
|
|
12
17
|
}
|
|
13
18
|
export type TapToPayPayment = (params?: TapToPayPaymentParams) => Promise<TapToPayPaymentResponse>;
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { applyMockPayment, MOCK_CART } from "../../demo/database";
|
|
2
2
|
export const mockTerminalPayment = async (params) => {
|
|
3
3
|
console.log("[Mock] terminalPayment called", params);
|
|
4
4
|
const connectionType = params?.paymentType || "Cloud";
|
|
5
5
|
// Simulate terminal interaction
|
|
6
6
|
window.alert(`Demo: Processing ${connectionType} Terminal Payment...\n(Please tap, insert, or swipe card on terminal)`);
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
const order = createOrderFromCart("card", amount, "stripe_terminal");
|
|
7
|
+
const due = params?.amount ?? MOCK_CART.amountToBeCharged ?? MOCK_CART.total;
|
|
8
|
+
const order = applyMockPayment(due, "card", "stripe_terminal");
|
|
10
9
|
return {
|
|
11
10
|
success: true,
|
|
12
|
-
amount:
|
|
11
|
+
amount: due,
|
|
13
12
|
paymentType: "terminal",
|
|
14
13
|
order,
|
|
15
14
|
timestamp: new Date().toISOString()
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { CFOrder } from "../../CommonTypes";
|
|
2
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
2
3
|
export interface TerminalPaymentParams {
|
|
3
4
|
/** If not provided, uses the cart total. */
|
|
4
5
|
amount?: number;
|
|
5
6
|
/** "Bluetooth" or "Cloud". Defaults to "Cloud". */
|
|
6
7
|
paymentType?: 'Bluetooth' | 'Cloud';
|
|
8
|
+
/** Override the fulfillment state after full payment. Render resolves the cascade. */
|
|
9
|
+
checkoutFulfillmentTarget?: string;
|
|
7
10
|
}
|
|
8
11
|
export interface TerminalPaymentResponse {
|
|
9
12
|
success: boolean;
|
|
@@ -11,5 +14,7 @@ export interface TerminalPaymentResponse {
|
|
|
11
14
|
paymentType: string;
|
|
12
15
|
order: CFOrder | null;
|
|
13
16
|
timestamp: string;
|
|
17
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
18
|
+
transitionResult?: CFTransitionResult;
|
|
14
19
|
}
|
|
15
20
|
export type TerminalPayment = (params?: TerminalPaymentParams) => Promise<TerminalPaymentResponse>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { MOCK_CART, mockPublishEvent } from "../../demo/database";
|
|
2
|
-
export const mockUpdateCartItemQuantity =
|
|
2
|
+
export const mockUpdateCartItemQuantity = (params) => {
|
|
3
3
|
console.log("[Mock] updateCartItemQuantity called", params);
|
|
4
4
|
if (!params?.internalId) {
|
|
5
|
-
throw new Error(
|
|
5
|
+
throw new Error("internalId is required");
|
|
6
6
|
}
|
|
7
7
|
if (params.quantity === undefined || params.quantity === null) {
|
|
8
|
-
throw new Error(
|
|
8
|
+
throw new Error("quantity is required");
|
|
9
9
|
}
|
|
10
10
|
const { internalId, quantity } = params;
|
|
11
11
|
// Find the product in the cart
|
|
@@ -25,16 +25,16 @@ export const mockUpdateCartItemQuantity = async (params) => {
|
|
|
25
25
|
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
26
26
|
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
27
27
|
// Publish product-deleted event
|
|
28
|
-
mockPublishEvent(
|
|
28
|
+
mockPublishEvent("cart", "product-deleted", {
|
|
29
29
|
product: product,
|
|
30
30
|
internalId: internalId
|
|
31
31
|
});
|
|
32
|
-
return {
|
|
32
|
+
return Promise.resolve({
|
|
33
33
|
success: true,
|
|
34
34
|
internalId: internalId,
|
|
35
35
|
quantity: 0,
|
|
36
36
|
timestamp: new Date().toISOString()
|
|
37
|
-
};
|
|
37
|
+
});
|
|
38
38
|
}
|
|
39
39
|
// Update quantity
|
|
40
40
|
const quantityDelta = quantity - previousQuantity;
|
|
@@ -46,15 +46,15 @@ export const mockUpdateCartItemQuantity = async (params) => {
|
|
|
46
46
|
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
47
47
|
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
48
48
|
// Publish product-updated event
|
|
49
|
-
mockPublishEvent(
|
|
49
|
+
mockPublishEvent("cart", "product-updated", {
|
|
50
50
|
product: product,
|
|
51
51
|
previousQuantity: previousQuantity,
|
|
52
52
|
newQuantity: quantity
|
|
53
53
|
});
|
|
54
|
-
return {
|
|
54
|
+
return Promise.resolve({
|
|
55
55
|
success: true,
|
|
56
56
|
internalId: internalId,
|
|
57
57
|
quantity: quantity,
|
|
58
58
|
timestamp: new Date().toISOString()
|
|
59
|
-
};
|
|
59
|
+
});
|
|
60
60
|
};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { CFOrder } from "../../CommonTypes";
|
|
2
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
2
3
|
export interface VendaraPaymentParams {
|
|
3
4
|
/** If not provided, uses the cart total. */
|
|
4
5
|
amount?: number;
|
|
6
|
+
/** Override the fulfillment state after full payment. Render resolves the cascade. */
|
|
7
|
+
checkoutFulfillmentTarget?: string;
|
|
5
8
|
}
|
|
6
9
|
export interface VendaraPaymentResponse {
|
|
7
10
|
success: boolean;
|
|
@@ -9,5 +12,7 @@ export interface VendaraPaymentResponse {
|
|
|
9
12
|
paymentType: string;
|
|
10
13
|
order: CFOrder | null;
|
|
11
14
|
timestamp: string;
|
|
15
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
16
|
+
transitionResult?: CFTransitionResult;
|
|
12
17
|
}
|
|
13
18
|
export type VendaraPayment = (params?: VendaraPaymentParams) => Promise<VendaraPaymentResponse>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State machine protocol types for the command-frame boundary.
|
|
3
|
+
* These mirror @final-commerce/common shapes but carry no logic.
|
|
4
|
+
* command-frame must NOT depend on common.
|
|
5
|
+
*/
|
|
6
|
+
export interface CFStatePair {
|
|
7
|
+
payment: string;
|
|
8
|
+
fulfillment: string;
|
|
9
|
+
}
|
|
10
|
+
export type CFBlockedBy = "financial_invariant" | "cross_axis_rule" | "path" | "condition";
|
|
11
|
+
export interface CFTransitionResult {
|
|
12
|
+
allowed: boolean;
|
|
13
|
+
blockedBy?: CFBlockedBy;
|
|
14
|
+
guard?: string;
|
|
15
|
+
reason?: string;
|
|
16
|
+
failedConditions?: CFFailedCondition[];
|
|
17
|
+
}
|
|
18
|
+
export interface CFFailedCondition {
|
|
19
|
+
field: string;
|
|
20
|
+
operator: string;
|
|
21
|
+
value: unknown;
|
|
22
|
+
reason?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface CFConditionStatus {
|
|
25
|
+
met: boolean;
|
|
26
|
+
description: string;
|
|
27
|
+
}
|
|
28
|
+
export interface CFAvailableTransition {
|
|
29
|
+
to: CFStatePair;
|
|
30
|
+
displayLabel: string;
|
|
31
|
+
conditions: CFConditionStatus[];
|
|
32
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State config fragment types for the command-frame boundary.
|
|
3
|
+
* These mirror @final-commerce/common's StateConfigFragment shapes but carry no logic.
|
|
4
|
+
* command-frame must NOT depend on common.
|
|
5
|
+
*
|
|
6
|
+
* Extensions pass a CFStateConfigFragment to Render, which merges it into the
|
|
7
|
+
* running StoredStateConfig via mergeFragment(). All contributed entries are tagged
|
|
8
|
+
* with the extension's id (_sourceExtensionId) so they can be cleaned up on unregister.
|
|
9
|
+
*/
|
|
10
|
+
import type { CFStatePair } from "./order-state";
|
|
11
|
+
export type CFConditionOperator = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "isEmpty" | "isNotEmpty";
|
|
12
|
+
export interface CFCondition {
|
|
13
|
+
/** Dot-path into the OrderContext, e.g. "order.balance" or "computed.totalPaid". */
|
|
14
|
+
field: string;
|
|
15
|
+
operator: CFConditionOperator;
|
|
16
|
+
value: unknown;
|
|
17
|
+
}
|
|
18
|
+
/** All conditions in a group are AND'd together. */
|
|
19
|
+
export interface CFConditionGroup {
|
|
20
|
+
conditions: CFCondition[];
|
|
21
|
+
}
|
|
22
|
+
/** Groups are OR'd — the first passing group satisfies the set. */
|
|
23
|
+
export interface CFTransitionConditionSet {
|
|
24
|
+
id: string;
|
|
25
|
+
label: string;
|
|
26
|
+
groups: CFConditionGroup[];
|
|
27
|
+
}
|
|
28
|
+
export interface CFPaymentTransitionPath {
|
|
29
|
+
from: string;
|
|
30
|
+
to: string;
|
|
31
|
+
/** References a CFTransitionConditionSet.id in the same fragment. */
|
|
32
|
+
conditionSetId?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface CFFulfillmentTransitionPath {
|
|
35
|
+
from: string;
|
|
36
|
+
to: string;
|
|
37
|
+
conditionSetId?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface CFCrossAxisRule {
|
|
40
|
+
id: string;
|
|
41
|
+
label: string;
|
|
42
|
+
description?: string;
|
|
43
|
+
enabled: boolean;
|
|
44
|
+
/** Which axis + target state(s) activate this rule. */
|
|
45
|
+
trigger: {
|
|
46
|
+
axis: "payment" | "fulfillment";
|
|
47
|
+
to: string[];
|
|
48
|
+
};
|
|
49
|
+
/** Which axis + states must be present when the trigger fires. */
|
|
50
|
+
requires: {
|
|
51
|
+
axis: "payment" | "fulfillment";
|
|
52
|
+
states: string[];
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export interface CFDisplayStateRule {
|
|
56
|
+
paymentState?: string[];
|
|
57
|
+
fulfillmentState?: string[];
|
|
58
|
+
label: string;
|
|
59
|
+
color?: string;
|
|
60
|
+
icon?: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Partial config contributed by an extension. Render merges this into the
|
|
64
|
+
* running StoredStateConfig. All arrays are appended; display rules replace
|
|
65
|
+
* on key collision.
|
|
66
|
+
*
|
|
67
|
+
* IDs (crossAxisRules, transitionConditions) must be unique across the merged
|
|
68
|
+
* config — prefix them with your extension id to avoid collisions.
|
|
69
|
+
*/
|
|
70
|
+
export interface CFStateConfigFragment {
|
|
71
|
+
paymentPaths?: CFPaymentTransitionPath[];
|
|
72
|
+
fulfillmentPaths?: CFFulfillmentTransitionPath[];
|
|
73
|
+
crossAxisRules?: CFCrossAxisRule[];
|
|
74
|
+
transitionConditions?: CFTransitionConditionSet[];
|
|
75
|
+
validInitialStates?: CFStatePair[];
|
|
76
|
+
displayStateMap?: CFDisplayStateRule[];
|
|
77
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State config fragment types for the command-frame boundary.
|
|
3
|
+
* These mirror @final-commerce/common's StateConfigFragment shapes but carry no logic.
|
|
4
|
+
* command-frame must NOT depend on common.
|
|
5
|
+
*
|
|
6
|
+
* Extensions pass a CFStateConfigFragment to Render, which merges it into the
|
|
7
|
+
* running StoredStateConfig via mergeFragment(). All contributed entries are tagged
|
|
8
|
+
* with the extension's id (_sourceExtensionId) so they can be cleaned up on unregister.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
package/dist/demo/database.d.ts
CHANGED
|
@@ -50,6 +50,9 @@ export declare const MOCK_PRODUCT_HABANERO: CFProduct;
|
|
|
50
50
|
export declare const MOCK_PRODUCT_BLACK_GARLIC: CFProduct;
|
|
51
51
|
export declare const MOCK_ORDER_1: CFActiveOrder;
|
|
52
52
|
export declare const MOCK_ORDER_2: CFActiveOrder;
|
|
53
|
+
export declare const MOCK_ORDER_3: CFActiveOrder;
|
|
54
|
+
export declare const MOCK_PARKED_ORDER_1: CFActiveOrder;
|
|
55
|
+
export declare const MOCK_PARKED_ORDER_2: CFActiveOrder;
|
|
53
56
|
export declare const MOCK_USERS: CFActiveUser[];
|
|
54
57
|
export declare const MOCK_STATIONS: CFActiveStation[];
|
|
55
58
|
export declare const MOCK_OUTLETS: CFActiveOutlet[];
|
|
@@ -76,3 +79,10 @@ type MockEventCallback = (event: any) => void;
|
|
|
76
79
|
export declare const mockPublishEvent: (topic: string, eventType: string, data: any) => void;
|
|
77
80
|
export declare const mockSubscribeToTopic: (topic: string, callback: MockEventCallback) => void;
|
|
78
81
|
export declare const createOrderFromCart: (paymentType: string, amount: number, processor?: string) => CFActiveOrder;
|
|
82
|
+
/**
|
|
83
|
+
* Apply a (possibly partial) payment of `amount` minor units to the active cart.
|
|
84
|
+
* Decrements the remaining balance; when it reaches zero the sale completes
|
|
85
|
+
* (creates the order, resets the cart, returns it). Otherwise the cart stays
|
|
86
|
+
* open with `amountToBeCharged` reset to what's left, and returns null.
|
|
87
|
+
*/
|
|
88
|
+
export declare const applyMockPayment: (amount: number, paymentType: string, processor?: string) => CFActiveOrder | null;
|
package/dist/demo/database.js
CHANGED
|
@@ -6,7 +6,7 @@ import { CFProductType, CFUserTypes, CurrencyCode } from "../CommonTypes";
|
|
|
6
6
|
export * from "./mocks";
|
|
7
7
|
// Asset Imports - Using Remote URLs to avoid build complexity with asset copying
|
|
8
8
|
const ASSETS_BASE_URL = "https://raw.githubusercontent.com/Final-Commerce/command-frame/refs/heads/main/src/demo/assets";
|
|
9
|
-
const logo =
|
|
9
|
+
const logo = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA5OCAxMDQiIGZpbGw9Im5vbmUiPjxwYXRoIGQ9Ik01NS4yOTk4IDUwLjE2NjJMMzcuNzQyMiA0MC4wMjkzTDMxLjcyNzQgNTAuNDQ3MkwzOC45MjQyIDU0LjYwMjJMNTUuMjk5OCA1MC4xNjYyWiIgZmlsbD0iI0E1NjhCQyIvPjxwYXRoIGQ9Ik0zMS45OTYzIDcwLjQ1MDZMNDkuNTU2OCA4MC41ODkxTDU1LjU3MTUgNzAuMTcxM0w0OC4zNzE4IDY2LjAxNDVMMzEuOTk2MyA3MC40NTA2WiIgZmlsbD0iI0E1NjhCQyIvPjxwYXRoIGQ9Ik0zNi4zNTQyIDM0LjI1NzJDMzYuMzU0MiAzNC4yNTcyIDM2LjM1ODMgMzQuMjYzNSAzNi4zNTY3IDM0LjI2NjRDMzcuMTg2OSAzNC4wNjk3IDM4LjA5MTkgMzQuMTU5NiAzOC44ODUxIDM0LjYxNzVMNjIuNjQ4NiA0OC4zMzc0TDU0LjE3MjkgMjkuOTA0OUwzNi4zNDk2IDM0LjI1ODRMMzYuMzU0MiAzNC4yNTcyWiIgZmlsbD0iI0ZDODc1MyIvPjxwYXRoIGQ9Ik0zMy4wOTg4IDE4Ljk1MDdMMzYuMzc3MiAzNC4yNDczTDE4Ljc1MjUgMzkuMzM3M0wyOC45MzcxIDIxLjY5N0MyOS44NDUzIDIwLjEyMzkgMzEuNDE1MiAxOS4xNzYxIDMzLjA5ODggMTguOTUwN1oiIGZpbGw9IiM0MkQzQTkiLz48cGF0aCBkPSJNMTguNzUzMiAzOS4zNDA2TDIwLjY4MjQgNTkuNTE3MUw0LjU3NjA3IDYzLjg5NjJMMTguNzUzMiAzOS4zNDA2WiIgZmlsbD0iIzI3OTdFOCIvPjxwYXRoIGQ9Ik0zNi4zNzc5IDM0LjI0MDNDMzYuMzc3OSAzNC4yNDAzIDM2LjM3NzQgMzQuMjQ3OCAzNi4zODAzIDM0LjI0OTVDMzUuNTYyNCAzNC40OTE5IDM0LjgyMzkgMzUuMDE5NiAzNC4zNjczIDM1LjgxMDVMMjAuNjg2OSA1OS41MDU2TDE4Ljc1NzcgMzkuMzI5MUwzNi4zODI0IDM0LjIzOTFMMzYuMzc3OSAzNC4yNDAzWiIgZmlsbD0iIzFEQkFDQiIvPjxwYXRoIGQ9Ik01NS45MzUyIDEwMS41NDNMNTEuMDgxOSA4Ni42NjU5TDMzLjI1ODcgOTEuMDE5NEw1MC45NDk5IDEwMS4yMzNDNTIuNTI3NiAxMDIuMTQ0IDU0LjM2MzggMTAyLjE4NSA1NS45MzUyIDEwMS41NDNaIiBmaWxsPSIjRkQ1MjYzIi8+PHBhdGggZD0iTTMzLjI1NDkgOTEuMDE0TDI0Ljc4MjEgNzIuNTgzMkw4LjYzMTM1IDc2Ljc5NzVMMzMuMjU0OSA5MS4wMTRaIiBmaWxsPSIjRkZDRjIzIi8+PHBhdGggZD0iTTUxLjA3OSA4Ni42NjM5QzUxLjA3OSA4Ni42NjM5IDUxLjA3NDkgODYuNjU3NiA1MS4wNzY2IDg2LjY1NDdDNTAuMjQ2NCA4Ni44NTE0IDQ5LjM0MTQgODYuNzYxNSA0OC41NDgyIDg2LjMwMzZMMjQuNzg0NiA3Mi41ODM3TDMzLjI2MDQgOTEuMDE2MUw1MS4wODM2IDg2LjY2MjdMNTEuMDc5IDg2LjY2MzlaIiBmaWxsPSIjRkM4NzUzIi8+PHBhdGggZD0iTTU0LjMzNDIgMTAxLjk2OUw1MS4wNTU4IDg2LjY3MjRMNjguNjgwNSA4MS41ODI0TDU4LjQ5NTkgOTkuMjIyN0M1Ny41ODc3IDEwMC43OTYgNTYuMDE3OCAxMDEuNzQ0IDU0LjMzNDIgMTAxLjk2OVoiIGZpbGw9IiM0MkQzQTkiLz48cGF0aCBkPSJNNjguNjgwMSA4MS41ODk5TDY2Ljc0OTMgNjEuNDE2Mkw4Mi44NTU2IDU3LjAzNzJMNjguNjgwMSA4MS41ODk5WiIgZmlsbD0iIzI3OTdFOCIvPjxwYXRoIGQ9Ik01MS4wNTU3IDg2LjY3ODZDNTEuMDU1NyA4Ni42Nzg2IDUxLjA1NjIgODYuNjcxMSA1MS4wNTMyIDg2LjY2OTVDNTEuODcxMSA4Ni40MjcxIDUyLjYwOTcgODUuODk5NCA1My4wNjYzIDg1LjEwODVMNjYuNzQ2NyA2MS40MTMzTDY4LjY3NTkgODEuNTg5OEw1MS4wNTExIDg2LjY3OThMNTEuMDU1NyA4Ni42Nzg2WiIgZmlsbD0iIzFEQkFDQiIvPjxwYXRoIGQ9Ik00Ny44OTQ5IDI2LjI3NjhDNDcuODc4IDI2LjM1OTcgNDcuODUyIDI2LjQ0NTEgNDcuODA2OCAyNi41MjM0TDQ3LjYyNzggMjYuODMzM0M0Ni43ODY1IDI4LjI5MDYgNDQuOTIzMiAyOC43ODY5IDQzLjQ2MTggMjcuOTQzMkM0Mi4wMDA0IDI3LjA5OTQgNDEuNDk4NiAyNS4yMzc2IDQyLjMzOTkgMjMuNzgwNEw0Mi41MTg5IDIzLjQ3MDRDNDIuNTY0MSAyMy4zOTIyIDQyLjYyNSAyMy4zMjY5IDQyLjY4ODQgMjMuMjcwOEwzNi40ODUzIDE5LjY4OTRDMzQuOTA3NiAxOC43Nzg2IDMzLjA3MTQgMTguNzM4MiAzMS41IDE5LjM3OTlMMzYuMzUzMyAzNC4yNTY5TDU0LjE3NjUgMjkuOTAzNUw0Ny44OTQ5IDI2LjI3NjhaIiBmaWxsPSIjRkQ1MjYzIi8+PHBhdGggZD0iTTc1LjYzODYgNDIuMzAyN0M3NS42MjE3IDQyLjM4NTcgNzUuNTk1NiA0Mi40NzExIDc1LjU1MDUgNDIuNTQ5M0w3NS4zNzE1IDQyLjg1OTNDNzQuNTMwMiA0NC4zMTY1IDcyLjY2NjkgNDQuODEyOSA3MS4yMDU0IDQzLjk2OTFDNjkuNzQ0IDQzLjEyNTQgNjkuMjQyMyA0MS4yNjM2IDcwLjA4MzYgMzkuODA2M0w3MC4yNjI2IDM5LjQ5NjNDNzAuMzA3NyAzOS40MTgxIDcwLjM2ODYgMzkuMzUyOSA3MC40MzIgMzkuMjk2N0w1NC4xNzYxIDI5LjkxMTRMNjIuNjUxOSA0OC4zNDM5TDc4LjgwMjYgNDQuMTI5NUw3NS42NDE1IDQyLjMwNDRMNzUuNjM4NiA0Mi4zMDI3WiIgZmlsbD0iI0ZGQ0YyMyIvPjxwYXRoIGQ9Ik03NS42MDU4IDQwLjgyMTlMNzUuNjQ0MiA0MC43NTUyQzc4LjE0ODEgMzYuNDE4MyA3OC42NDY1IDMxLjQ0ODggNzcuNDMwOSAyNi45MzgzQzc2LjIxNTMgMjIuNDI3OCA3My4yODQ3IDE4LjM3MTggNjguOTM1MiAxNS44NjA3QzY0LjU4NTggMTMuMzQ5NSA1OS42MDc5IDEyLjgzOTUgNTUuMDkzOSAxNC4wNDJDNTAuNTc5OSAxNS4yNDQ2IDQ2LjUyNTMgMTguMTYwOSA0NC4wMjE0IDIyLjQ5NzhMNDIuOTkxMSAyNC4yODI0QzQyLjM3MzkgMjUuMzUxNCA0Mi43NDQyIDI2LjcxNjMgNDMuODEzNCAyNy4zMzM2QzQ0Ljg4MjYgMjcuOTUwOSA0Ni4yNTE0IDI3LjU4NjIgNDYuODY2OSAyNi41MjAxTDQ3Ljg5NzMgMjQuNzM1NUM0OS43ODU3IDIxLjQ2NDcgNTIuODQ0MSAxOS4yNjczIDU2LjI1NDggMTguMzU4N0M1OS42NjU0IDE3LjQ1MDEgNjMuNDE5MSAxNy44MzI3IDY2LjY5OTQgMTkuNzI2NkM2OS45Nzk2IDIxLjYyMDQgNzIuMTg3OSAyNC42Nzk5IDczLjEwNjMgMjguMDg3OUM3NC4wMjQ4IDMxLjQ5NiA3My42NTEgMzUuMjQzNCA3MS43NjI2IDM4LjUxNDFMNzEuNzI0MSAzOC41ODA4TDcwLjczMzkgNDAuMjk1OEM3MC4xMTY3IDQxLjM2NDkgNzAuNDg3IDQyLjcyOTcgNzEuNTU2MiA0My4zNDdDNzIuNjI1NCA0My45NjQ0IDczLjk5NDIgNDMuNTk5NyA3NC42MDk4IDQyLjUzMzZMNzUuNTk5OSA0MC44MTg1TDc1LjYwNTggNDAuODIxOVoiIGZpbGw9IiMzRDRDNjYiLz48L3N2Zz4="; // crisp vector mark (was logo.png — pixelated when scaled)
|
|
10
10
|
const basilAlmondImg = `${ASSETS_BASE_URL}/basil-almond-paste.png`;
|
|
11
11
|
const beerImg = `${ASSETS_BASE_URL}/beer-paste.png`;
|
|
12
12
|
const beetImg = `${ASSETS_BASE_URL}/beet-paste.png`;
|
|
@@ -335,6 +335,9 @@ export const MOCK_ORDER_1 = {
|
|
|
335
335
|
companyId: MOCK_COMPANY.id,
|
|
336
336
|
externalId: null,
|
|
337
337
|
status: "completed",
|
|
338
|
+
paymentState: "paid",
|
|
339
|
+
fulfillmentState: "fulfilled",
|
|
340
|
+
displayState: "Completed",
|
|
338
341
|
customer: MOCK_CUSTOMER_1,
|
|
339
342
|
summary: {
|
|
340
343
|
total: 2100,
|
|
@@ -382,6 +385,9 @@ export const MOCK_ORDER_2 = {
|
|
|
382
385
|
companyId: MOCK_COMPANY.id,
|
|
383
386
|
externalId: null,
|
|
384
387
|
status: "completed",
|
|
388
|
+
paymentState: "paid",
|
|
389
|
+
fulfillmentState: "fulfilled",
|
|
390
|
+
displayState: "Completed",
|
|
385
391
|
customer: MOCK_CUSTOMER_2,
|
|
386
392
|
summary: {
|
|
387
393
|
total: 3000,
|
|
@@ -421,6 +427,140 @@ export const MOCK_ORDER_2 = {
|
|
|
421
427
|
station: MOCK_STATION_2,
|
|
422
428
|
createdAt: new Date(Date.now() - 3600000).toISOString()
|
|
423
429
|
};
|
|
430
|
+
export const MOCK_ORDER_3 = {
|
|
431
|
+
_id: "order_1003",
|
|
432
|
+
currency: CurrencyCode.USD,
|
|
433
|
+
minorUnits: 2,
|
|
434
|
+
receiptId: "1001-0003",
|
|
435
|
+
companyId: MOCK_COMPANY.id,
|
|
436
|
+
externalId: null,
|
|
437
|
+
status: "refunded",
|
|
438
|
+
paymentState: "refunded",
|
|
439
|
+
fulfillmentState: "fulfilled",
|
|
440
|
+
displayState: "Refunded",
|
|
441
|
+
customer: MOCK_CUSTOMER_3,
|
|
442
|
+
summary: {
|
|
443
|
+
total: 1500,
|
|
444
|
+
subTotal: 1500,
|
|
445
|
+
discountTotal: 0,
|
|
446
|
+
shippingTotal: 0,
|
|
447
|
+
totalTaxes: 0,
|
|
448
|
+
taxes: [],
|
|
449
|
+
isTaxInclusive: false
|
|
450
|
+
},
|
|
451
|
+
cartDiscount: null,
|
|
452
|
+
cartFees: [],
|
|
453
|
+
paymentMethods: [
|
|
454
|
+
{
|
|
455
|
+
transactionId: "trans_card_2",
|
|
456
|
+
paymentType: "credit_card",
|
|
457
|
+
amount: 1500,
|
|
458
|
+
timestamp: new Date(Date.now() - 7200000).toISOString(),
|
|
459
|
+
processor: "stripe"
|
|
460
|
+
}
|
|
461
|
+
],
|
|
462
|
+
source: "pos",
|
|
463
|
+
posData: {
|
|
464
|
+
outlet: MOCK_OUTLET_MAIN.id,
|
|
465
|
+
station: MOCK_STATION_1._id,
|
|
466
|
+
employee: MOCK_USER_MARIO.id
|
|
467
|
+
},
|
|
468
|
+
sessionId: "sess_3",
|
|
469
|
+
metadata: [],
|
|
470
|
+
billing: null,
|
|
471
|
+
shipping: null,
|
|
472
|
+
lineItems: [createLineItem(MOCK_PRODUCT_BEET, 0, 1)],
|
|
473
|
+
customSales: [],
|
|
474
|
+
balance: 0,
|
|
475
|
+
user: MOCK_USER_MARIO,
|
|
476
|
+
outlet: MOCK_OUTLET_MAIN,
|
|
477
|
+
station: MOCK_STATION_1,
|
|
478
|
+
createdAt: new Date(Date.now() - 7200000).toISOString()
|
|
479
|
+
};
|
|
480
|
+
export const MOCK_PARKED_ORDER_1 = {
|
|
481
|
+
_id: "parked_2001",
|
|
482
|
+
currency: CurrencyCode.USD,
|
|
483
|
+
minorUnits: 2,
|
|
484
|
+
receiptId: "PARK-0001",
|
|
485
|
+
companyId: MOCK_COMPANY.id,
|
|
486
|
+
externalId: null,
|
|
487
|
+
status: "parked",
|
|
488
|
+
paymentState: "unpaid",
|
|
489
|
+
fulfillmentState: "unfulfilled",
|
|
490
|
+
displayState: "Parked",
|
|
491
|
+
customer: MOCK_CUSTOMER_4,
|
|
492
|
+
summary: {
|
|
493
|
+
total: 2100,
|
|
494
|
+
subTotal: 2100,
|
|
495
|
+
discountTotal: 0,
|
|
496
|
+
shippingTotal: 0,
|
|
497
|
+
totalTaxes: 0,
|
|
498
|
+
taxes: [],
|
|
499
|
+
isTaxInclusive: false
|
|
500
|
+
},
|
|
501
|
+
cartDiscount: null,
|
|
502
|
+
cartFees: [],
|
|
503
|
+
paymentMethods: [],
|
|
504
|
+
source: "pos",
|
|
505
|
+
posData: {
|
|
506
|
+
outlet: MOCK_OUTLET_MAIN.id,
|
|
507
|
+
station: MOCK_STATION_1._id,
|
|
508
|
+
employee: MOCK_USER_LUIGI.id
|
|
509
|
+
},
|
|
510
|
+
sessionId: "sess_park_1",
|
|
511
|
+
metadata: [],
|
|
512
|
+
billing: null,
|
|
513
|
+
shipping: null,
|
|
514
|
+
lineItems: [createLineItem(MOCK_PRODUCT_LEMON, 0, 2)],
|
|
515
|
+
customSales: [],
|
|
516
|
+
balance: 2100,
|
|
517
|
+
user: MOCK_USER_LUIGI,
|
|
518
|
+
outlet: MOCK_OUTLET_MAIN,
|
|
519
|
+
station: MOCK_STATION_1,
|
|
520
|
+
createdAt: new Date(Date.now() - 1800000).toISOString()
|
|
521
|
+
};
|
|
522
|
+
export const MOCK_PARKED_ORDER_2 = {
|
|
523
|
+
_id: "parked_2002",
|
|
524
|
+
currency: CurrencyCode.USD,
|
|
525
|
+
minorUnits: 2,
|
|
526
|
+
receiptId: "PARK-0002",
|
|
527
|
+
companyId: MOCK_COMPANY.id,
|
|
528
|
+
externalId: null,
|
|
529
|
+
status: "parked",
|
|
530
|
+
paymentState: "unpaid",
|
|
531
|
+
fulfillmentState: "unfulfilled",
|
|
532
|
+
displayState: "Parked",
|
|
533
|
+
customer: null,
|
|
534
|
+
summary: {
|
|
535
|
+
total: 2500,
|
|
536
|
+
subTotal: 2500,
|
|
537
|
+
discountTotal: 0,
|
|
538
|
+
shippingTotal: 0,
|
|
539
|
+
totalTaxes: 0,
|
|
540
|
+
taxes: [],
|
|
541
|
+
isTaxInclusive: false
|
|
542
|
+
},
|
|
543
|
+
cartDiscount: null,
|
|
544
|
+
cartFees: [],
|
|
545
|
+
paymentMethods: [],
|
|
546
|
+
source: "pos",
|
|
547
|
+
posData: {
|
|
548
|
+
outlet: MOCK_OUTLET_MAIN.id,
|
|
549
|
+
station: MOCK_STATION_2._id,
|
|
550
|
+
employee: MOCK_USER_MARIO.id
|
|
551
|
+
},
|
|
552
|
+
sessionId: "sess_park_2",
|
|
553
|
+
metadata: [],
|
|
554
|
+
billing: null,
|
|
555
|
+
shipping: null,
|
|
556
|
+
lineItems: [createLineItem(MOCK_PRODUCT_CARAMELIZED, 0, 1), createLineItem(MOCK_PRODUCT_GINGER_LIME, 0, 1)],
|
|
557
|
+
customSales: [],
|
|
558
|
+
balance: 2500,
|
|
559
|
+
user: MOCK_USER_MARIO,
|
|
560
|
+
outlet: MOCK_OUTLET_MAIN,
|
|
561
|
+
station: MOCK_STATION_2,
|
|
562
|
+
createdAt: new Date(Date.now() - 900000).toISOString()
|
|
563
|
+
};
|
|
424
564
|
// --- EXPORT COLLECTIONS ---
|
|
425
565
|
export const MOCK_USERS = [MOCK_USER_MARIO, MOCK_USER_LUIGI];
|
|
426
566
|
export const MOCK_STATIONS = [MOCK_STATION_1, MOCK_STATION_2];
|
|
@@ -443,8 +583,8 @@ export const MOCK_PRODUCTS = [
|
|
|
443
583
|
MOCK_PRODUCT_HABANERO,
|
|
444
584
|
MOCK_PRODUCT_BLACK_GARLIC
|
|
445
585
|
];
|
|
446
|
-
export const MOCK_ORDERS = [MOCK_ORDER_1, MOCK_ORDER_2];
|
|
447
|
-
export const MOCK_PARKED_ORDERS = [];
|
|
586
|
+
export const MOCK_ORDERS = [MOCK_ORDER_1, MOCK_ORDER_2, MOCK_ORDER_3];
|
|
587
|
+
export const MOCK_PARKED_ORDERS = [MOCK_PARKED_ORDER_1, MOCK_PARKED_ORDER_2];
|
|
448
588
|
// Compatibility Exports (reassigned by setMockDatabase)
|
|
449
589
|
export let MOCK_USER = MOCK_USERS[0];
|
|
450
590
|
export let MOCK_STATION = MOCK_STATIONS[0];
|
|
@@ -607,6 +747,9 @@ export const createOrderFromCart = (paymentType, amount, processor = "cash") =>
|
|
|
607
747
|
companyId: MOCK_COMPANY.id,
|
|
608
748
|
externalId: null,
|
|
609
749
|
status: "completed",
|
|
750
|
+
paymentState: "paid",
|
|
751
|
+
fulfillmentState: "fulfilled",
|
|
752
|
+
displayState: "Completed",
|
|
610
753
|
customer: MOCK_CART.customer ? MOCK_CART.customer : null,
|
|
611
754
|
summary: {
|
|
612
755
|
total: totalNum,
|
|
@@ -652,3 +795,26 @@ export const createOrderFromCart = (paymentType, amount, processor = "cash") =>
|
|
|
652
795
|
mockPublishEvent("cart", "cart-created", {});
|
|
653
796
|
return newOrder;
|
|
654
797
|
};
|
|
798
|
+
/**
|
|
799
|
+
* Apply a (possibly partial) payment of `amount` minor units to the active cart.
|
|
800
|
+
* Decrements the remaining balance; when it reaches zero the sale completes
|
|
801
|
+
* (creates the order, resets the cart, returns it). Otherwise the cart stays
|
|
802
|
+
* open with `amountToBeCharged` reset to what's left, and returns null.
|
|
803
|
+
*/
|
|
804
|
+
export const applyMockPayment = (amount, paymentType, processor = "cash") => {
|
|
805
|
+
const remainingBefore = MOCK_CART.remainingBalance ?? MOCK_CART.total;
|
|
806
|
+
const charge = Math.min(Math.max(0, amount || remainingBefore), remainingBefore);
|
|
807
|
+
const remainingAfter = Math.max(0, remainingBefore - charge);
|
|
808
|
+
if (remainingAfter > 0) {
|
|
809
|
+
// Partial payment — keep the cart open, queue the rest for the next tender.
|
|
810
|
+
MOCK_CART.remainingBalance = remainingAfter;
|
|
811
|
+
MOCK_CART.amountToBeCharged = remainingAfter;
|
|
812
|
+
mockPublishEvent("cart", "partial-payment-applied", { charged: charge, remaining: remainingAfter });
|
|
813
|
+
return null;
|
|
814
|
+
}
|
|
815
|
+
// Fully paid — create the completed order (this also resets the cart).
|
|
816
|
+
const orderTotal = MOCK_CART.total;
|
|
817
|
+
const order = createOrderFromCart(paymentType, orderTotal, processor);
|
|
818
|
+
mockPublishEvent("payments", "payment-done", { order });
|
|
819
|
+
return order;
|
|
820
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { preorderNoDepositFragment } from "./preorder-no-deposit";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { preorderNoDepositFragment } from "./preorder-no-deposit";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { CFStateConfigFragment } from "../common-types/state-fragment";
|
|
2
|
+
/**
|
|
3
|
+
* Pre-order fragment — no deposit required.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors preorder-with-deposit but removes the cross-axis rule that gates
|
|
6
|
+
* `on_hold` on payment state. An order can be placed on hold while still
|
|
7
|
+
* `unpaid` — payment is collected later (pay-at-pickup, BOPIS, COD, etc.).
|
|
8
|
+
*
|
|
9
|
+
* State flow:
|
|
10
|
+
*
|
|
11
|
+
* unpaid|on_hold → (cashier collects payment) → paid|on_hold
|
|
12
|
+
* ↓
|
|
13
|
+
* (progress fulfillment)
|
|
14
|
+
* ↓
|
|
15
|
+
* paid|in_progress
|
|
16
|
+
*
|
|
17
|
+
* Key difference from preorder-with-deposit:
|
|
18
|
+
* - No cross-axis rule blocking `on_hold` when unpaid. The cashier can
|
|
19
|
+
* confirm the pre-order without collecting a deposit first.
|
|
20
|
+
* - `unpaid|on_hold` is whitelisted as a valid first-save state pair.
|
|
21
|
+
* - `in_progress` still requires at least a partial payment (you must pay
|
|
22
|
+
* before the merchant starts fulfilling).
|
|
23
|
+
*
|
|
24
|
+
* Prefix all IDs with your extension id before merging to avoid collisions.
|
|
25
|
+
*/
|
|
26
|
+
export declare const preorderNoDepositFragment: CFStateConfigFragment;
|