@final-commerce/command-frame 0.9.0-staging.1 → 0.9.0

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.
Files changed (56) hide show
  1. package/dist/CommonTypes.d.ts +1 -25
  2. package/dist/actions/add-product-fee/mock.d.ts +1 -1
  3. package/dist/actions/add-product-fee/mock.js +9 -15
  4. package/dist/actions/add-product-to-cart/mock.d.ts +0 -23
  5. package/dist/actions/add-product-to-cart/mock.js +1 -300
  6. package/dist/actions/add-product-to-cart/types.d.ts +1 -27
  7. package/dist/actions/adjust-inventory/mock.js +20 -0
  8. package/dist/actions/adjust-inventory/types.d.ts +13 -0
  9. package/dist/actions/adjust-inventory/types.js +1 -0
  10. package/dist/actions/get-current-cart/mock.d.ts +1 -1
  11. package/dist/actions/get-current-cart/mock.js +3 -13
  12. package/dist/actions/get-current-cart/types.d.ts +1 -7
  13. package/dist/actions/get-custom-stock-actions/action.d.ts +5 -0
  14. package/dist/actions/get-custom-stock-actions/action.js +7 -0
  15. package/dist/actions/get-custom-stock-actions/mock.d.ts +2 -0
  16. package/dist/actions/get-custom-stock-actions/mock.js +11 -0
  17. package/dist/actions/get-custom-stock-actions/types.d.ts +12 -0
  18. package/dist/actions/get-custom-stock-actions/types.js +2 -0
  19. package/dist/actions/get-product-modifier-selections/mock.js +0 -12
  20. package/dist/actions/get-products/mock.js +3 -7
  21. package/dist/actions/get-products/types.d.ts +1 -1
  22. package/dist/actions/get-refund-plan/mock.d.ts +4 -0
  23. package/dist/actions/get-refund-plan/mock.js +8 -0
  24. package/dist/actions/get-refund-plan/mockRows.d.ts +6 -0
  25. package/dist/actions/get-refund-plan/mockRows.js +114 -0
  26. package/dist/actions/get-refund-plan/types.d.ts +89 -0
  27. package/dist/actions/set-product-modifier-selections/mock.js +0 -12
  28. package/dist/demo/database.d.ts +1 -39
  29. package/dist/demo/database.js +1 -214
  30. package/dist/index.d.ts +4 -6
  31. package/dist/index.js +2 -4
  32. package/dist/projects/render/mocks.js +2 -4
  33. package/dist/projects/render/types.d.ts +2 -3
  34. package/dist/pubsub/topics/products/index.d.ts +2 -2
  35. package/dist/pubsub/topics/products/index.js +18 -33
  36. package/dist/pubsub/topics/products/types.d.ts +10 -16
  37. package/dist/pubsub/topics/products/types.js +4 -7
  38. package/package.json +2 -2
  39. package/dist/actions/get-composite-availability/action.d.ts +0 -6
  40. package/dist/actions/get-composite-availability/action.js +0 -8
  41. package/dist/actions/get-composite-availability/mock.d.ts +0 -2
  42. package/dist/actions/get-composite-availability/mock.js +0 -45
  43. package/dist/actions/get-composite-availability/types.d.ts +0 -29
  44. package/dist/actions/get-composite-availability/types.js +0 -1
  45. package/dist/actions/get-composite-price/action.d.ts +0 -6
  46. package/dist/actions/get-composite-price/action.js +0 -8
  47. package/dist/actions/get-composite-price/mock.d.ts +0 -2
  48. package/dist/actions/get-composite-price/mock.js +0 -37
  49. package/dist/actions/get-composite-price/types.d.ts +0 -31
  50. package/dist/actions/get-composite-price/types.js +0 -1
  51. package/dist/pubsub/topics/products/catalog-visibility-changed/types.d.ts +0 -17
  52. package/dist/pubsub/topics/products/catalog-visibility-changed/types.js +0 -1
  53. package/dist/pubsub/topics/products/composite-changed/types.d.ts +0 -17
  54. package/dist/pubsub/topics/products/composite-changed/types.js +0 -1
  55. package/dist/pubsub/topics/products/inventory-changed/types.d.ts +0 -18
  56. package/dist/pubsub/topics/products/inventory-changed/types.js +0 -1
@@ -16,18 +16,6 @@ export const mockGetProductModifierSelections = async (params) => {
16
16
  timestamp: new Date().toISOString(),
17
17
  };
