@final-commerce/command-frame 0.1.63 → 0.2.0-beta.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.
- package/README.md +26 -28
- package/dist/CommonTypes.d.ts +118 -19
- package/dist/actions/add-customer-note/mock.js +27 -18
- package/dist/actions/add-customer-note/types.d.ts +3 -2
- package/dist/actions/add-product/mock.js +11 -5
- 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/types.d.ts +5 -0
- package/dist/actions/delete-parked-order/types.d.ts +3 -0
- package/dist/actions/edit-product/mock.js +4 -2
- 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 +12 -6
- package/dist/actions/initiate-refund/types.d.ts +3 -0
- package/dist/actions/park-order/types.d.ts +3 -0
- package/dist/actions/partial-payment/types.d.ts +5 -0
- package/dist/actions/print/mock.js +3 -6
- package/dist/actions/print/types.d.ts +1 -7
- package/dist/actions/process-partial-refund/types.d.ts +3 -0
- package/dist/actions/remove-customer-note/mock.js +16 -7
- package/dist/actions/resume-parked-order/types.d.ts +3 -0
- package/dist/actions/tap-to-pay-payment/types.d.ts +5 -0
- package/dist/actions/terminal-payment/types.d.ts +5 -0
- 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.js +18 -24
- 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 +17 -2
- package/dist/index.js +12 -0
- package/dist/projects/render/mocks.js +5 -1
- package/dist/projects/render/types.d.ts +3 -1
- package/dist/pubsub/topics/attributes/attribute-created/types.d.ts +6 -0
- package/dist/pubsub/topics/attributes/attribute-created/types.js +1 -0
- package/dist/pubsub/topics/attributes/attribute-updated/types.d.ts +6 -0
- package/dist/pubsub/topics/attributes/attribute-updated/types.js +1 -0
- package/dist/pubsub/topics/attributes/index.d.ts +3 -0
- package/dist/pubsub/topics/attributes/index.js +18 -0
- package/dist/pubsub/topics/attributes/types.d.ts +6 -0
- package/dist/pubsub/topics/attributes/types.js +2 -0
- package/dist/pubsub/topics/categories/category-created/types.d.ts +6 -0
- package/dist/pubsub/topics/categories/category-created/types.js +1 -0
- package/dist/pubsub/topics/categories/category-updated/types.d.ts +6 -0
- package/dist/pubsub/topics/categories/category-updated/types.js +1 -0
- package/dist/pubsub/topics/categories/index.d.ts +3 -0
- package/dist/pubsub/topics/categories/index.js +18 -0
- package/dist/pubsub/topics/categories/types.d.ts +6 -0
- package/dist/pubsub/topics/categories/types.js +2 -0
- package/dist/pubsub/topics/index.d.ts +4 -0
- package/dist/pubsub/topics/index.js +4 -0
- 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/dist/pubsub/topics/print/print-completed/types.d.ts +1 -1
- package/dist/pubsub/topics/print/print-error/types.d.ts +1 -1
- package/dist/pubsub/topics/print/print-started/types.d.ts +1 -1
- package/dist/pubsub/topics/transactions/index.d.ts +3 -0
- package/dist/pubsub/topics/transactions/index.js +18 -0
- package/dist/pubsub/topics/transactions/transaction-created/types.d.ts +6 -0
- package/dist/pubsub/topics/transactions/transaction-created/types.js +1 -0
- package/dist/pubsub/topics/transactions/transaction-updated/types.d.ts +6 -0
- package/dist/pubsub/topics/transactions/transaction-updated/types.js +1 -0
- package/dist/pubsub/topics/transactions/types.d.ts +6 -0
- package/dist/pubsub/topics/transactions/types.js +2 -0
- package/dist/pubsub/topics/types.d.ts +8 -0
- package/dist/pubsub/topics/users/index.js +10 -0
- package/dist/pubsub/topics/users/types.d.ts +6 -2
- package/dist/pubsub/topics/users/types.js +2 -0
- package/dist/pubsub/topics/users/user-created/types.d.ts +6 -0
- package/dist/pubsub/topics/users/user-created/types.js +1 -0
- package/dist/pubsub/topics/users/user-updated/types.d.ts +6 -0
- package/dist/pubsub/topics/users/user-updated/types.js +1 -0
- package/dist/pubsub/topics/variants/index.d.ts +3 -0
- package/dist/pubsub/topics/variants/index.js +18 -0
- package/dist/pubsub/topics/variants/types.d.ts +6 -0
- package/dist/pubsub/topics/variants/types.js +2 -0
- package/dist/pubsub/topics/variants/variant-created/types.d.ts +6 -0
- package/dist/pubsub/topics/variants/variant-created/types.js +1 -0
- package/dist/pubsub/topics/variants/variant-updated/types.d.ts +6 -0
- package/dist/pubsub/topics/variants/variant-updated/types.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock implementation: returns a fixed set of plausible transitions
|
|
3
|
+
* so the demo app has data to render.
|
|
4
|
+
*/
|
|
5
|
+
export const getAvailableTransitionsMock = async (_params) => ({
|
|
6
|
+
transitions: [
|
|
7
|
+
{
|
|
8
|
+
to: { payment: "refunded", fulfillment: "returned" },
|
|
9
|
+
displayLabel: "Full Refund",
|
|
10
|
+
conditions: [{ met: true, description: "Order is paid" }],
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
to: { payment: "partially_refunded", fulfillment: "partially_returned" },
|
|
14
|
+
displayLabel: "Partial Refund",
|
|
15
|
+
conditions: [{ met: true, description: "Order is paid" }],
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
to: { payment: "voided", fulfillment: "cancelled" },
|
|
19
|
+
displayLabel: "Void Order",
|
|
20
|
+
conditions: [
|
|
21
|
+
{ met: true, description: "Order exists" },
|
|
22
|
+
{ met: false, description: "No payments captured (mock: skipped)" },
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CFAvailableTransition } from "../../common-types/order-state";
|
|
2
|
+
export interface GetAvailableTransitionsParams {
|
|
3
|
+
/** Order to evaluate. Required — we need the current state. */
|
|
4
|
+
orderId: string;
|
|
5
|
+
}
|
|
6
|
+
export interface GetAvailableTransitionsResponse {
|
|
7
|
+
transitions: CFAvailableTransition[];
|
|
8
|
+
}
|
|
9
|
+
export type GetAvailableTransitions = (params: GetAvailableTransitionsParams) => Promise<GetAvailableTransitionsResponse>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { MOCK_COMPANY, MOCK_OUTLET, MOCK_STATION, MOCK_USER } from "../../demo/database";
|
|
2
2
|
// Mock for Render context (POS terminal)
|
|
3
|
-
export const mockGetContext =
|
|
3
|
+
export const mockGetContext = () => {
|
|
4
4
|
console.log("[Mock] getContext called (Render)");
|
|
5
|
-
return {
|
|
5
|
+
return Promise.resolve({
|
|
6
6
|
userId: MOCK_USER.id || null,
|
|
7
7
|
companyId: MOCK_COMPANY.id || null,
|
|
8
8
|
companyName: MOCK_COMPANY.name || null,
|
|
@@ -17,17 +17,23 @@ export const mockGetContext = async () => {
|
|
|
17
17
|
buildSourceId: "mock_source_id",
|
|
18
18
|
buildIsPremium: true,
|
|
19
19
|
isOffline: false,
|
|
20
|
+
currency: "USD",
|
|
21
|
+
currencySymbol: "$",
|
|
22
|
+
currencyPrefix: "$",
|
|
23
|
+
currencySuffix: "",
|
|
24
|
+
thousandSeparator: ",",
|
|
25
|
+
decimalSeparator: ".",
|
|
20
26
|
user: null,
|
|
21
27
|
company: null,
|
|
22
28
|
station: null,
|
|
23
29
|
outlet: null,
|
|
24
30
|
timestamp: new Date().toISOString()
|
|
25
|
-
};
|
|
31
|
+
});
|
|
26
32
|
};
|
|
27
33
|
// Mock for Manage context (Hub/BuilderHub)
|
|
28
|
-
export const mockGetContextManage =
|
|
34
|
+
export const mockGetContextManage = () => {
|
|
29
35
|
console.log("[Mock] getContext called (Manage)");
|
|
30
|
-
return {
|
|
36
|
+
return Promise.resolve({
|
|
31
37
|
user: {
|
|
32
38
|
_id: MOCK_USER.id,
|
|
33
39
|
id: MOCK_USER.id,
|
|
@@ -47,5 +53,5 @@ export const mockGetContextManage = async () => {
|
|
|
47
53
|
extensionId: "mock_extension_id",
|
|
48
54
|
outlets: [MOCK_OUTLET],
|
|
49
55
|
timestamp: new Date().toISOString()
|
|
50
|
-
};
|
|
56
|
+
});
|
|
51
57
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
1
2
|
export interface InitiateRefundParams {
|
|
2
3
|
/** The ID of the order to refund. If not provided, uses the currently active order. */
|
|
3
4
|
orderId?: string;
|
|
@@ -6,5 +7,7 @@ export interface InitiateRefundResponse {
|
|
|
6
7
|
success: boolean;
|
|
7
8
|
orderId: string;
|
|
8
9
|
timestamp: string;
|
|
10
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
11
|
+
transitionResult?: CFTransitionResult;
|
|
9
12
|
}
|
|
10
13
|
export type InitiateRefund = (params?: InitiateRefundParams) => Promise<InitiateRefundResponse>;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { CFOrder } from "../../CommonTypes";
|
|
2
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
2
3
|
export interface ParkOrderResponse {
|
|
3
4
|
success: boolean;
|
|
4
5
|
order: CFOrder;
|
|
5
6
|
timestamp: string;
|
|
7
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
8
|
+
transitionResult?: CFTransitionResult;
|
|
6
9
|
}
|
|
7
10
|
export type ParkOrder = () => Promise<ParkOrderResponse>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CFOrder } from "../../CommonTypes";
|
|
2
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
2
3
|
export interface PartialPaymentParams {
|
|
3
4
|
/** The payment amount (required if openUI is false). */
|
|
4
5
|
amount?: number;
|
|
@@ -6,6 +7,8 @@ export interface PartialPaymentParams {
|
|
|
6
7
|
isPercent?: boolean;
|
|
7
8
|
/** If true, opens the split payment UI. */
|
|
8
9
|
openUI?: boolean;
|
|
10
|
+
/** Override the fulfillment state after full payment. Render resolves the cascade. */
|
|
11
|
+
checkoutFulfillmentTarget?: string;
|
|
9
12
|
}
|
|
10
13
|
export interface PartialPaymentResponse {
|
|
11
14
|
success: boolean;
|
|
@@ -14,5 +17,7 @@ export interface PartialPaymentResponse {
|
|
|
14
17
|
openUI: boolean;
|
|
15
18
|
order: CFOrder | null;
|
|
16
19
|
timestamp: string;
|
|
20
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
21
|
+
transitionResult?: CFTransitionResult;
|
|
17
22
|
}
|
|
18
23
|
export type PartialPayment = (params?: PartialPaymentParams) => Promise<PartialPaymentResponse>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const mockPrint =
|
|
1
|
+
export const mockPrint = (params) => {
|
|
2
2
|
console.log("[Mock] print called", params);
|
|
3
3
|
if (!params) {
|
|
4
4
|
throw new Error("Print parameters are required");
|
|
@@ -11,16 +11,13 @@ export const mockPrint = async (params) => {
|
|
|
11
11
|
case "html":
|
|
12
12
|
console.log("[Mock] Would print HTML:", params.data.html?.substring(0, 100) + "...");
|
|
13
13
|
break;
|
|
14
|
-
case "selector":
|
|
15
|
-
console.log("[Mock] Would print element with selector:", params.data.selector);
|
|
16
|
-
break;
|
|
17
14
|
case "receipt":
|
|
18
15
|
console.log("[Mock] Would print receipt for order:", params.data.order);
|
|
19
16
|
break;
|
|
20
17
|
}
|
|
21
|
-
return {
|
|
18
|
+
return Promise.resolve({
|
|
22
19
|
success: true,
|
|
23
20
|
timestamp: new Date().toISOString(),
|
|
24
21
|
type: params.type
|
|
25
|
-
};
|
|
22
|
+
});
|
|
26
23
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CFActiveOrder } from "../../CommonTypes";
|
|
2
|
-
export type PrintType = "image" | "html" | "
|
|
2
|
+
export type PrintType = "image" | "html" | "receipt";
|
|
3
3
|
export type PrintParams = {
|
|
4
4
|
type: "image";
|
|
5
5
|
data: {
|
|
@@ -12,12 +12,6 @@ export type PrintParams = {
|
|
|
12
12
|
html: string;
|
|
13
13
|
};
|
|
14
14
|
options?: PrintOptions;
|
|
15
|
-
} | {
|
|
16
|
-
type: "selector";
|
|
17
|
-
data: {
|
|
18
|
-
selector: string;
|
|
19
|
-
};
|
|
20
|
-
options?: PrintOptions;
|
|
21
15
|
} | {
|
|
22
16
|
type: "receipt";
|
|
23
17
|
data: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
1
2
|
export interface ProcessPartialRefundParams {
|
|
2
3
|
/** Optional refund reason. */
|
|
3
4
|
reason?: string;
|
|
@@ -15,5 +16,7 @@ export interface ProcessPartialRefundResponse {
|
|
|
15
16
|
success: boolean;
|
|
16
17
|
refundId: string;
|
|
17
18
|
timestamp: string;
|
|
19
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
20
|
+
transitionResult?: CFTransitionResult;
|
|
18
21
|
}
|
|
19
22
|
export type ProcessPartialRefund = (params?: ProcessPartialRefundParams) => Promise<ProcessPartialRefundResponse>;
|
|
@@ -1,13 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
import { MOCK_CUSTOMERS, mockPublishEvent } from "../../demo/database";
|
|
2
|
+
export const mockRemoveCustomerNote = (params) => {
|
|
2
3
|
console.log("[Mock] removeCustomerNote called", params);
|
|
3
4
|
const noteId = params?.noteId ?? "";
|
|
4
5
|
const timestamp = new Date().toISOString();
|
|
5
6
|
if (!noteId) {
|
|
6
|
-
return { success: false, noteId, timestamp };
|
|
7
|
+
return Promise.resolve({ success: false, noteId, timestamp });
|
|
7
8
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
noteId
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
for (const customer of MOCK_CUSTOMERS) {
|
|
10
|
+
const before = customer.notes?.length ?? 0;
|
|
11
|
+
const removed = (customer.notes || []).find(n => n._id === noteId);
|
|
12
|
+
customer.notes = (customer.notes || []).filter(n => n._id !== noteId);
|
|
13
|
+
if ((customer.notes?.length ?? 0) !== before) {
|
|
14
|
+
mockPublishEvent("customers", "customer-note-deleted", {
|
|
15
|
+
customer,
|
|
16
|
+
note: removed
|
|
17
|
+
});
|
|
18
|
+
return Promise.resolve({ success: true, noteId, timestamp });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return Promise.resolve({ success: false, noteId, timestamp });
|
|
13
22
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CFOrder } from "../../CommonTypes";
|
|
2
|
+
import type { CFTransitionResult } from "../../common-types/order-state";
|
|
2
3
|
export interface ResumeParkedOrderParams {
|
|
3
4
|
orderId: string;
|
|
4
5
|
}
|
|
@@ -6,5 +7,7 @@ export interface ResumeParkedOrderResponse {
|
|
|
6
7
|
success: boolean;
|
|
7
8
|
order: CFOrder;
|
|
8
9
|
timestamp: string;
|
|
10
|
+
/** Present when the state machine blocked or forced the transition. */
|
|
11
|
+
transitionResult?: CFTransitionResult;
|
|
9
12
|
}
|
|
10
13
|
export type ResumeParkedOrder = (params?: ResumeParkedOrderParams) => Promise<ResumeParkedOrderResponse>;
|
|
@@ -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,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,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.js
CHANGED
|
@@ -202,7 +202,7 @@ export const MOCK_CATEGORY_SPICY = {
|
|
|
202
202
|
parentId: null
|
|
203
203
|
};
|
|
204
204
|
// --- PRODUCTS ---
|
|
205
|
-
const createInventory = (stock) => [{ outletId: MOCK_OUTLET_MAIN.id, stock }];
|
|
205
|
+
const createInventory = (stock) => [{ warehouse: "main", outletId: MOCK_OUTLET_MAIN.id, stock }];
|
|
206
206
|
// Helper for Simple Product
|
|
207
207
|
const createSimpleProduct = (id, name, price, image, categories, description) => {
|
|
208
208
|
const sku = `SKU-${id.toUpperCase()}`;
|
|
@@ -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,
|
|
@@ -366,10 +369,7 @@ export const MOCK_ORDER_1 = {
|
|
|
366
369
|
metadata: [],
|
|
367
370
|
billing: MOCK_CUSTOMER_1.billing || null,
|
|
368
371
|
shipping: null,
|
|
369
|
-
lineItems: [
|
|
370
|
-
createLineItem(MOCK_PRODUCT_GARLIC, 0, 1),
|
|
371
|
-
createLineItem(MOCK_PRODUCT_BASIL_ALMOND, 0, 1)
|
|
372
|
-
],
|
|
372
|
+
lineItems: [createLineItem(MOCK_PRODUCT_GARLIC, 0, 1), createLineItem(MOCK_PRODUCT_BASIL_ALMOND, 0, 1)],
|
|
373
373
|
customSales: [],
|
|
374
374
|
balance: 0,
|
|
375
375
|
user: MOCK_USER_LUIGI,
|
|
@@ -385,6 +385,9 @@ export const MOCK_ORDER_2 = {
|
|
|
385
385
|
companyId: MOCK_COMPANY.id,
|
|
386
386
|
externalId: null,
|
|
387
387
|
status: "completed",
|
|
388
|
+
paymentState: "paid",
|
|
389
|
+
fulfillmentState: "fulfilled",
|
|
390
|
+
displayState: "Completed",
|
|
388
391
|
customer: MOCK_CUSTOMER_2,
|
|
389
392
|
summary: {
|
|
390
393
|
total: 3000,
|
|
@@ -416,9 +419,7 @@ export const MOCK_ORDER_2 = {
|
|
|
416
419
|
metadata: [],
|
|
417
420
|
billing: null,
|
|
418
421
|
shipping: null,
|
|
419
|
-
lineItems: [
|
|
420
|
-
createLineItem(MOCK_PRODUCT_BEER, 0, 2)
|
|
421
|
-
],
|
|
422
|
+
lineItems: [createLineItem(MOCK_PRODUCT_BEER, 0, 2)],
|
|
422
423
|
customSales: [],
|
|
423
424
|
balance: 0,
|
|
424
425
|
user: MOCK_USER_MARIO,
|
|
@@ -430,20 +431,8 @@ export const MOCK_ORDER_2 = {
|
|
|
430
431
|
export const MOCK_USERS = [MOCK_USER_MARIO, MOCK_USER_LUIGI];
|
|
431
432
|
export const MOCK_STATIONS = [MOCK_STATION_1, MOCK_STATION_2];
|
|
432
433
|
export const MOCK_OUTLETS = [MOCK_OUTLET_MAIN];
|
|
433
|
-
export const MOCK_CUSTOMERS = [
|
|
434
|
-
|
|
435
|
-
MOCK_CUSTOMER_2,
|
|
436
|
-
MOCK_CUSTOMER_3,
|
|
437
|
-
MOCK_CUSTOMER_4,
|
|
438
|
-
MOCK_CUSTOMER_5
|
|
439
|
-
];
|
|
440
|
-
export const MOCK_CATEGORIES = [
|
|
441
|
-
MOCK_CATEGORY_PASTES,
|
|
442
|
-
MOCK_CATEGORY_SPECIALTY,
|
|
443
|
-
MOCK_CATEGORY_BASIC,
|
|
444
|
-
MOCK_CATEGORY_VEGAN,
|
|
445
|
-
MOCK_CATEGORY_SPICY
|
|
446
|
-
];
|
|
434
|
+
export const MOCK_CUSTOMERS = [MOCK_CUSTOMER_1, MOCK_CUSTOMER_2, MOCK_CUSTOMER_3, MOCK_CUSTOMER_4, MOCK_CUSTOMER_5];
|
|
435
|
+
export const MOCK_CATEGORIES = [MOCK_CATEGORY_PASTES, MOCK_CATEGORY_SPECIALTY, MOCK_CATEGORY_BASIC, MOCK_CATEGORY_VEGAN, MOCK_CATEGORY_SPICY];
|
|
447
436
|
export const MOCK_PRODUCTS = [
|
|
448
437
|
MOCK_PRODUCT_BASIL_ALMOND,
|
|
449
438
|
MOCK_PRODUCT_BEER,
|
|
@@ -494,7 +483,8 @@ export const resetMockCart = () => {
|
|
|
494
483
|
};
|
|
495
484
|
};
|
|
496
485
|
function resolveMockOrderCurrency() {
|
|
497
|
-
const
|
|
486
|
+
const settings = MOCK_COMPANY.settings;
|
|
487
|
+
const raw = settings?.currency;
|
|
498
488
|
if (typeof raw === "string" && Object.values(CurrencyCode).includes(raw)) {
|
|
499
489
|
return raw;
|
|
500
490
|
}
|
|
@@ -554,6 +544,7 @@ export const safeSerialize = (data) => {
|
|
|
554
544
|
return JSON.parse(JSON.stringify(data));
|
|
555
545
|
};
|
|
556
546
|
const mockTopicSubscribers = {};
|
|
547
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
557
548
|
export const mockPublishEvent = (topic, eventType, data) => {
|
|
558
549
|
const subscribers = mockTopicSubscribers[topic] || [];
|
|
559
550
|
const event = {
|
|
@@ -618,6 +609,9 @@ export const createOrderFromCart = (paymentType, amount, processor = "cash") =>
|
|
|
618
609
|
companyId: MOCK_COMPANY.id,
|
|
619
610
|
externalId: null,
|
|
620
611
|
status: "completed",
|
|
612
|
+
paymentState: "paid",
|
|
613
|
+
fulfillmentState: "fulfilled",
|
|
614
|
+
displayState: "Completed",
|
|
621
615
|
customer: MOCK_CART.customer ? MOCK_CART.customer : null,
|
|
622
616
|
summary: {
|
|
623
617
|
total: totalNum,
|
|
@@ -660,6 +654,6 @@ export const createOrderFromCart = (paymentType, amount, processor = "cash") =>
|
|
|
660
654
|
MOCK_ORDERS.push(newOrder);
|
|
661
655
|
resetMockCart();
|
|
662
656
|
// Publish cart-created event after cart is reset (simulates new empty cart)
|
|
663
|
-
mockPublishEvent(
|
|
657
|
+
mockPublishEvent("cart", "cart-created", {});
|
|
664
658
|
return newOrder;
|
|
665
659
|
};
|
|
@@ -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;
|