@final-commerce/command-frame 0.1.74 → 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/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/cash-payment/mock.js +12 -18
- package/dist/actions/delete-parked-order/mock.js +3 -1
- package/dist/actions/get-context/mock.js +1 -1
- package/dist/actions/get-orders/mock.js +3 -3
- package/dist/actions/park-order/mock.js +4 -1
- package/dist/actions/partial-payment/mock.js +21 -3
- 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/resume-parked-order/mock.js +4 -1
- package/dist/actions/tap-to-pay-payment/mock.js +5 -3
- package/dist/actions/terminal-payment/mock.js +4 -5
- package/dist/demo/database.d.ts +10 -0
- package/dist/demo/database.js +160 -3
- package/dist/projects/render/mocks.js +8 -4
- package/package.json +1 -1
|
@@ -2,17 +2,20 @@ import { MOCK_CART, mockPublishEvent } from "../../demo/database";
|
|
|
2
2
|
export const mockAddCartDiscount = async (params) => {
|
|
3
3
|
console.log("[Mock] addCartDiscount called", params);
|
|
4
4
|
if (params) {
|
|
5
|
+
// Mirror render: input is raw (50 = 50%, 5 = $5). Store percent as a
|
|
6
|
+
// fraction (0.5) and fixed as minor units (500), like the real handler.
|
|
7
|
+
const minorFactor = 10 ** (MOCK_CART.minorUnits ?? 2);
|
|
8
|
+
const value = params.isPercent ? params.amount / 100 : Math.round(params.amount * minorFactor);
|
|
5
9
|
MOCK_CART.discount = {
|
|
6
|
-
value
|
|
10
|
+
value,
|
|
7
11
|
isPercent: params.isPercent,
|
|
8
12
|
label: params.label
|
|
9
13
|
};
|
|
10
|
-
// Simple mock calc (not real logic)
|
|
11
14
|
if (params.isPercent) {
|
|
12
15
|
MOCK_CART.total = MOCK_CART.subtotal * (1 - params.amount / 100);
|
|
13
16
|
}
|
|
14
17
|
else {
|
|
15
|
-
MOCK_CART.total = MOCK_CART.subtotal -
|
|
18
|
+
MOCK_CART.total = MOCK_CART.subtotal - value;
|
|
16
19
|
}
|
|
17
20
|
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
18
21
|
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
@@ -4,18 +4,18 @@ export const mockAddCartFee = async (params) => {
|
|
|
4
4
|
if (params) {
|
|
5
5
|
if (!MOCK_CART.customFee)
|
|
6
6
|
MOCK_CART.customFee = [];
|
|
7
|
+
// Mirror render: input is raw (50 = 50%, 5 = $5). Store percent as a
|
|
8
|
+
// fraction (0.5) and fixed as minor units (500), like the real handler.
|
|
9
|
+
const minorFactor = 10 ** (MOCK_CART.minorUnits ?? 2);
|
|
10
|
+
const storedAmount = params.isPercent ? params.amount / 100 : Math.round(params.amount * minorFactor);
|
|
7
11
|
MOCK_CART.customFee.push({
|
|
8
12
|
label: params.label || "Fee",
|
|
9
|
-
amount:
|
|
13
|
+
amount: storedAmount,
|
|
10
14
|
isPercent: params.isPercent || false,
|
|
11
15
|
applyTaxes: params.applyTaxes || false,
|
|
12
16
|
taxTableId: params.taxTableId
|
|
13
17
|
});
|
|
14
|
-
|
|
15
|
-
let feeAmount = params.amount;
|
|
16
|
-
if (params.isPercent) {
|
|
17
|
-
feeAmount = MOCK_CART.subtotal * (params.amount / 100);
|
|
18
|
-
}
|
|
18
|
+
const feeAmount = params.isPercent ? MOCK_CART.subtotal * (params.amount / 100) : storedAmount;
|
|
19
19
|
MOCK_CART.total += feeAmount;
|
|
20
20
|
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
21
21
|
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { MOCK_CART } from "../../demo/database";
|
|
1
|
+
import { MOCK_CART, mockPublishEvent } from "../../demo/database";
|
|
2
2
|
export const mockAddCustomSale = async (params) => {
|
|
3
3
|
console.log("[Mock] addCustomSale called", params);
|
|
4
4
|
if (!params)
|
|
5
5
|
throw new Error("Params required");
|
|
6
6
|
// Simple mock ID generation
|
|
7
7
|
const mockId = 'sale_' + Math.random().toString(36).substr(2, 9);
|
|
8
|
-
|
|
8
|
+
// Mirror render: the flow sends raw dollars ($4); render does toMinorUnits.
|
|
9
|
+
// MOCK_CART tracks minor units, so convert here too.
|
|
10
|
+
const minorFactor = 10 ** (MOCK_CART.minorUnits ?? 2);
|
|
11
|
+
const price = Math.round(Number(params.price) * minorFactor);
|
|
9
12
|
const quantity = 1; // Default to 1 for custom sale usually
|
|
10
13
|
const customSale = {
|
|
11
14
|
id: mockId,
|
|
@@ -24,6 +27,8 @@ export const mockAddCustomSale = async (params) => {
|
|
|
24
27
|
MOCK_CART.total += price * quantity;
|
|
25
28
|
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
26
29
|
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
30
|
+
// Publish custom-sale-added event so cart subscribers refresh
|
|
31
|
+
mockPublishEvent('cart', 'custom-sale-added', { customSale });
|
|
27
32
|
return {
|
|
28
33
|
success: true,
|
|
29
34
|
customSaleId: mockId,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MOCK_CART } from "../../demo/database";
|
|
1
|
+
import { MOCK_CART, mockPublishEvent } from "../../demo/database";
|
|
2
2
|
export const mockAddOrderNote = async (params) => {
|
|
3
3
|
console.log("[Mock] addOrderNote called", params);
|
|
4
4
|
// In Render, AddOrderNote usually adds a note to the active cart if it's not checked out yet.
|
|
@@ -9,6 +9,8 @@ export const mockAddOrderNote = async (params) => {
|
|
|
9
9
|
else {
|
|
10
10
|
MOCK_CART.orderNotes = params.note;
|
|
11
11
|
}
|
|
12
|
+
// Publish order-note-added event so cart subscribers refresh.
|
|
13
|
+
mockPublishEvent("cart", "order-note-added", { note: params.note });
|
|
12
14
|
}
|
|
13
15
|
return {
|
|
14
16
|
success: true,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MOCK_CART } from "../../demo/database";
|
|
1
|
+
import { MOCK_CART, mockPublishEvent } from "../../demo/database";
|
|
2
2
|
export const mockAddProductDiscount = async (params) => {
|
|
3
3
|
console.log("[Mock] addProductDiscount called", params);
|
|
4
4
|
if (params && (params.amount > 0 || params.amount < 0)) { // Allow 0 to clear discount if logic permits
|
|
@@ -10,13 +10,20 @@ export const mockAddProductDiscount = async (params) => {
|
|
|
10
10
|
item = MOCK_CART.products[MOCK_CART.products.length - 1];
|
|
11
11
|
}
|
|
12
12
|
if (item) {
|
|
13
|
+
// Mirror render's product handler: it stores `amount` AS-IS — the flow
|
|
14
|
+
// already sends a fraction (0.5 = 50%) for percent and minor units (500 = $5)
|
|
15
|
+
// for fixed. tax.ts then uses value as the fraction / minor amount directly.
|
|
13
16
|
item.discount = {
|
|
14
17
|
value: params.amount,
|
|
15
18
|
isPercent: params.isPercent || false,
|
|
16
19
|
label: params.label
|
|
17
20
|
};
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
const linePrice = (item.price || 0) * (item.quantity || 1);
|
|
22
|
+
const discountMinor = params.isPercent ? Math.round(linePrice * params.amount) : params.amount;
|
|
23
|
+
MOCK_CART.total = Math.max(0, MOCK_CART.total - discountMinor);
|
|
24
|
+
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
25
|
+
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
26
|
+
mockPublishEvent("cart", "product-discount-added", { internalId: params.internalId });
|
|
20
27
|
}
|
|
21
28
|
}
|
|
22
29
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MOCK_CART } from "../../demo/database";
|
|
1
|
+
import { MOCK_CART, mockPublishEvent } from "../../demo/database";
|
|
2
2
|
export const mockAddProductFee = async (params) => {
|
|
3
3
|
console.log("[Mock] addProductFee called", params);
|
|
4
4
|
if (params) {
|
|
@@ -10,12 +10,21 @@ export const mockAddProductFee = async (params) => {
|
|
|
10
10
|
item = MOCK_CART.products[MOCK_CART.products.length - 1];
|
|
11
11
|
}
|
|
12
12
|
if (item) {
|
|
13
|
+
// Mirror render's product handler: it stores `amount` AS-IS — the flow
|
|
14
|
+
// already sends a fraction (0.5 = 50%) for percent and minor units (500 = $5)
|
|
15
|
+
// for fixed. tax.ts then uses amount as the fraction / minor amount directly.
|
|
13
16
|
item.fee = {
|
|
14
17
|
label: params.label || "Fee",
|
|
15
18
|
amount: params.amount,
|
|
16
19
|
isPercent: params.isPercent || false,
|
|
17
20
|
applyTaxes: params.applyTaxes || false
|
|
18
21
|
};
|
|
22
|
+
const linePrice = (item.price || 0) * (item.quantity || 1);
|
|
23
|
+
const feeMinor = params.isPercent ? Math.round(linePrice * params.amount) : params.amount;
|
|
24
|
+
MOCK_CART.total += feeMinor;
|
|
25
|
+
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
26
|
+
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
27
|
+
mockPublishEvent("cart", "product-fee-added", { internalId: params.internalId });
|
|
19
28
|
}
|
|
20
29
|
}
|
|
21
30
|
return {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { applyMockPayment, MOCK_CART } from "../../demo/database";
|
|
2
2
|
export const mockCashPayment = async (params) => {
|
|
3
3
|
console.log("[Mock] cashPayment called", params);
|
|
4
|
-
// Default to true to match action behavior
|
|
4
|
+
// Default to true to match action behavior.
|
|
5
5
|
const openChangeCalculator = params?.openChangeCalculator ?? true;
|
|
6
|
-
|
|
6
|
+
// Amount due for THIS tender (the queued amount-to-be-charged), in minor units.
|
|
7
|
+
const due = params?.amount ?? MOCK_CART.amountToBeCharged ?? MOCK_CART.total;
|
|
7
8
|
if (openChangeCalculator) {
|
|
8
9
|
try {
|
|
9
|
-
const input = window.prompt(`
|
|
10
|
+
const input = window.prompt(`Amount due: $${(due / 100).toFixed(2)}\nEnter amount tendered:`, (due / 100).toFixed(2));
|
|
10
11
|
if (input === null) {
|
|
11
|
-
// User cancelled
|
|
12
12
|
return {
|
|
13
13
|
success: false,
|
|
14
14
|
amount: 0,
|
|
@@ -18,28 +18,22 @@ export const mockCashPayment = async (params) => {
|
|
|
18
18
|
timestamp: new Date().toISOString()
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
-
const tendered = parseFloat(input);
|
|
21
|
+
const tendered = parseFloat(input); // dollars
|
|
22
22
|
if (!isNaN(tendered)) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
window.alert(`Warning: Tendered amount is less than total. Short by: $${Math.abs(change).toFixed(2)}`);
|
|
30
|
-
}
|
|
23
|
+
const change = tendered - due / 100;
|
|
24
|
+
window.alert(change >= 0
|
|
25
|
+
? `Change Due: $${change.toFixed(2)}`
|
|
26
|
+
: `Warning: Tendered is short by: $${Math.abs(change).toFixed(2)}`);
|
|
31
27
|
}
|
|
32
28
|
}
|
|
33
29
|
catch (e) {
|
|
34
30
|
console.warn("Could not open prompt/alert (possibly in non-interactive environment)", e);
|
|
35
31
|
}
|
|
36
32
|
}
|
|
37
|
-
const order =
|
|
38
|
-
// Publish payment-done event
|
|
39
|
-
mockPublishEvent('payments', 'payment-done', { order });
|
|
33
|
+
const order = applyMockPayment(due, "cash", "cash");
|
|
40
34
|
return {
|
|
41
35
|
success: true,
|
|
42
|
-
amount,
|
|
36
|
+
amount: due,
|
|
43
37
|
openChangeCalculator,
|
|
44
38
|
paymentType: "cash",
|
|
45
39
|
order,
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { MOCK_PARKED_ORDERS } from "../../demo/database";
|
|
1
|
+
import { MOCK_PARKED_ORDERS, mockPublishEvent } from "../../demo/database";
|
|
2
2
|
export const mockDeleteParkedOrder = async (params) => {
|
|
3
3
|
console.log("[Mock] deleteParkedOrder called", params);
|
|
4
4
|
if (params?.orderId) {
|
|
5
5
|
const index = MOCK_PARKED_ORDERS.findIndex(o => o._id === params.orderId);
|
|
6
6
|
if (index !== -1) {
|
|
7
7
|
MOCK_PARKED_ORDERS.splice(index, 1);
|
|
8
|
+
// Refresh order lists (the parked-order modal reads getOrders).
|
|
9
|
+
mockPublishEvent("orders", "parked-order-deleted", { orderId: params.orderId });
|
|
8
10
|
}
|
|
9
11
|
}
|
|
10
12
|
return {
|
|
@@ -24,7 +24,7 @@ export const mockGetContext = () => {
|
|
|
24
24
|
thousandSeparator: ",",
|
|
25
25
|
decimalSeparator: ".",
|
|
26
26
|
user: null,
|
|
27
|
-
company:
|
|
27
|
+
company: { _id: MOCK_COMPANY.id, name: MOCK_COMPANY.name, logo: MOCK_COMPANY.logo },
|
|
28
28
|
station: null,
|
|
29
29
|
outlet: null,
|
|
30
30
|
timestamp: new Date().toISOString()
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { MOCK_ORDERS, MOCK_USERS, MOCK_STATIONS, MOCK_OUTLETS, safeSerialize } from "../../demo/database";
|
|
1
|
+
import { MOCK_ORDERS, MOCK_PARKED_ORDERS, MOCK_USERS, MOCK_STATIONS, MOCK_OUTLETS, safeSerialize } from "../../demo/database";
|
|
2
2
|
export const mockGetOrders = async (params) => {
|
|
3
3
|
console.log("[Mock] getOrders called", params);
|
|
4
|
-
// Start with a safe copy of mock orders
|
|
5
|
-
let orders = safeSerialize(MOCK_ORDERS);
|
|
4
|
+
// Start with a safe copy of mock orders, including parked (status: "parked").
|
|
5
|
+
let orders = safeSerialize([...MOCK_ORDERS, ...MOCK_PARKED_ORDERS]);
|
|
6
6
|
// Filter simulation
|
|
7
7
|
if (params) {
|
|
8
8
|
const { customerId, status, sessionId, searchValue, limit, offset, sortBy, sortDirection } = params;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MOCK_PARKED_ORDERS, createOrderFromCart, MOCK_ORDERS } from "../../demo/database";
|
|
1
|
+
import { MOCK_PARKED_ORDERS, createOrderFromCart, MOCK_ORDERS, mockPublishEvent } from "../../demo/database";
|
|
2
2
|
export const mockParkOrder = async () => {
|
|
3
3
|
console.log("[Mock] parkOrder called");
|
|
4
4
|
// Create a temporary order to capture cart state
|
|
@@ -13,6 +13,9 @@ export const mockParkOrder = async () => {
|
|
|
13
13
|
MOCK_ORDERS.splice(foundIndex, 1);
|
|
14
14
|
}
|
|
15
15
|
MOCK_PARKED_ORDERS.push(tempOrder);
|
|
16
|
+
// Refresh order lists so the new parked order appears (createOrderFromCart
|
|
17
|
+
// already published the cart-created event that clears the cart).
|
|
18
|
+
mockPublishEvent("orders", "order-parked", { order: tempOrder });
|
|
16
19
|
return {
|
|
17
20
|
success: true,
|
|
18
21
|
order: tempOrder,
|
|
@@ -1,17 +1,35 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MOCK_CART, mockPublishEvent } from "../../demo/database";
|
|
2
2
|
export const mockPartialPayment = async (params) => {
|
|
3
3
|
console.log("[Mock] partialPayment called", params);
|
|
4
4
|
const openUI = params?.openUI ?? true;
|
|
5
5
|
if (openUI) {
|
|
6
|
-
//
|
|
6
|
+
// Split-payment UI is host-owned; nothing to simulate here.
|
|
7
7
|
window.alert("Demo: Split Payment UI would open here.");
|
|
8
|
+
return {
|
|
9
|
+
success: true,
|
|
10
|
+
amount: params?.amount,
|
|
11
|
+
isPercent: params?.isPercent || false,
|
|
12
|
+
openUI,
|
|
13
|
+
order: null,
|
|
14
|
+
timestamp: new Date().toISOString()
|
|
15
|
+
};
|
|
8
16
|
}
|
|
17
|
+
// Queue a partial amount as the next tender. The remaining balance is left
|
|
18
|
+
// untouched until the payment is actually taken (see applyMockPayment).
|
|
19
|
+
const remaining = MOCK_CART.remainingBalance ?? MOCK_CART.total;
|
|
20
|
+
const raw = params?.amount ?? 0;
|
|
21
|
+
// Mirror render: fixed amount is raw dollars (render does toMinorUnits), so
|
|
22
|
+
// convert to minor units here; percent is a percentage of the remaining total.
|
|
23
|
+
const minorFactor = 10 ** (MOCK_CART.minorUnits ?? 2);
|
|
24
|
+
const charge = params?.isPercent ? Math.round((remaining * raw) / 100) : Math.round(raw * minorFactor);
|
|
25
|
+
MOCK_CART.amountToBeCharged = Math.min(Math.max(0, charge), remaining);
|
|
26
|
+
mockPublishEvent("cart", "partial-payment-set", { amountToBeCharged: MOCK_CART.amountToBeCharged });
|
|
9
27
|
return {
|
|
10
28
|
success: true,
|
|
11
29
|
amount: params?.amount,
|
|
12
30
|
isPercent: params?.isPercent || false,
|
|
13
31
|
openUI,
|
|
14
|
-
order:
|
|
32
|
+
order: null,
|
|
15
33
|
timestamp: new Date().toISOString()
|
|
16
34
|
};
|
|
17
35
|
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { MOCK_CART, mockPublishEvent } from "../../demo/database";
|
|
2
|
+
export const mockRemoveCustomSale = (params) => {
|
|
3
|
+
console.log("[Mock] removeCustomSale called", params);
|
|
4
|
+
if (!params?.id) {
|
|
5
|
+
throw new Error("id is required");
|
|
6
|
+
}
|
|
7
|
+
const { id } = params;
|
|
8
|
+
const sales = MOCK_CART.customSales ?? [];
|
|
9
|
+
const index = sales.findIndex(s => s.id === id);
|
|
10
|
+
if (index === -1) {
|
|
11
|
+
throw new Error(`Custom sale with id ${id} not found`);
|
|
12
|
+
}
|
|
13
|
+
const sale = sales[index];
|
|
14
|
+
// Remove from cart
|
|
15
|
+
sales.splice(index, 1);
|
|
16
|
+
// Recalculate totals
|
|
17
|
+
const lineTotal = sale.price * sale.quantity;
|
|
18
|
+
MOCK_CART.subtotal -= lineTotal;
|
|
19
|
+
MOCK_CART.total -= lineTotal;
|
|
20
|
+
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
21
|
+
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
22
|
+
// Publish custom-sale-removed event so cart subscribers refresh
|
|
23
|
+
mockPublishEvent("cart", "custom-sale-removed", { customSale: sale, id });
|
|
24
|
+
return Promise.resolve({
|
|
25
|
+
success: true,
|
|
26
|
+
id,
|
|
27
|
+
timestamp: new Date().toISOString()
|
|
28
|
+
});
|
|
29
|
+
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { MOCK_CART } from "../../demo/database";
|
|
1
|
+
import { MOCK_CART, mockPublishEvent } from "../../demo/database";
|
|
2
2
|
export const mockRemoveCustomerFromCart = async () => {
|
|
3
3
|
console.log("[Mock] removeCustomerFromCart called");
|
|
4
4
|
// Actually remove the customer from the mock cart
|
|
5
5
|
MOCK_CART.customer = null;
|
|
6
|
+
// Publish customer-removed event so cart subscribers refresh
|
|
7
|
+
mockPublishEvent('cart', 'customer-removed', {});
|
|
6
8
|
return {
|
|
7
9
|
success: true,
|
|
8
10
|
timestamp: new Date().toISOString()
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { MOCK_CART, mockPublishEvent } from "../../demo/database";
|
|
2
|
+
export const mockRemoveOrderNote = () => {
|
|
3
|
+
console.log("[Mock] removeOrderNote called");
|
|
4
|
+
// Clear the active cart's note.
|
|
5
|
+
MOCK_CART.orderNotes = undefined;
|
|
6
|
+
// Publish order-note-removed event so cart subscribers refresh.
|
|
7
|
+
mockPublishEvent("cart", "order-note-removed", {});
|
|
8
|
+
return Promise.resolve({
|
|
9
|
+
success: true,
|
|
10
|
+
timestamp: new Date().toISOString()
|
|
11
|
+
});
|
|
12
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { MOCK_CART, mockPublishEvent } from "../../demo/database";
|
|
2
|
+
export const mockRemoveProductDiscount = (params) => {
|
|
3
|
+
console.log("[Mock] removeProductDiscount called", params);
|
|
4
|
+
const item = params?.internalId
|
|
5
|
+
? MOCK_CART.products.find(p => p.internalId === params.internalId)
|
|
6
|
+
: MOCK_CART.products[MOCK_CART.products.length - 1];
|
|
7
|
+
if (item) {
|
|
8
|
+
delete item.discount;
|
|
9
|
+
// Publish so cart subscribers refresh.
|
|
10
|
+
mockPublishEvent("cart", "product-discount-removed", { internalId: params?.internalId });
|
|
11
|
+
}
|
|
12
|
+
return Promise.resolve({
|
|
13
|
+
success: true,
|
|
14
|
+
internalId: params?.internalId,
|
|
15
|
+
timestamp: new Date().toISOString()
|
|
16
|
+
});
|
|
17
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { MOCK_CART, mockPublishEvent } from "../../demo/database";
|
|
2
|
+
export const mockRemoveProductFee = (params) => {
|
|
3
|
+
console.log("[Mock] removeProductFee called", params);
|
|
4
|
+
const item = params?.internalId
|
|
5
|
+
? MOCK_CART.products.find(p => p.internalId === params.internalId)
|
|
6
|
+
: MOCK_CART.products[MOCK_CART.products.length - 1];
|
|
7
|
+
if (item) {
|
|
8
|
+
delete item.fee;
|
|
9
|
+
// Publish so cart subscribers refresh.
|
|
10
|
+
mockPublishEvent("cart", "product-fee-removed", { internalId: params?.internalId });
|
|
11
|
+
}
|
|
12
|
+
return Promise.resolve({
|
|
13
|
+
success: true,
|
|
14
|
+
internalId: params?.internalId,
|
|
15
|
+
timestamp: new Date().toISOString()
|
|
16
|
+
});
|
|
17
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MOCK_PARKED_ORDERS, MOCK_CART, resetMockCart } from "../../demo/database";
|
|
1
|
+
import { MOCK_PARKED_ORDERS, MOCK_CART, resetMockCart, mockPublishEvent } from "../../demo/database";
|
|
2
2
|
export const mockResumeParkedOrder = async (params) => {
|
|
3
3
|
console.log("[Mock] resumeParkedOrder called", params);
|
|
4
4
|
const orderId = params?.orderId;
|
|
@@ -45,6 +45,9 @@ export const mockResumeParkedOrder = async (params) => {
|
|
|
45
45
|
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
46
46
|
// Remove from parked
|
|
47
47
|
MOCK_PARKED_ORDERS.splice(index, 1);
|
|
48
|
+
// Refresh the restored cart and the order lists.
|
|
49
|
+
mockPublishEvent("cart", "parked-order-resumed", { orderId });
|
|
50
|
+
mockPublishEvent("orders", "parked-order-resumed", { orderId });
|
|
48
51
|
return {
|
|
49
52
|
success: true,
|
|
50
53
|
order: orderToResume,
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { applyMockPayment, MOCK_CART } from "../../demo/database";
|
|
2
2
|
export const mockTapToPayPayment = async (params) => {
|
|
3
3
|
console.log("[Mock] tapToPayPayment called", params);
|
|
4
4
|
// Simulate Tap to Pay interaction
|
|
5
5
|
window.alert("Demo: Processing Tap to Pay...\n(Please tap card or device on screen)");
|
|
6
|
+
const due = params?.amount ?? MOCK_CART.amountToBeCharged ?? MOCK_CART.total;
|
|
7
|
+
const order = applyMockPayment(due, "card", "tapToPay");
|
|
6
8
|
return {
|
|
7
9
|
success: true,
|
|
8
|
-
amount:
|
|
10
|
+
amount: due,
|
|
9
11
|
paymentType: "tapToPay",
|
|
10
|
-
order
|
|
12
|
+
order,
|
|
11
13
|
timestamp: new Date().toISOString()
|
|
12
14
|
};
|
|
13
15
|
};
|
|
@@ -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()
|
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`;
|
|
@@ -427,6 +427,140 @@ export const MOCK_ORDER_2 = {
|
|
|
427
427
|
station: MOCK_STATION_2,
|
|
428
428
|
createdAt: new Date(Date.now() - 3600000).toISOString()
|
|
429
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
|
+
};
|
|
430
564
|
// --- EXPORT COLLECTIONS ---
|
|
431
565
|
export const MOCK_USERS = [MOCK_USER_MARIO, MOCK_USER_LUIGI];
|
|
432
566
|
export const MOCK_STATIONS = [MOCK_STATION_1, MOCK_STATION_2];
|
|
@@ -449,8 +583,8 @@ export const MOCK_PRODUCTS = [
|
|
|
449
583
|
MOCK_PRODUCT_HABANERO,
|
|
450
584
|
MOCK_PRODUCT_BLACK_GARLIC
|
|
451
585
|
];
|
|
452
|
-
export const MOCK_ORDERS = [MOCK_ORDER_1, MOCK_ORDER_2];
|
|
453
|
-
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];
|
|
454
588
|
// Compatibility Exports (reassigned by setMockDatabase)
|
|
455
589
|
export let MOCK_USER = MOCK_USERS[0];
|
|
456
590
|
export let MOCK_STATION = MOCK_STATIONS[0];
|
|
@@ -661,3 +795,26 @@ export const createOrderFromCart = (paymentType, amount, processor = "cash") =>
|
|
|
661
795
|
mockPublishEvent("cart", "cart-created", {});
|
|
662
796
|
return newOrder;
|
|
663
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
|
+
};
|
|
@@ -2,13 +2,17 @@ import { mockAddCartDiscount } from "../../actions/add-cart-discount/mock";
|
|
|
2
2
|
import { mockAddCartFee } from "../../actions/add-cart-fee/mock";
|
|
3
3
|
import { mockRemoveCartFee } from "../../actions/remove-cart-fee/mock";
|
|
4
4
|
import { mockAddCustomSale } from "../../actions/add-custom-sale/mock";
|
|
5
|
+
import { mockRemoveCustomSale } from "../../actions/remove-custom-sale/mock";
|
|
5
6
|
import { mockAddCustomer } from "../../actions/add-customer/mock";
|
|
6
7
|
import { mockAddCustomerNote } from "../../actions/add-customer-note/mock";
|
|
7
8
|
import { mockRemoveCustomerNote } from "../../actions/remove-customer-note/mock";
|
|
8
9
|
import { mockEditCustomer } from "../../actions/edit-customer/mock";
|
|
9
10
|
import { mockAddOrderNote } from "../../actions/add-order-note/mock";
|
|
11
|
+
import { mockRemoveOrderNote } from "../../actions/remove-order-note/mock";
|
|
10
12
|
import { mockAddProductDiscount } from "../../actions/add-product-discount/mock";
|
|
11
13
|
import { mockAddProductFee } from "../../actions/add-product-fee/mock";
|
|
14
|
+
import { mockRemoveProductDiscount } from "../../actions/remove-product-discount/mock";
|
|
15
|
+
import { mockRemoveProductFee } from "../../actions/remove-product-fee/mock";
|
|
12
16
|
import { mockSetActiveProductFee } from "../../actions/set-active-product-fee/mock";
|
|
13
17
|
import { mockSetActiveProductDiscount } from "../../actions/set-active-product-discount/mock";
|
|
14
18
|
import { mockGetActiveProduct } from "../../actions/get-active-product/mock";
|
|
@@ -182,12 +186,12 @@ export const RENDER_MOCKS = {
|
|
|
182
186
|
getActiveUser: mockGetActiveUser,
|
|
183
187
|
setActiveUser: mockSetActiveUser,
|
|
184
188
|
setActiveRefund: mockSetActiveRefund,
|
|
185
|
-
removeProductDiscount:
|
|
186
|
-
removeProductFee:
|
|
189
|
+
removeProductDiscount: mockRemoveProductDiscount,
|
|
190
|
+
removeProductFee: mockRemoveProductFee,
|
|
187
191
|
removeProductNote: () => Promise.resolve({ success: true, timestamp: new Date().toISOString() }),
|
|
188
192
|
removeCartFee: mockRemoveCartFee,
|
|
189
|
-
removeOrderNote:
|
|
190
|
-
removeCustomSale:
|
|
193
|
+
removeOrderNote: mockRemoveOrderNote,
|
|
194
|
+
removeCustomSale: mockRemoveCustomSale,
|
|
191
195
|
removeNonRevenueItem: params => Promise.resolve({ success: true, externalId: params.externalId, timestamp: new Date().toISOString() }),
|
|
192
196
|
canTransition: canTransitionMock,
|
|
193
197
|
getAvailableTransitions: getAvailableTransitionsMock,
|