18
18
  }
19
- // Like the host (FT-83): a composite line's modifiers belong to its components.
20
- if (line.components?.length) {
21
- return {
22
- success: false,
23
- reason: 'The modifiers of a composite line cannot be edited yet: remove the line and add it again with its picks',
24
- internalId: line.internalId,
25
- selections: [],
26
- rows: [],
27
- modifiersTotal: 0,
28
- timestamp: new Date().toISOString(),
29
- };
30
- }
31
19
  // The priced rows already sit on the line; extending them by the line quantity is
32
20
  // the host's job, not the flow's.
33
21
  const { rows, modifiersTotal } = buildModifierRows(line.modifiers, line.quantity);
@@ -1,13 +1,9 @@
1
- import { MOCK_PRODUCTS, mockCompositeAtOutlet, mockHiddenProductIds, safeSerialize } from '../../demo/database';
1
+ import { MOCK_PRODUCTS, safeSerialize } from '../../demo/database';
2
2
  import { resolveUnit } from '@final-commerce/common';
3
3
  export const mockGetProducts = async (params) => {
4
4
  console.log('[Mock] getProducts called', params);
5
- // Simple filter simulation. Like the host: a product hidden at this outlet is left out, and a composite offers only
6
- // what is sold here.
7
- const hidden = mockHiddenProductIds();
8
- let products = MOCK_PRODUCTS.filter((p) => !hidden.has(p._id)).map((p) =>
9
- // B43: the host never hands a composite modifiers of its own.
10
- p.composite ? { ...p, modifiers: [], composite: mockCompositeAtOutlet(p.composite, hidden) } : p);
5
+ // Simple filter simulation
6
+ let products = MOCK_PRODUCTS;
11
7
  const query = params?.query || {};
12
8
  // Same rule as the real host: a bookable service is not catalogue stock and is left out unless
13
9
  // the query names `productType`. Mirrored here on purpose — a mock that hands back services the
@@ -27,7 +27,7 @@ export interface GetProductsParams {
27
27
  };
28
28
  status?: string;
29
29
  /**
30
- * `simple` | `variable` | `booking` | `composite`. Naming it at all switches OFF the default exclusion
30
+ * `simple` | `variable` | `booking`. Naming it at all switches OFF the default exclusion
31
31
  * of bookable services — including `{ $ne: 'booking' }`, which then means what it says.
32
32
  */
33
33
  productType?: string | {
@@ -15,5 +15,9 @@ import { GetRefundPlan } from './types';
15
15
  * and no company cash-rounding setting, so it always describes a FULL refund
16
16
  * with `rounding: 0` and no cash `payout`. Against real kaching the allocation
17
17
  * tracks the live selection and carries the drawer snap.
18
+ *
19
+ * `rows` / `allocation.breakdown` follow the engine's reading of the order
20
+ * (`line.total` includes the line's tax) but prorate by plain quantity share;
21
+ * the engine's remainder carry across earlier partial refunds is not modelled.
18
22
  */
19
23
  export declare const mockGetRefundPlan: GetRefundPlan;
@@ -1,4 +1,5 @@
1
1
  import { MOCK_ORDERS } from '../../demo/database';
2
+ import { mockRefundBreakdown, mockRefundRows } from './mockRows';
2
3
  /**
3
4
  * Demo derivation of the runtime `getRefundPlan`. Builds the per-source rows
4
5
  * from the mock order's `paymentMethods`, mirroring the runtime's capacity
@@ -15,6 +16,10 @@ import { MOCK_ORDERS } from '../../demo/database';
15
16
  * and no company cash-rounding setting, so it always describes a FULL refund
16
17
  * with `rounding: 0` and no cash `payout`. Against real kaching the allocation
17
18
  * tracks the live selection and carries the drawer snap.
19
+ *
20
+ * `rows` / `allocation.breakdown` follow the engine's reading of the order
21
+ * (`line.total` includes the line's tax) but prorate by plain quantity share;
22
+ * the engine's remainder carry across earlier partial refunds is not modelled.
18
23
  */
19
24
  export const mockGetRefundPlan = async (params) => {
20
25
  console.log('[Mock] getRefundPlan called', params);
@@ -62,16 +67,19 @@ export const mockGetRefundPlan = async (params) => {
62
67
  requiresGiftCardDestination: s.paymentType === 'redeem',
63
68
  }));
64
69
  const budget = legs.reduce((sum, l) => sum + l.amount, 0);
70
+ const rows = mockRefundRows(order);
65
71
  return {
66
72
  success: true,
67
73
  orderId: order._id,
68
74
  sources,
75
+ rows,
69
76
  allocation: {
70
77
  budget,
71
78
  // No cash rounding in the demo, so the goods value and the budget agree.
72
79
  itemTotal: budget,
73
80
  rounding: 0,
74
81
  legs,
82
+ breakdown: mockRefundBreakdown(rows, params?.items),
75
83
  },
76
84
  // Demo: no prior refunds, so remaining = captured minus the non-revenue load.
77
85
  remainingRefundable: Math.max(0, totalCaptured - nonRefundableLiability),
@@ -0,0 +1,6 @@
1
+ import type { CFActiveOrder } from '../../CommonTypes';
2
+ import type { GetRefundPlanParams, RefundPlanBreakdown, RefundPlanRow } from './types';
3
+ /** Every row of a demo order. The demo has no refund ledger, so everything is refundable. */
4
+ export declare function mockRefundRows(order: CFActiveOrder): RefundPlanRow[];
5
+ /** The selection's breakdown; no `items` means everything, like the demo's full-refund legs. */
6
+ export declare function mockRefundBreakdown(rows: RefundPlanRow[], items?: GetRefundPlanParams['items']): RefundPlanBreakdown;
@@ -0,0 +1,114 @@
1
+ // Demo derivation of `getRefundPlan`'s `rows` and `allocation.breakdown`, for
2
+ // local/standalone mode only. See the note on `mockGetRefundPlan`.
3
+ const minor = (v) => Math.round(Number(v ?? 0)) || 0;
4
+ /** A line's whole-quantity money, reading `total` as tax-inclusive (the engine's reading). */
5
+ function lineAmounts(line) {
6
+ const tax = minor(line.totalTax);
7
+ const itemDiscount = (line.discount?.itemDiscounts ?? []).reduce((s, d) => s + minor(d.amount), 0);
8
+ const cartDiscount = minor(line.discount?.cartDiscount?.amount);
9
+ const net = Math.max(0, minor(line.total) - tax);
10
+ const taxes = (line.taxes ?? []).map((t) => ({
11
+ name: String(t.name ?? 'Tax'),
12
+ percentage: t.percentage,
13
+ amount: minor(t.amount),
14
+ }));
15
+ return { subtotal: net + itemDiscount + cartDiscount, itemDiscount, cartDiscount, tax, taxes, total: net + tax };
16
+ }
17
+ function scale(a, share) {
18
+ if (share >= 1)
19
+ return a;
20
+ const r = (n) => Math.round(n * share);
21
+ const out = {
22
+ subtotal: r(a.subtotal),
23
+ itemDiscount: r(a.itemDiscount),
24
+ cartDiscount: r(a.cartDiscount),
25
+ tax: r(a.tax),
26
+ taxes: a.taxes.map((t) => ({ ...t, amount: r(t.amount) })),
27
+ };
28
+ return { ...out, total: out.subtotal - out.itemDiscount - out.cartDiscount + out.tax };
29
+ }
30
+ /** Every row of a demo order. The demo has no refund ledger, so everything is refundable. */
31
+ export function mockRefundRows(order) {
32
+ const rows = [];
33
+ for (const li of order.lineItems ?? []) {
34
+ const itemKey = String(li.internalId || li.variantId || '');
35
+ if (!itemKey || !(li.quantity > 0))
36
+ continue;
37
+ rows.push({
38
+ type: 'product',
39
+ itemKey,
40
+ label: String(li.name ?? 'Item'),
41
+ ...(li.sku ? { sku: li.sku } : {}),
42
+ ...(li.attributes ? { attributes: li.attributes } : {}),
43
+ quantity: li.quantity,
44
+ refundableQuantity: li.quantity,
45
+ amounts: lineAmounts(li),
46
+ });
47
+ }
48
+ for (const cs of order.customSales ?? []) {
49
+ if (!cs.customSaleId || !(cs.quantity > 0))
50
+ continue;
51
+ rows.push({
52
+ type: 'customSale',
53
+ itemKey: cs.customSaleId,
54
+ label: String(cs.name ?? 'Custom sale'),
55
+ quantity: cs.quantity,
56
+ refundableQuantity: cs.quantity,
57
+ amounts: lineAmounts(cs),
58
+ });
59
+ }
60
+ for (const fee of order.cartFees ?? []) {
61
+ const amount = minor(fee.amount);
62
+ const tax = minor(fee.tax);
63
+ rows.push({
64
+ type: 'fee',
65
+ itemKey: String(fee.id),
66
+ label: String(fee.label || 'Cart fee'),
67
+ quantity: 1,
68
+ refundableQuantity: 1,
69
+ amounts: { subtotal: amount, itemDiscount: 0, cartDiscount: 0, tax, taxes: [], total: amount + tax },
70
+ });
71
+ }
72
+ for (const pm of order.paymentMethods ?? []) {
73
+ const tip = minor(pm.tip?.amount);
74
+ if (tip <= 0)
75
+ continue;
76
+ rows.push({
77
+ type: 'tip',
78
+ itemKey: pm.transactionId,
79
+ label: 'Tip',
80
+ paymentType: pm.paymentType,
81
+ quantity: 1,
82
+ refundableQuantity: 1,
83
+ amounts: { subtotal: tip, itemDiscount: 0, cartDiscount: 0, tax: 0, taxes: [], total: tip },
84
+ });
85
+ }
86
+ return rows;
87
+ }
88
+ /** The selection's breakdown; no `items` means everything, like the demo's full-refund legs. */
89
+ export function mockRefundBreakdown(rows, items) {
90
+ const picked = new Map((items ?? []).map((i) => [i.itemKey, i.quantity]));
91
+ const selected = rows
92
+ .map((row) => {
93
+ const quantity = items?.length
94
+ ? Math.min(picked.get(row.itemKey) ?? 0, row.refundableQuantity)
95
+ : row.refundableQuantity;
96
+ return { type: row.type, itemKey: row.itemKey, quantity, amounts: scale(row.amounts, quantity / row.quantity) };
97
+ })
98
+ .filter((r) => r.quantity > 0);
99
+ const totals = { items: 0, discounts: 0, fees: 0, tax: 0, tip: 0, total: 0 };
100
+ for (const r of selected) {
101
+ const a = r.amounts;
102
+ if (r.type === 'fee')
103
+ totals.fees += a.subtotal;
104
+ else if (r.type === 'tip')
105
+ totals.tip += a.subtotal;
106
+ else {
107
+ totals.items += a.subtotal;
108
+ totals.discounts += a.itemDiscount + a.cartDiscount;
109
+ }
110
+ totals.tax += a.tax;
111
+ totals.total += a.total;
112
+ }
113
+ return { rows: selected, totals };
114
+ }
@@ -79,6 +79,81 @@ export interface RefundPlanLeg {
79
79
  rounding: number;
80
80
  };
81
81
  }
82
+ export type RefundPlanRowType = 'product' | 'customSale' | 'fee' | 'tip';
83
+ /** One tax rate's share of a row's refund (minor units). */
84
+ export interface RefundPlanTaxLine {
85
+ name: string;
86
+ /** Decimal rate as stored on the order (e.g. `0.15`), when the order recorded one. */
87
+ percentage?: number;
88
+ amount: number;
89
+ }
90
+ /**
91
+ * The money a row refunds, split the way a receipt shows it. Every field is
92
+ * minor units and already rounded; `subtotal − itemDiscount − cartDiscount +
93
+ * tax === total` always holds. DISPLAY IT — never re-add or prorate it.
94
+ */
95
+ export interface RefundPlanAmounts {
96
+ /** Before discounts, tax excluded. For a tip row, the tip itself. */
97
+ subtotal: number;
98
+ /** Per-item discounts on the refunded quantity (positive). */
99
+ itemDiscount: number;
100
+ /** Cart discount share on the refunded quantity (positive). */
101
+ cartDiscount: number;
102
+ /** Tax on the refunded quantity. Zero for a tip. */
103
+ tax: number;
104
+ /** `tax` per rate — the price breakdown's tax lines. */
105
+ taxes: RefundPlanTaxLine[];
106
+ /** What the row refunds. */
107
+ total: number;
108
+ }
109
+ /**
110
+ * One refundable row of the order — a line item, custom sale, cart fee or tip —
111
+ * served ready to render. Rows with nothing left to refund are not listed.
112
+ */
113
+ export interface RefundPlanRow {
114
+ type: RefundPlanRowType;
115
+ /** The key `items[].itemKey` takes, for this call and for `processPartialRefund`. */
116
+ itemKey: string;
117
+ /** Line or fee name; `Tip` for a tip. */
118
+ label: string;
119
+ /** Product lines only, when the order recorded them. */
120
+ sku?: string;
121
+ attributes?: string;
122
+ /** Tip rows only: the tender that took the tip (`card`, `cash`, …). */
123
+ paymentType?: string;
124
+ /** Quantity originally sold. Fees and tips are `1` — all or nothing. */
125
+ quantity: number;
126
+ /** Quantity still refundable — the stepper's max. */
127
+ refundableQuantity: number;
128
+ /** The money for refunding ALL of `refundableQuantity`. */
129
+ amounts: RefundPlanAmounts;
130
+ }
131
+ /** One selected row and what refunding the selected quantity of it moves. */
132
+ export interface RefundPlanSelectedRow {
133
+ type: RefundPlanRowType;
134
+ itemKey: string;
135
+ quantity: number;
136
+ amounts: RefundPlanAmounts;
137
+ }
138
+ /**
139
+ * The selection's goods value broken down for display. Minor units;
140
+ * `items − discounts + fees + tax + tip === total === allocation.itemTotal`.
141
+ */
142
+ export interface RefundPlanTotals {
143
+ /** Σ selected line subtotals (before discounts, tax excluded). */
144
+ items: number;
145
+ /** Σ item + cart discounts on the selected lines (positive). */
146
+ discounts: number;
147
+ /** Σ selected cart fees, tax excluded. */
148
+ fees: number;
149
+ tax: number;
150
+ tip: number;
151
+ total: number;
152
+ }
153
+ export interface RefundPlanBreakdown {
154
+ rows: RefundPlanSelectedRow[];
155
+ totals: RefundPlanTotals;
156
+ }
82
157
  /**
83
158
  * The engine's own allocation of the CURRENT refund selection across the
84
159
  * order's captures — what a flow renders and submits instead of computing a
@@ -106,11 +181,25 @@ export interface RefundPlanAllocation {
106
181
  rounding: number;
107
182
  /** One leg per source that receives money. Submit as `legs`, unchanged. */
108
183
  legs: RefundPlanLeg[];
184
+ /**
185
+ * What the selection refunds, per row and in total — the numbers a refund
186
+ * dialog's rows and footer render. Optional so an older runtime still
187
+ * type-checks; kaching 1.12.1+ always sends it.
188
+ */
189
+ breakdown?: RefundPlanBreakdown;
109
190
  }
110
191
  export interface GetRefundPlanResponse {
111
192
  success: boolean;
112
193
  orderId: string;
113
194
  sources: RefundPlanSource[];
195
+ /**
196
+ * Every row still refundable on the order, with the money for refunding all
197
+ * of it — what a refund dialog lists before anything is selected. Replaces
198
+ * reading line totals off the order and deciding whether they include tax.
199
+ * Optional so an older runtime still type-checks; kaching 1.12.1+ always
200
+ * sends it.
201
+ */
202
+ rows?: RefundPlanRow[];
114
203
  /**
115
204
  * Ready-to-submit allocation of the current selection. Present only when a
116
205
  * refund selection exists on the active order. See {@link RefundPlanAllocation}.
@@ -30,18 +30,6 @@ export const mockSetProductModifierSelections = async (params) => {
30
30
  timestamp: new Date().toISOString(),
31
31
  };
32
32
  }
33
- // Like the host (FT-83): a composite line's modifiers belong to its components.
34
- if (line.components?.length) {
35
- return {
36
- success: false,
37
- reason: 'The modifiers of a composite line cannot be edited yet: remove the line and add it again with its picks',
38
- internalId: line.internalId,
39
- selections: [],
40
- rows: [],
41
- modifiersTotal: 0,
42
- timestamp: new Date().toISOString(),
43
- };
44
- }
45
33
  // Full replacement — passing [] clears the rows. The line drops the product's resolved
46
34
  // stack when it is built, so the menu is re-read from the catalogue to price against.
47
35
  // Cart totals are not touched, for the same reason addProductToCart does not move them
@@ -2,7 +2,7 @@
2
2
  * Mock Database for Standalone/Demo Mode
3
3
  * Stores mock data that mimics the Render environment
4
4
  */
5
- import { CFActiveCompany, CFActiveUser, CFActiveStation, CFActiveOutlet, CFActiveOrder, CFCustomer, CFProduct, CFComposite, CFCartLineComponent, CFActiveCart, CFCategory, CFActiveProduct, CFSession, CFActiveRefundDetails, CFSmartGridLayout, CFBooking, CFBookingAvailability, CFBookingResource, CFBookingSlot, CFCartLineModifier, CFProdModifierBreakdown, CFModifierSelection, CFResolvedModifier } from '../CommonTypes';
5
+ import { CFActiveCompany, CFActiveUser, CFActiveStation, CFActiveOutlet, CFActiveOrder, CFCustomer, CFProduct, CFActiveCart, CFCategory, CFActiveProduct, CFSession, CFActiveRefundDetails, CFSmartGridLayout, CFBooking, CFBookingAvailability, CFBookingResource, CFCartLineModifier, CFProdModifierBreakdown, CFModifierSelection, CFResolvedModifier } from '../CommonTypes';
6
6
  export * from './mocks';
7
7
  /** Replace mock catalog / context data in place (same array references mock handlers use). */
8
8
  export interface MockDatabaseConfig {
@@ -19,12 +19,6 @@ export interface MockDatabaseConfig {
19
19
  bookingResources?: CFBookingResource[];
20
20
  /** Windows already taken when the dataset loads, so a calendar does not open empty. */
21
21
  bookings?: CFBooking[];
22
- /** Products hidden at an outlet (the host's `catalog-visibility`, product-level rows). Empty = sold everywhere. */
23
- catalogVisibility?: MockCatalogVisibility[];
24
- }
25
- export interface MockCatalogVisibility {
26
- productId: string;
27
- outletId: string;
28
22
  }
29
23
  export declare const MOCK_COMPANY: CFActiveCompany;
30
24
  export declare const MOCK_OUTLET_MAIN: CFActiveOutlet;
@@ -70,40 +64,8 @@ export declare const MOCK_OUTLETS: import("@final-commerce/common/pos-types").Ac
70
64
  export declare const MOCK_CUSTOMERS: import("@final-commerce/common/pos-types").ActiveCustomer[];
71
65
  export declare const MOCK_CATEGORIES: import("@final-commerce/common/pos-types").Category[];
72
66
  export declare const MOCK_PRODUCT_HAIRCUT: CFProduct;
73
- export declare const MOCK_PRODUCT_PASTE_TRIO: CFProduct;
74
67
  export declare const MOCK_PRODUCTS: import("@final-commerce/common/pos-types").FullProduct[];
75
68
  export declare const MOCK_ORDERS: import("@final-commerce/common/pos-types").ActiveOrder[];
76
- /** Nothing hidden by default; `setMockDatabase({ catalogVisibility })` hides products at an outlet. */
77
- export declare const MOCK_CATALOG_VISIBILITY: MockCatalogVisibility[];
78
- /**
79
- * The host's cart stock check for composites (kaching `compositeStockRefusal`), over the demo shelves — a copy: what the
80
- * cart takes of each component's variant (plain lines and components × their line quantity) against its shelf here.
81
- * The demo has no pools or units, so it counts per variant; untracked and backordered variants are never short.
82
- */
83
- export declare function mockCompositeStockRefusal(products: {
84
- variantId: string;
85
- quantity: number;
86
- components?: CFCartLineComponent[];
87
- }[]): string | null;
88
- /** Product ids hidden at the demo's active outlet. */
89
- export declare const mockHiddenProductIds: () => Set<string>;
90
- /**
91
- * The host's outlet rules for a composite (kaching `resolveComposite`), over the demo's static view — a copy, change both
92
- * in one step: an item whose product is hidden here is left out, a category item keeps only products sold here (none →
93
- * `'empty'`), an Optional part with nothing to pick is not offered, a required one with nothing makes it unavailable,
94
- * and the D36 default and "from" price are read off what is left.
95
- */
96
- /** B41: the seats a bookable demo product has free in the slot starting at `startAt` — as the host reads them. */
97
- export declare function mockBookableWindow(productId: string, startAt: string): {
98
- free: number;
99
- slot: CFBookingSlot | null;
100
- };
101
- export declare const mockIsBookable: (productId: string) => boolean;
102
- export declare function mockCompositeAtOutlet(composite: Omit<CFComposite, 'needsDate'>, hidden?: Set<string>,
103
- /** B41: the window bookable items are judged in; absent = `by_date`. */
104
- slot?: {
105
- startAt: string;
106
- }): CFComposite;
107
69
  export declare const MOCK_PARKED_ORDERS: CFActiveOrder[];
108
70
  export declare let MOCK_USER: CFActiveUser;
109
71
  export declare let MOCK_STATION: CFActiveStation;