@final-commerce/command-frame 0.5.1 → 0.6.0-staging.4
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 +0 -2
- package/dist/CommonTypes.d.ts +6 -6
- package/dist/CommonTypes.js +2 -2
- package/dist/actions/add-cart-discount/mock.d.ts +1 -1
- package/dist/actions/add-cart-discount/mock.js +8 -8
- package/dist/actions/add-cart-fee/mock.d.ts +1 -1
- package/dist/actions/add-cart-fee/mock.js +8 -8
- package/dist/actions/add-product-to-cart/mock.d.ts +1 -1
- package/dist/actions/add-product-to-cart/mock.js +24 -10
- package/dist/actions/add-product-to-cart/types.d.ts +13 -1
- package/dist/actions/adjust-inventory/mock.d.ts +1 -1
- package/dist/actions/adjust-inventory/mock.js +6 -6
- package/dist/actions/apply-transition/mock.d.ts +1 -1
- package/dist/actions/apply-transition/mock.js +8 -8
- package/dist/actions/apply-transition/types.d.ts +1 -1
- package/dist/actions/authenticate-user/mock.d.ts +1 -1
- package/dist/actions/authenticate-user/mock.js +3 -3
- package/dist/actions/calculate-refund-total/action.d.ts +1 -1
- package/dist/actions/calculate-refund-total/action.js +2 -2
- package/dist/actions/can-transition/types.d.ts +1 -1
- package/dist/actions/cash-payment/mock.d.ts +1 -1
- package/dist/actions/cash-payment/mock.js +10 -10
- package/dist/actions/cash-payment/types.d.ts +1 -1
- package/dist/actions/extension-payment/mock.d.ts +1 -1
- package/dist/actions/extension-payment/mock.js +3 -3
- package/dist/actions/extension-payment/types.d.ts +1 -1
- package/dist/actions/get-available-transitions/mock.d.ts +2 -7
- package/dist/actions/get-available-transitions/mock.js +9 -9
- package/dist/actions/get-final-context/mock.d.ts +1 -1
- package/dist/actions/get-final-context/mock.js +2 -2
- package/dist/actions/get-products/mock.d.ts +1 -1
- package/dist/actions/get-products/mock.js +26 -9
- package/dist/actions/get-refunds/types.d.ts +1 -1
- package/dist/actions/get-remaining-refundable-quantities/action.d.ts +1 -1
- package/dist/actions/get-remaining-refundable-quantities/action.js +2 -2
- package/dist/actions/get-remaining-refundable-quantities/mock.d.ts +1 -1
- package/dist/actions/get-remaining-refundable-quantities/mock.js +2 -2
- package/dist/actions/integration-payment/types.d.ts +1 -1
- package/dist/actions/park-order/types.d.ts +1 -1
- package/dist/actions/partial-payment/mock.d.ts +1 -1
- package/dist/actions/partial-payment/mock.js +8 -8
- package/dist/actions/partial-payment/types.d.ts +1 -1
- package/dist/actions/print/mock.d.ts +1 -1
- package/dist/actions/print/mock.js +9 -9
- package/dist/actions/print/types.d.ts +6 -6
- package/dist/actions/redeem-payment/types.d.ts +1 -1
- package/dist/actions/remove-cart-fee/mock.d.ts +1 -1
- package/dist/actions/remove-cart-fee/mock.js +7 -7
- package/dist/actions/remove-product-from-cart/mock.d.ts +1 -1
- package/dist/actions/remove-product-from-cart/mock.js +11 -8
- package/dist/actions/resume-parked-order/types.d.ts +1 -1
- package/dist/actions/select-all-refund-items/action.d.ts +1 -1
- package/dist/actions/select-all-refund-items/action.js +2 -2
- package/dist/actions/set-active-product/mock.d.ts +1 -1
- package/dist/actions/set-active-product/mock.js +19 -14
- package/dist/actions/set-active-refund/types.d.ts +1 -1
- package/dist/actions/tap-to-pay-payment/mock.d.ts +1 -1
- package/dist/actions/tap-to-pay-payment/mock.js +6 -6
- package/dist/actions/tap-to-pay-payment/types.d.ts +1 -1
- package/dist/actions/terminal-payment/mock.d.ts +1 -1
- package/dist/actions/terminal-payment/mock.js +6 -6
- package/dist/actions/terminal-payment/types.d.ts +2 -2
- package/dist/actions/update-cart-item-quantity/mock.d.ts +1 -1
- package/dist/actions/update-cart-item-quantity/mock.js +23 -15
- package/dist/actions/update-cart-item-quantity/types.d.ts +8 -1
- package/dist/actions/upsert-custom-table-data/mock.d.ts +1 -1
- package/dist/actions/upsert-custom-table-data/mock.js +3 -3
- package/dist/demo/database.js +30 -4
- package/package.json +2 -2
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
* Get remaining refundable quantities action
|
|
3
3
|
* Calls the getRemainingRefundableQuantities action on the parent window
|
|
4
4
|
*/
|
|
5
|
-
import type { GetRemainingRefundableQuantities } from
|
|
5
|
+
import type { GetRemainingRefundableQuantities } from './types';
|
|
6
6
|
export declare const getRemainingRefundableQuantities: GetRemainingRefundableQuantities;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Get remaining refundable quantities action
|
|
3
3
|
* Calls the getRemainingRefundableQuantities action on the parent window
|
|
4
4
|
*/
|
|
5
|
-
import { commandFrameClient } from
|
|
5
|
+
import { commandFrameClient } from '../../client';
|
|
6
6
|
export const getRemainingRefundableQuantities = async (params) => {
|
|
7
|
-
return await commandFrameClient.call(
|
|
7
|
+
return await commandFrameClient.call('getRemainingRefundableQuantities', params);
|
|
8
8
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { GetRemainingRefundableQuantities } from
|
|
1
|
+
import { GetRemainingRefundableQuantities } from './types';
|
|
2
2
|
export declare const mockGetRemainingRefundableQuantities: GetRemainingRefundableQuantities;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export const mockGetRemainingRefundableQuantities = async (_params) => {
|
|
2
|
-
console.log(
|
|
2
|
+
console.log('[Mock] getRemainingRefundableQuantities called', _params);
|
|
3
3
|
return {
|
|
4
4
|
success: true,
|
|
5
5
|
lineItems: {},
|
|
6
6
|
customSales: {},
|
|
7
7
|
cartFees: {},
|
|
8
8
|
tips: {},
|
|
9
|
-
timestamp: new Date().toISOString()
|
|
9
|
+
timestamp: new Date().toISOString(),
|
|
10
10
|
};
|
|
11
11
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { PartialPayment } from
|
|
1
|
+
import { PartialPayment } from './types';
|
|
2
2
|
export declare const mockPartialPayment: PartialPayment;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { MOCK_CART, mockPublishEvent } from
|
|
2
|
-
import { percentToFraction, requireMinorUnitsInteger } from
|
|
1
|
+
import { MOCK_CART, mockPublishEvent } from '../../demo/database';
|
|
2
|
+
import { percentToFraction, requireMinorUnitsInteger } from '../../demo/units';
|
|
3
3
|
export const mockPartialPayment = async (params) => {
|
|
4
|
-
console.log(
|
|
4
|
+
console.log('[Mock] partialPayment called', params);
|
|
5
5
|
const openUI = params?.openUI ?? true;
|
|
6
6
|
if (openUI) {
|
|
7
7
|
// Split-payment UI is host-owned; nothing to simulate here.
|
|
8
|
-
window.alert(
|
|
8
|
+
window.alert('Demo: Split Payment UI would open here.');
|
|
9
9
|
return {
|
|
10
10
|
success: true,
|
|
11
11
|
amount: params?.amount,
|
|
12
12
|
isPercent: params?.isPercent || false,
|
|
13
13
|
openUI,
|
|
14
14
|
order: null,
|
|
15
|
-
timestamp: new Date().toISOString()
|
|
15
|
+
timestamp: new Date().toISOString(),
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
18
|
// Queue a partial amount as the next tender. The remaining balance is left
|
|
@@ -23,15 +23,15 @@ export const mockPartialPayment = async (params) => {
|
|
|
23
23
|
// directly; a percent is raw 0-100 against the remaining total.
|
|
24
24
|
const charge = params?.isPercent
|
|
25
25
|
? Math.round(remaining * percentToFraction(raw))
|
|
26
|
-
: requireMinorUnitsInteger(raw,
|
|
26
|
+
: requireMinorUnitsInteger(raw, 'Payment amount');
|
|
27
27
|
MOCK_CART.amountToBeCharged = Math.min(Math.max(0, charge), remaining);
|
|
28
|
-
mockPublishEvent(
|
|
28
|
+
mockPublishEvent('cart', 'partial-payment-set', { amountToBeCharged: MOCK_CART.amountToBeCharged });
|
|
29
29
|
return {
|
|
30
30
|
success: true,
|
|
31
31
|
amount: params?.amount,
|
|
32
32
|
isPercent: params?.isPercent || false,
|
|
33
33
|
openUI,
|
|
34
34
|
order: null,
|
|
35
|
-
timestamp: new Date().toISOString()
|
|
35
|
+
timestamp: new Date().toISOString(),
|
|
36
36
|
};
|
|
37
37
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CFOrder } from
|
|
1
|
+
import { CFOrder } from '../../CommonTypes';
|
|
2
2
|
export interface PartialPaymentParams {
|
|
3
3
|
/** The payment amount in integer MINOR currency units (required if openUI is false). If isPercent is true, this is a percentage (0-100) instead. */
|
|
4
4
|
amount?: number;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Print } from
|
|
1
|
+
import { Print } from './types';
|
|
2
2
|
export declare const mockPrint: Print;
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
export const mockPrint = (params) => {
|
|
2
|
-
console.log(
|
|
2
|
+
console.log('[Mock] print called', params);
|
|
3
3
|
if (!params) {
|
|
4
|
-
throw new Error(
|
|
4
|
+
throw new Error('Print parameters are required');
|
|
5
5
|
}
|
|
6
6
|
// Mock implementation - just log what would be printed
|
|
7
7
|
switch (params.type) {
|
|
8
|
-
case
|
|
9
|
-
console.log(
|
|
8
|
+
case 'image':
|
|
9
|
+
console.log('[Mock] Would print image:', params.data.image?.substring(0, 50) + '...');
|
|
10
10
|
break;
|
|
11
|
-
case
|
|
11
|
+
case 'html':
|
|
12
12
|
console.warn("[Mock] print type 'html' is DEPRECATED — rasterize and use type: 'image'.");
|
|
13
|
-
console.log(
|
|
13
|
+
console.log('[Mock] Would print HTML:', params.data.html?.substring(0, 100) + '...');
|
|
14
14
|
break;
|
|
15
|
-
case
|
|
15
|
+
case 'receipt':
|
|
16
16
|
console.warn("[Mock] print type 'receipt' is DEPRECATED — rasterize and use type: 'image'.");
|
|
17
|
-
console.log(
|
|
17
|
+
console.log('[Mock] Would print receipt for order:', params.data.order);
|
|
18
18
|
break;
|
|
19
19
|
}
|
|
20
20
|
return Promise.resolve({
|
|
21
21
|
success: true,
|
|
22
22
|
timestamp: new Date().toISOString(),
|
|
23
|
-
type: params.type
|
|
23
|
+
type: params.type,
|
|
24
24
|
});
|
|
25
25
|
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import type { CFActiveOrder } from
|
|
2
|
-
export type PrintType =
|
|
1
|
+
import type { CFActiveOrder } from '../../CommonTypes';
|
|
2
|
+
export type PrintType = 'image' | 'html' | 'receipt';
|
|
3
3
|
export type PrintParams = {
|
|
4
|
-
type:
|
|
4
|
+
type: 'image';
|
|
5
5
|
data: {
|
|
6
6
|
image: string;
|
|
7
7
|
};
|
|
8
8
|
options?: PrintOptions;
|
|
9
9
|
} | {
|
|
10
10
|
/** @deprecated Rasterize your HTML and use `type: "image"`. The native path posts raw HTML to the shell (no html2canvas/sanitization) and PrintOptions may be dropped. */
|
|
11
|
-
type:
|
|
11
|
+
type: 'html';
|
|
12
12
|
data: {
|
|
13
13
|
html: string;
|
|
14
14
|
};
|
|
@@ -19,9 +19,9 @@ export type PrintParams = {
|
|
|
19
19
|
* The station requires `order` (no active-order fallback), ignores
|
|
20
20
|
* `globalBlockId`, and drops ALL PrintOptions (including tag routing).
|
|
21
21
|
*/
|
|
22
|
-
type:
|
|
22
|
+
type: 'receipt';
|
|
23
23
|
data: {
|
|
24
|
-
order?: Omit<CFActiveOrder,
|
|
24
|
+
order?: Omit<CFActiveOrder, '_id'>;
|
|
25
25
|
globalBlockId?: string;
|
|
26
26
|
};
|
|
27
27
|
options?: PrintOptions;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExtensionPaymentResponse } from
|
|
1
|
+
import type { ExtensionPaymentResponse } from '../extension-payment/types';
|
|
2
2
|
/**
|
|
3
3
|
* Redeem (e.g. gift card) — always uses paymentType `"redeem"` on the wire.
|
|
4
4
|
* `amount` is required so the persisted payment never silently falls back to the cart
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { RemoveCartFee } from
|
|
1
|
+
import type { RemoveCartFee } from './types';
|
|
2
2
|
export declare const mockRemoveCartFee: RemoveCartFee;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MOCK_CART, mockPublishEvent } from
|
|
1
|
+
import { MOCK_CART, mockPublishEvent } from '../../demo/database';
|
|
2
2
|
function feeContributionToTotal(fee, subtotal) {
|
|
3
3
|
// A percent fee is STORED as a fraction (10% -> 0.1), so it scales the
|
|
4
4
|
// subtotal directly. Dividing by 100 again credited back a hundredth of the
|
|
@@ -9,14 +9,14 @@ function feeContributionToTotal(fee, subtotal) {
|
|
|
9
9
|
return fee.amount;
|
|
10
10
|
}
|
|
11
11
|
export const mockRemoveCartFee = (params) => {
|
|
12
|
-
console.log(
|
|
12
|
+
console.log('[Mock] removeCartFee called', params);
|
|
13
13
|
const { index } = params;
|
|
14
|
-
if (typeof index !==
|
|
15
|
-
throw new Error(
|
|
14
|
+
if (typeof index !== 'number' || !Number.isInteger(index) || index < 0) {
|
|
15
|
+
throw new Error('removeCartFee requires a non-negative integer index');
|
|
16
16
|
}
|
|
17
17
|
const fees = MOCK_CART.customFee;
|
|
18
18
|
if (!fees?.length) {
|
|
19
|
-
throw new Error(
|
|
19
|
+
throw new Error('Cart has no fees to remove');
|
|
20
20
|
}
|
|
21
21
|
if (index >= fees.length) {
|
|
22
22
|
throw new Error(`Cart fee index ${index} is out of range (0–${fees.length - 1})`);
|
|
@@ -30,9 +30,9 @@ export const mockRemoveCartFee = (params) => {
|
|
|
30
30
|
MOCK_CART.total -= delta;
|
|
31
31
|
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
32
32
|
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
33
|
-
mockPublishEvent(
|
|
33
|
+
mockPublishEvent('cart', 'cart-fee-removed', { feeIndex: index });
|
|
34
34
|
return Promise.resolve({
|
|
35
35
|
success: true,
|
|
36
|
-
timestamp: new Date().toISOString()
|
|
36
|
+
timestamp: new Date().toISOString(),
|
|
37
37
|
});
|
|
38
38
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { RemoveProductFromCart } from
|
|
1
|
+
import { RemoveProductFromCart } from './types';
|
|
2
2
|
export declare const mockRemoveProductFromCart: RemoveProductFromCart;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { MOCK_CART, mockPublishEvent } from
|
|
1
|
+
import { MOCK_CART, mockPublishEvent } from '../../demo/database';
|
|
2
|
+
import { extendPrice } from '@final-commerce/common';
|
|
2
3
|
export const mockRemoveProductFromCart = (params) => {
|
|
3
|
-
console.log(
|
|
4
|
+
console.log('[Mock] removeProductFromCart called', params);
|
|
4
5
|
if (!params?.internalId) {
|
|
5
|
-
throw new Error(
|
|
6
|
+
throw new Error('internalId is required');
|
|
6
7
|
}
|
|
7
8
|
const { internalId } = params;
|
|
8
9
|
// Find the product in the cart
|
|
9
|
-
const productIndex = MOCK_CART.products.findIndex(p => p.internalId === internalId);
|
|
10
|
+
const productIndex = MOCK_CART.products.findIndex((p) => p.internalId === internalId);
|
|
10
11
|
if (productIndex === -1) {
|
|
11
12
|
throw new Error(`Cart item with internalId ${internalId} not found`);
|
|
12
13
|
}
|
|
@@ -14,19 +15,21 @@ export const mockRemoveProductFromCart = (params) => {
|
|
|
14
15
|
// Remove from cart
|
|
15
16
|
MOCK_CART.products.splice(productIndex, 1);
|
|
16
17
|
// Recalculate totals
|
|
17
|
-
|
|
18
|
+
// The same rounded extension the add path put on: subtracting a raw multiply from a
|
|
19
|
+
// weighed line would leave the cent extendPrice rounded away stuck in the cart total.
|
|
20
|
+
const lineTotal = extendPrice(product.price, product.quantity);
|
|
18
21
|
MOCK_CART.subtotal -= lineTotal;
|
|
19
22
|
MOCK_CART.total -= lineTotal;
|
|
20
23
|
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
21
24
|
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
22
25
|
// Publish product-deleted event
|
|
23
|
-
mockPublishEvent(
|
|
26
|
+
mockPublishEvent('cart', 'product-deleted', {
|
|
24
27
|
product: product,
|
|
25
|
-
internalId: internalId
|
|
28
|
+
internalId: internalId,
|
|
26
29
|
});
|
|
27
30
|
return Promise.resolve({
|
|
28
31
|
success: true,
|
|
29
32
|
internalId: internalId,
|
|
30
|
-
timestamp: new Date().toISOString()
|
|
33
|
+
timestamp: new Date().toISOString(),
|
|
31
34
|
});
|
|
32
35
|
};
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
* Select all refund items action
|
|
3
3
|
* Calls the selectAllRefundItems action on the parent window
|
|
4
4
|
*/
|
|
5
|
-
import type { SelectAllRefundItems } from
|
|
5
|
+
import type { SelectAllRefundItems } from './types';
|
|
6
6
|
export declare const selectAllRefundItems: SelectAllRefundItems;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Select all refund items action
|
|
3
3
|
* Calls the selectAllRefundItems action on the parent window
|
|
4
4
|
*/
|
|
5
|
-
import { commandFrameClient } from
|
|
5
|
+
import { commandFrameClient } from '../../client';
|
|
6
6
|
export const selectAllRefundItems = async (params) => {
|
|
7
|
-
return await commandFrameClient.call(
|
|
7
|
+
return await commandFrameClient.call('selectAllRefundItems', params);
|
|
8
8
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { SetActiveProduct } from
|
|
1
|
+
import type { SetActiveProduct } from './types';
|
|
2
2
|
export declare const mockSetActiveProduct: SetActiveProduct;
|
|
@@ -1,47 +1,52 @@
|
|
|
1
|
-
import { MOCK_PRODUCTS, setMockActiveProduct } from
|
|
1
|
+
import { MOCK_PRODUCTS, setMockActiveProduct } from '../../demo/database';
|
|
2
|
+
import { resolveUnit } from '@final-commerce/common';
|
|
2
3
|
export const mockSetActiveProduct = async (params) => {
|
|
3
|
-
console.log(
|
|
4
|
+
console.log('[Mock] setActiveProduct called', params);
|
|
4
5
|
if (!params?.variantId) {
|
|
5
|
-
throw new Error(
|
|
6
|
+
throw new Error('Variant ID is required');
|
|
6
7
|
}
|
|
7
8
|
const { variantId } = params;
|
|
8
9
|
let matchedProduct;
|
|
9
10
|
let matchedVariant;
|
|
10
11
|
for (const product of MOCK_PRODUCTS) {
|
|
11
|
-
const variant = product.variants.find(v => v._id === variantId);
|
|
12
|
+
const variant = product.variants.find((v) => v._id === variantId);
|
|
12
13
|
if (variant) {
|
|
13
14
|
matchedProduct = product;
|
|
14
15
|
matchedVariant = variant;
|
|
15
16
|
break;
|
|
16
17
|
}
|
|
17
18
|
}
|
|
19
|
+
// The unit the variant sells in, resolved exactly as the add-to-cart mock does — the
|
|
20
|
+
// product card reads the ACTIVE product, and without this it cannot label "100" as kg.
|
|
21
|
+
const unit = matchedVariant?.unitId ? resolveUnit(matchedVariant.unitId) : undefined;
|
|
18
22
|
const activeProduct = {
|
|
19
|
-
id: matchedProduct?._id ||
|
|
23
|
+
id: matchedProduct?._id || 'mock_product',
|
|
20
24
|
internalId: `internal_${Date.now()}`,
|
|
21
|
-
externalId: matchedVariant?.externalId ||
|
|
22
|
-
productExternalId: matchedProduct?.externalId ||
|
|
25
|
+
externalId: matchedVariant?.externalId || 'mock_external_id',
|
|
26
|
+
productExternalId: matchedProduct?.externalId || 'mock_product_external_id',
|
|
23
27
|
variantId: matchedVariant?._id || variantId,
|
|
24
|
-
name: matchedProduct?.name ||
|
|
25
|
-
sku: matchedVariant?.sku ||
|
|
28
|
+
name: matchedProduct?.name || 'Mock Product',
|
|
29
|
+
sku: matchedVariant?.sku || 'mock_sku',
|
|
26
30
|
price: matchedVariant?.price || 100,
|
|
27
31
|
images: matchedVariant?.images || matchedProduct?.images || [],
|
|
28
|
-
taxTableId: matchedProduct?.taxTable ||
|
|
32
|
+
taxTableId: matchedProduct?.taxTable || 'mock_tax_table_id',
|
|
29
33
|
quantity: 1,
|
|
30
34
|
note: undefined,
|
|
31
35
|
discount: undefined,
|
|
32
|
-
description: matchedProduct?.description ||
|
|
33
|
-
barcodeId: matchedVariant?.barcode ||
|
|
36
|
+
description: matchedProduct?.description || 'Mock Description',
|
|
37
|
+
barcodeId: matchedVariant?.barcode || 'mock_barcode_id',
|
|
34
38
|
stock: matchedVariant?.inventory?.[0]?.stock ?? 100,
|
|
39
|
+
...(unit ? { unit } : {}),
|
|
35
40
|
allowBackOrder: matchedVariant?.allowBackorder || false,
|
|
36
41
|
fee: undefined,
|
|
37
42
|
isUnlimited: !matchedVariant?.manageStock,
|
|
38
|
-
attributes: matchedVariant?.attributes?.map(a => a.value).join(
|
|
43
|
+
attributes: matchedVariant?.attributes?.map((a) => a.value).join(', ') || '',
|
|
39
44
|
localQuantity: 1,
|
|
40
45
|
};
|
|
41
46
|
setMockActiveProduct(activeProduct);
|
|
42
47
|
return {
|
|
43
48
|
success: true,
|
|
44
49
|
product: activeProduct,
|
|
45
|
-
timestamp: new Date().toISOString()
|
|
50
|
+
timestamp: new Date().toISOString(),
|
|
46
51
|
};
|
|
47
52
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { TapToPayPayment } from
|
|
1
|
+
import { TapToPayPayment } from './types';
|
|
2
2
|
export declare const mockTapToPayPayment: TapToPayPayment;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { applyMockPayment, MOCK_CART } from
|
|
1
|
+
import { applyMockPayment, MOCK_CART } from '../../demo/database';
|
|
2
2
|
export const mockTapToPayPayment = async (params) => {
|
|
3
|
-
console.log(
|
|
3
|
+
console.log('[Mock] tapToPayPayment called', params);
|
|
4
4
|
// Simulate Tap to Pay interaction
|
|
5
|
-
window.alert(
|
|
5
|
+
window.alert('Demo: Processing Tap to Pay...\n(Please tap card or device on screen)');
|
|
6
6
|
const due = params?.amount ?? MOCK_CART.amountToBeCharged ?? MOCK_CART.total;
|
|
7
|
-
const order = applyMockPayment(due,
|
|
7
|
+
const order = applyMockPayment(due, 'card', 'tapToPay');
|
|
8
8
|
return {
|
|
9
9
|
success: true,
|
|
10
10
|
amount: due,
|
|
11
|
-
paymentType:
|
|
11
|
+
paymentType: 'tapToPay',
|
|
12
12
|
order,
|
|
13
13
|
timestamp: new Date().toISOString(),
|
|
14
14
|
change: 0,
|
|
15
15
|
cashRounding: 0,
|
|
16
16
|
saleFinalized: true,
|
|
17
|
-
remainingBalance: 0
|
|
17
|
+
remainingBalance: 0,
|
|
18
18
|
};
|
|
19
19
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { TerminalPayment } from
|
|
1
|
+
import { TerminalPayment } from './types';
|
|
2
2
|
export declare const mockTerminalPayment: TerminalPayment;
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { applyMockPayment, MOCK_CART } from
|
|
1
|
+
import { applyMockPayment, MOCK_CART } from '../../demo/database';
|
|
2
2
|
export const mockTerminalPayment = async (params) => {
|
|
3
|
-
console.log(
|
|
4
|
-
const connectionType = params?.paymentType ||
|
|
3
|
+
console.log('[Mock] terminalPayment called', params);
|
|
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
7
|
const due = params?.amount ?? MOCK_CART.amountToBeCharged ?? MOCK_CART.total;
|
|
8
|
-
const order = applyMockPayment(due,
|
|
8
|
+
const order = applyMockPayment(due, 'card', 'stripe_terminal');
|
|
9
9
|
return {
|
|
10
10
|
success: true,
|
|
11
11
|
amount: due,
|
|
12
|
-
paymentType:
|
|
12
|
+
paymentType: 'terminal',
|
|
13
13
|
order,
|
|
14
14
|
timestamp: new Date().toISOString(),
|
|
15
15
|
change: 0,
|
|
16
16
|
cashRounding: 0,
|
|
17
17
|
saleFinalized: true,
|
|
18
|
-
remainingBalance: 0
|
|
18
|
+
remainingBalance: 0,
|
|
19
19
|
};
|
|
20
20
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CFOrder } from
|
|
1
|
+
import { CFOrder } from '../../CommonTypes';
|
|
2
2
|
export interface TerminalPaymentParams {
|
|
3
3
|
/**
|
|
4
4
|
* The amount to pay with this tender, in integer MINOR currency units
|
|
@@ -11,7 +11,7 @@ export interface TerminalPaymentParams {
|
|
|
11
11
|
*/
|
|
12
12
|
amount: number;
|
|
13
13
|
/** "Bluetooth" or "Cloud". Only "Cloud" routes to the cloud processor; omitted or "Bluetooth" uses the native card reader. */
|
|
14
|
-
paymentType?:
|
|
14
|
+
paymentType?: 'Bluetooth' | 'Cloud';
|
|
15
15
|
/** Override the fulfillment state the order lands in on full payment (validated against the fulfillment state machine; invalid values throw). Omitted: preserve advanced fulfillment, auto-fulfill from draft/pending/on_hold. */
|
|
16
16
|
checkoutFulfillmentTarget?: string;
|
|
17
17
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { UpdateCartItemQuantity } from
|
|
1
|
+
import { UpdateCartItemQuantity } from './types';
|
|
2
2
|
export declare const mockUpdateCartItemQuantity: UpdateCartItemQuantity;
|
|
@@ -1,60 +1,68 @@
|
|
|
1
|
-
import { MOCK_CART, mockPublishEvent } from
|
|
1
|
+
import { MOCK_CART, mockPublishEvent } from '../../demo/database';
|
|
2
|
+
import { extendPrice, isValidQuantity } from '@final-commerce/common';
|
|
2
3
|
export const mockUpdateCartItemQuantity = (params) => {
|
|
3
|
-
console.log(
|
|
4
|
+
console.log('[Mock] updateCartItemQuantity called', params);
|
|
4
5
|
if (!params?.internalId) {
|
|
5
|
-
throw new Error(
|
|
6
|
+
throw new Error('internalId is required');
|
|
6
7
|
}
|
|
7
8
|
if (params.quantity === undefined || params.quantity === null) {
|
|
8
|
-
throw new Error(
|
|
9
|
+
throw new Error('quantity is required');
|
|
9
10
|
}
|
|
10
11
|
const { internalId, quantity } = params;
|
|
11
12
|
// Find the product in the cart
|
|
12
|
-
const productIndex = MOCK_CART.products.findIndex(p => p.internalId === internalId);
|
|
13
|
+
const productIndex = MOCK_CART.products.findIndex((p) => p.internalId === internalId);
|
|
13
14
|
if (productIndex === -1) {
|
|
14
15
|
throw new Error(`Cart item with internalId ${internalId} not found`);
|
|
15
16
|
}
|
|
16
17
|
const product = MOCK_CART.products[productIndex];
|
|
17
18
|
const previousQuantity = product.quantity;
|
|
19
|
+
// The line resolved its unit when it was added; a piece-sold line has none and stays whole.
|
|
20
|
+
if (quantity !== 0 &&
|
|
21
|
+
!isValidQuantity(quantity, (product.unit ?? { unitId: 'piece', ratioToBase: 1, precision: 0 }))) {
|
|
22
|
+
throw new Error(product.unit
|
|
23
|
+
? `${quantity} is finer than ${product.unit.abbreviation} can express (${product.unit.precision} decimals)`
|
|
24
|
+
: `${product.name} is sold by the piece, so ${quantity} is not a quantity it can sell in`);
|
|
25
|
+
}
|
|
18
26
|
// If quantity is 0, remove the item
|
|
19
27
|
if (quantity === 0) {
|
|
20
28
|
MOCK_CART.products.splice(productIndex, 1);
|
|
21
29
|
// Recalculate totals
|
|
22
|
-
const lineTotal = product.price
|
|
30
|
+
const lineTotal = extendPrice(product.price, previousQuantity);
|
|
23
31
|
MOCK_CART.subtotal -= lineTotal;
|
|
24
32
|
MOCK_CART.total -= lineTotal;
|
|
25
33
|
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
26
34
|
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
27
35
|
// Publish product-deleted event
|
|
28
|
-
mockPublishEvent(
|
|
36
|
+
mockPublishEvent('cart', 'product-deleted', {
|
|
29
37
|
product: product,
|
|
30
|
-
internalId: internalId
|
|
38
|
+
internalId: internalId,
|
|
31
39
|
});
|
|
32
40
|
return Promise.resolve({
|
|
33
41
|
success: true,
|
|
34
42
|
internalId: internalId,
|
|
35
43
|
quantity: 0,
|
|
36
|
-
timestamp: new Date().toISOString()
|
|
44
|
+
timestamp: new Date().toISOString(),
|
|
37
45
|
});
|
|
38
46
|
}
|
|
39
47
|
// Update quantity
|
|
40
|
-
const quantityDelta = quantity - previousQuantity;
|
|
41
48
|
product.quantity = quantity;
|
|
42
|
-
//
|
|
43
|
-
|
|
49
|
+
// Difference of the two ROUNDED extensions — rounding the delta itself would let the
|
|
50
|
+
// line's running total drift from what extendPrice(price, quantity) says it is.
|
|
51
|
+
const lineTotalDelta = extendPrice(product.price, quantity) - extendPrice(product.price, previousQuantity);
|
|
44
52
|
MOCK_CART.subtotal += lineTotalDelta;
|
|
45
53
|
MOCK_CART.total += lineTotalDelta;
|
|
46
54
|
MOCK_CART.amountToBeCharged = MOCK_CART.total;
|
|
47
55
|
MOCK_CART.remainingBalance = MOCK_CART.total;
|
|
48
56
|
// Publish product-updated event
|
|
49
|
-
mockPublishEvent(
|
|
57
|
+
mockPublishEvent('cart', 'product-updated', {
|
|
50
58
|
product: product,
|
|
51
59
|
previousQuantity: previousQuantity,
|
|
52
|
-
newQuantity: quantity
|
|
60
|
+
newQuantity: quantity,
|
|
53
61
|
});
|
|
54
62
|
return Promise.resolve({
|
|
55
63
|
success: true,
|
|
56
64
|
internalId: internalId,
|
|
57
65
|
quantity: quantity,
|
|
58
|
-
timestamp: new Date().toISOString()
|
|
66
|
+
timestamp: new Date().toISOString(),
|
|
59
67
|
});
|
|
60
68
|
};
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
export interface UpdateCartItemQuantityParams {
|
|
2
2
|
/** The unique identifier for the specific cart item to update. */
|
|
3
3
|
internalId: string;
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* The new quantity. If set to 0, the item will be removed from the cart.
|
|
6
|
+
*
|
|
7
|
+
* **May be fractional** for a variant sold by measure; the number of decimals allowed comes
|
|
8
|
+
* from `variant.unit.precision`. The engine refuses anything finer and names the unit in the
|
|
9
|
+
* error. Do not round or clamp before sending — a silently altered quantity is charged and
|
|
10
|
+
* deducted differently than the one the cashier typed.
|
|
11
|
+
*/
|
|
5
12
|
quantity: number;
|
|
6
13
|
}
|
|
7
14
|
export interface UpdateCartItemQuantityResponse {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { UpsertCustomTableData } from
|
|
1
|
+
import { UpsertCustomTableData } from './types';
|
|
2
2
|
export declare const mockUpsertCustomTableData: UpsertCustomTableData;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const mockUpsertCustomTableData = async (params) => {
|
|
2
|
-
console.log(
|
|
2
|
+
console.log('[Mock] upsertCustomTableData called', params);
|
|
3
3
|
const data = params?.data;
|
|
4
4
|
const now = new Date().toISOString();
|
|
5
5
|
// Return the data with _id and timestamps added
|
|
@@ -7,11 +7,11 @@ export const mockUpsertCustomTableData = async (params) => {
|
|
|
7
7
|
...data,
|
|
8
8
|
_id: data?._id || `mock_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
9
9
|
createdAt: data?.createdAt || now,
|
|
10
|
-
updatedAt: now
|
|
10
|
+
updatedAt: now,
|
|
11
11
|
};
|
|
12
12
|
return {
|
|
13
13
|
success: true,
|
|
14
14
|
data: resultData,
|
|
15
|
-
timestamp: now
|
|
15
|
+
timestamp: now,
|
|
16
16
|
};
|
|
17
17
|
};
|