@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.
- package/dist/CommonTypes.d.ts +1 -25
- package/dist/actions/add-product-fee/mock.d.ts +1 -1
- package/dist/actions/add-product-fee/mock.js +9 -15
- package/dist/actions/add-product-to-cart/mock.d.ts +0 -23
- package/dist/actions/add-product-to-cart/mock.js +1 -300
- package/dist/actions/add-product-to-cart/types.d.ts +1 -27
- package/dist/actions/adjust-inventory/mock.js +20 -0
- package/dist/actions/adjust-inventory/types.d.ts +13 -0
- package/dist/actions/adjust-inventory/types.js +1 -0
- package/dist/actions/get-current-cart/mock.d.ts +1 -1
- package/dist/actions/get-current-cart/mock.js +3 -13
- package/dist/actions/get-current-cart/types.d.ts +1 -7
- package/dist/actions/get-custom-stock-actions/action.d.ts +5 -0
- package/dist/actions/get-custom-stock-actions/action.js +7 -0
- package/dist/actions/get-custom-stock-actions/mock.d.ts +2 -0
- package/dist/actions/get-custom-stock-actions/mock.js +11 -0
- package/dist/actions/get-custom-stock-actions/types.d.ts +12 -0
- package/dist/actions/get-custom-stock-actions/types.js +2 -0
- package/dist/actions/get-product-modifier-selections/mock.js +0 -12
- package/dist/actions/get-products/mock.js +3 -7
- package/dist/actions/get-products/types.d.ts +1 -1
- package/dist/actions/get-refund-plan/mock.d.ts +4 -0
- package/dist/actions/get-refund-plan/mock.js +8 -0
- package/dist/actions/get-refund-plan/mockRows.d.ts +6 -0
- package/dist/actions/get-refund-plan/mockRows.js +114 -0
- package/dist/actions/get-refund-plan/types.d.ts +89 -0
- package/dist/actions/set-product-modifier-selections/mock.js +0 -12
- package/dist/demo/database.d.ts +1 -39
- package/dist/demo/database.js +1 -214
- package/dist/index.d.ts +4 -6
- package/dist/index.js +2 -4
- package/dist/projects/render/mocks.js +2 -4
- package/dist/projects/render/types.d.ts +2 -3
- package/dist/pubsub/topics/products/index.d.ts +2 -2
- package/dist/pubsub/topics/products/index.js +18 -33
- package/dist/pubsub/topics/products/types.d.ts +10 -16
- package/dist/pubsub/topics/products/types.js +4 -7
- package/package.json +2 -2
- package/dist/actions/get-composite-availability/action.d.ts +0 -6
- package/dist/actions/get-composite-availability/action.js +0 -8
- package/dist/actions/get-composite-availability/mock.d.ts +0 -2
- package/dist/actions/get-composite-availability/mock.js +0 -45
- package/dist/actions/get-composite-availability/types.d.ts +0 -29
- package/dist/actions/get-composite-availability/types.js +0 -1
- package/dist/actions/get-composite-price/action.d.ts +0 -6
- package/dist/actions/get-composite-price/action.js +0 -8
- package/dist/actions/get-composite-price/mock.d.ts +0 -2
- package/dist/actions/get-composite-price/mock.js +0 -37
- package/dist/actions/get-composite-price/types.d.ts +0 -31
- package/dist/actions/get-composite-price/types.js +0 -1
- package/dist/pubsub/topics/products/catalog-visibility-changed/types.d.ts +0 -17
- package/dist/pubsub/topics/products/catalog-visibility-changed/types.js +0 -1
- package/dist/pubsub/topics/products/composite-changed/types.d.ts +0 -17
- package/dist/pubsub/topics/products/composite-changed/types.js +0 -1
- package/dist/pubsub/topics/products/inventory-changed/types.d.ts +0 -18
- package/dist/pubsub/topics/products/inventory-changed/types.js +0 -1
package/dist/demo/database.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Stores mock data that mimics the Render environment
|
|
4
4
|
*/
|
|
5
5
|
import { CFProductType, CFUserTypes, CurrencyCode, } from '../CommonTypes';
|
|
6
|
-
import {
|
|
6
|
+
import { extendPrice, resolveUnit, toBase } from '@final-commerce/common';
|
|
7
7
|
import { BookingRatePeriod, BookingResourceKind, BookingType, ReservationStatus } from '@final-commerce/common';
|
|
8
8
|
export * from './mocks';
|
|
9
9
|
// Asset Imports - Using Remote URLs to avoid build complexity with asset copying
|
|
@@ -228,7 +228,6 @@ const createSimpleProduct = (id, name, price, image, categories, description) =>
|
|
|
228
228
|
maxPrice: price,
|
|
229
229
|
status: 'active',
|
|
230
230
|
productType: CFProductType.SIMPLE,
|
|
231
|
-
composite: null,
|
|
232
231
|
taxTable: 'tax_standard',
|
|
233
232
|
description,
|
|
234
233
|
images: [image],
|
|
@@ -264,7 +263,6 @@ const createVariableProduct = (id, name, basePrice, largePrice, image, categorie
|
|
|
264
263
|
maxPrice: largePrice,
|
|
265
264
|
status: 'active',
|
|
266
265
|
productType: CFProductType.VARIABLE,
|
|
267
|
-
composite: null,
|
|
268
266
|
taxTable: 'tax_standard',
|
|
269
267
|
description,
|
|
270
268
|
images: [image],
|
|
@@ -660,106 +658,7 @@ export const MOCK_PRODUCT_HAIRCUT = {
|
|
|
660
658
|
productType: CFProductType.BOOKING,
|
|
661
659
|
bookingRulesId: 'rule_salon_30',
|
|
662
660
|
};
|
|
663
|
-
// A composite (FT-83) as the host serves it: the merchant's price 27.00, items add only their upcharges (B31); each item
|
|
664
|
-
// keeps its own tax (`taxTable` empty). One item points at a deleted variant (unavailable), one is a whole category.
|
|
665
|
-
export const MOCK_PRODUCT_PASTE_TRIO = {
|
|
666
|
-
...createSimpleProduct('prod_paste_trio', 'Paste Trio', 2700, basilAlmondImg, [MOCK_CATEGORY_PASTES], 'Pick a paste and a spicy one.'),
|
|
667
|
-
productType: CFProductType.COMPOSITE,
|
|
668
|
-
taxTable: '',
|
|
669
|
-
// B43: a composite has no modifiers of its own; its items carry theirs.
|
|
670
|
-
modifiers: [],
|
|
671
|
-
composite: {
|
|
672
|
-
available: true,
|
|
673
|
-
basePrice: 2700,
|
|
674
|
-
fromPrice: 2800,
|
|
675
|
-
parts: [
|
|
676
|
-
{
|
|
677
|
-
_id: 'part_paste',
|
|
678
|
-
name: 'Paste',
|
|
679
|
-
required: true,
|
|
680
|
-
min: 1,
|
|
681
|
-
max: 1,
|
|
682
|
-
defaultPick: { itemId: 'item_basil', variantId: 'prod_basil_almond_var_main' },
|
|
683
|
-
items: [
|
|
684
|
-
{
|
|
685
|
-
_id: 'item_basil',
|
|
686
|
-
variantId: 'prod_basil_almond_var_main',
|
|
687
|
-
categoryId: null,
|
|
688
|
-
name: 'Basil Almond Paste',
|
|
689
|
-
extraCharge: 0,
|
|
690
|
-
quantity: 1,
|
|
691
|
-
cost: 0,
|
|
692
|
-
unavailable: null,
|
|
693
|
-
choices: [
|
|
694
|
-
{
|
|
695
|
-
productId: 'prod_basil_almond',
|
|
696
|
-
variantId: 'prod_basil_almond_var_main',
|
|
697
|
-
name: 'Basil Almond Paste',
|
|
698
|
-
attributes: [],
|
|
699
|
-
// The picked product's own modifiers (B28): taxed at its table, sent in the pick.
|
|
700
|
-
modifiers: [
|
|
701
|
-
{
|
|
702
|
-
_id: 'mod_texture',
|
|
703
|
-
name: 'Texture',
|
|
704
|
-
selectionType: 'single',
|
|
705
|
-
required: false,
|
|
706
|
-
sortOrder: 0,
|
|
707
|
-
choices: [
|
|
708
|
-
{ _id: 'choice_smooth', name: 'Smooth', price: 0, sortOrder: 0 },
|
|
709
|
-
{ _id: 'choice_chunky', name: 'Chunky', price: 50, sortOrder: 1 },
|
|
710
|
-
],
|
|
711
|
-
},
|
|
712
|
-
],
|
|
713
|
-
},
|
|
714
|
-
],
|
|
715
|
-
},
|
|
716
|
-
{
|
|
717
|
-
_id: 'item_gone',
|
|
718
|
-
variantId: 'prod_gone_var_main',
|
|
719
|
-
categoryId: null,
|
|
720
|
-
name: '',
|
|
721
|
-
extraCharge: 0,
|
|
722
|
-
quantity: 1,
|
|
723
|
-
cost: 0,
|
|
724
|
-
unavailable: 'deleted',
|
|
725
|
-
choices: [],
|
|
726
|
-
},
|
|
727
|
-
],
|
|
728
|
-
},
|
|
729
|
-
{
|
|
730
|
-
_id: 'part_spicy',
|
|
731
|
-
name: null,
|
|
732
|
-
required: true,
|
|
733
|
-
min: 1,
|
|
734
|
-
max: 2,
|
|
735
|
-
// "Pick up to 2": no preselected pick (B29 = D36) — the till shows how many are still needed.
|
|
736
|
-
defaultPick: null,
|
|
737
|
-
items: [
|
|
738
|
-
{
|
|
739
|
-
_id: 'item_spicy',
|
|
740
|
-
variantId: null,
|
|
741
|
-
categoryId: MOCK_CATEGORY_SPICY.id,
|
|
742
|
-
name: 'Spicy',
|
|
743
|
-
extraCharge: 100,
|
|
744
|
-
quantity: 1,
|
|
745
|
-
cost: 100,
|
|
746
|
-
unavailable: null,
|
|
747
|
-
choices: [
|
|
748
|
-
{
|
|
749
|
-
productId: 'prod_habanero',
|
|
750
|
-
variantId: 'prod_habanero_var_main',
|
|
751
|
-
name: 'Habanero Paste',
|
|
752
|
-
attributes: [],
|
|
753
|
-
},
|
|
754
|
-
],
|
|
755
|
-
},
|
|
756
|
-
],
|
|
757
|
-
},
|
|
758
|
-
],
|
|
759
|
-
},
|
|
760
|
-
};
|
|
761
661
|
export const MOCK_PRODUCTS = [
|
|
762
|
-
MOCK_PRODUCT_PASTE_TRIO,
|
|
763
662
|
MOCK_PRODUCT_BASIL_ALMOND,
|
|
764
663
|
MOCK_PRODUCT_BEER,
|
|
765
664
|
MOCK_PRODUCT_BEET,
|
|
@@ -777,114 +676,6 @@ export const MOCK_PRODUCTS = [
|
|
|
777
676
|
MOCK_PRODUCT_HAIRCUT,
|
|
778
677
|
];
|
|
779
678
|
export const MOCK_ORDERS = [MOCK_ORDER_1, MOCK_ORDER_2, MOCK_ORDER_3, MOCK_ORDER_4];
|
|
780
|
-
/** Nothing hidden by default; `setMockDatabase({ catalogVisibility })` hides products at an outlet. */
|
|
781
|
-
export const MOCK_CATALOG_VISIBILITY = [];
|
|
782
|
-
/**
|
|
783
|
-
* The host's cart stock check for composites (kaching `compositeStockRefusal`), over the demo shelves — a copy: what the
|
|
784
|
-
* cart takes of each component's variant (plain lines and components × their line quantity) against its shelf here.
|
|
785
|
-
* The demo has no pools or units, so it counts per variant; untracked and backordered variants are never short.
|
|
786
|
-
*/
|
|
787
|
-
export function mockCompositeStockRefusal(products) {
|
|
788
|
-
const components = products.flatMap((product) => product.components ?? []);
|
|
789
|
-
const demand = new Map();
|
|
790
|
-
for (const product of products) {
|
|
791
|
-
if (product.components)
|
|
792
|
-
for (const component of product.components)
|
|
793
|
-
demand.set(component.variantId, (demand.get(component.variantId) ?? 0) + component.quantity * product.quantity);
|
|
794
|
-
else
|
|
795
|
-
demand.set(product.variantId, (demand.get(product.variantId) ?? 0) + product.quantity);
|
|
796
|
-
}
|
|
797
|
-
for (const component of components) {
|
|
798
|
-
const variant = MOCK_PRODUCTS.flatMap((product) => product.variants).find((candidate) => candidate._id === component.variantId);
|
|
799
|
-
if (!variant?.manageStock || variant.allowBackorder)
|
|
800
|
-
continue;
|
|
801
|
-
const left = variant.inventory?.find((row) => row.outletId === MOCK_OUTLET.id)?.stock ?? 0;
|
|
802
|
-
if ((demand.get(component.variantId) ?? 0) > left)
|
|
803
|
-
return `${component.name}: only ${left} left`;
|
|
804
|
-
}
|
|
805
|
-
return null;
|
|
806
|
-
}
|
|
807
|
-
/** Product ids hidden at the demo's active outlet. */
|
|
808
|
-
export const mockHiddenProductIds = () => new Set(MOCK_CATALOG_VISIBILITY.filter((row) => row.outletId === MOCK_OUTLET.id).map((row) => row.productId));
|
|
809
|
-
/**
|
|
810
|
-
* The host's outlet rules for a composite (kaching `resolveComposite`), over the demo's static view — a copy, change both
|
|
811
|
-
* in one step: an item whose product is hidden here is left out, a category item keeps only products sold here (none →
|
|
812
|
-
* `'empty'`), an Optional part with nothing to pick is not offered, a required one with nothing makes it unavailable,
|
|
813
|
-
* and the D36 default and "from" price are read off what is left.
|
|
814
|
-
*/
|
|
815
|
-
/** B41: the seats a bookable demo product has free in the slot starting at `startAt` — as the host reads them. */
|
|
816
|
-
export function mockBookableWindow(productId, startAt) {
|
|
817
|
-
const at = new Date(startAt);
|
|
818
|
-
const slot = mockBookingAvailability(productId, at, new Date(+at + 86400000)).slots.find((candidate) => +new Date(candidate.startAt) === +at && candidate.canStart) ?? null;
|
|
819
|
-
return { free: slot?.free ?? 0, slot };
|
|
820
|
-
}
|
|
821
|
-
export const mockIsBookable = (productId) => MOCK_PRODUCTS.find((product) => product._id === productId)?.productType === CFProductType.BOOKING;
|
|
822
|
-
export function mockCompositeAtOutlet(composite, hidden = mockHiddenProductIds(),
|
|
823
|
-
/** B41: the window bookable items are judged in; absent = `by_date`. */
|
|
824
|
-
slot) {
|
|
825
|
-
// B41: a bookable item is judged by seats in the window, never by stock; with no window it waits for a date.
|
|
826
|
-
const bookable = (item) => !!item.variantId && item.choices.some((choice) => mockIsBookable(choice.productId));
|
|
827
|
-
const seatsFor = (item) => !slot
|
|
828
|
-
? 'by_date'
|
|
829
|
-
: mockBookableWindow(item.choices[0].productId, slot.startAt).free >= item.quantity
|
|
830
|
-
? null
|
|
831
|
-
: 'fully_booked';
|
|
832
|
-
const offered = (item) => !item.unavailable || item.unavailable === 'by_date';
|
|
833
|
-
// B35: a tracked variant without `quantity` on the demo shelf here (and no backorder) is sold out.
|
|
834
|
-
const soldOut = (variantId, quantity) => {
|
|
835
|
-
const variant = MOCK_PRODUCTS.flatMap((product) => product.variants).find((candidate) => candidate._id === variantId);
|
|
836
|
-
if (!variant?.manageStock || variant.allowBackorder)
|
|
837
|
-
return false;
|
|
838
|
-
return (variant.inventory?.find((row) => row.outletId === MOCK_OUTLET.id)?.stock ?? 0) < quantity;
|
|
839
|
-
};
|
|
840
|
-
// B36e: "N left" on a unit-sold tracked choice — the demo shelf already reads in the variant's own unit.
|
|
841
|
-
const withStockLeft = (choice) => {
|
|
842
|
-
const variant = MOCK_PRODUCTS.flatMap((product) => product.variants).find((candidate) => candidate._id === choice.variantId);
|
|
843
|
-
const onHand = variant?.inventory?.find((row) => row.outletId === MOCK_OUTLET.id)?.stock;
|
|
844
|
-
return variant?.unitId && variant.manageStock && typeof onHand === 'number'
|
|
845
|
-
? { ...choice, stockLeft: onHand }
|
|
846
|
-
: choice;
|
|
847
|
-
};
|
|
848
|
-
const upcharge = (item) => ({
|
|
849
|
-
extraCharge: item.extraCharge,
|
|
850
|
-
quantity: item.quantity,
|
|
851
|
-
available: offered(item),
|
|
852
|
-
});
|
|
853
|
-
const parts = composite.parts
|
|
854
|
-
.map((part) => {
|
|
855
|
-
const items = part.items.flatMap((item) => {
|
|
856
|
-
if (item.variantId) {
|
|
857
|
-
if (item.choices.some((choice) => hidden.has(choice.productId)))
|
|
858
|
-
return [];
|
|
859
|
-
if (!item.unavailable && bookable(item))
|
|
860
|
-
return [{ ...item, unavailable: seatsFor(item) }];
|
|
861
|
-
return item.unavailable || !soldOut(item.variantId, item.quantity)
|
|
862
|
-
? [{ ...item, choices: item.choices.map(withStockLeft) }]
|
|
863
|
-
: [{ ...item, unavailable: 'out_of_stock', choices: [] }];
|
|
864
|
-
}
|
|
865
|
-
const sold = item.choices.filter((choice) => !hidden.has(choice.productId));
|
|
866
|
-
const choices = sold.filter((choice) => !soldOut(choice.variantId, item.quantity));
|
|
867
|
-
const unavailable = item.unavailable ?? (!sold.length ? 'empty' : !choices.length ? 'out_of_stock' : null);
|
|
868
|
-
return [{ ...item, choices: unavailable ? [] : choices.map(withStockLeft), unavailable }];
|
|
869
|
-
});
|
|
870
|
-
const index = part.min === 1 && part.max === 1 ? cheapestCompositeItem(items.map(upcharge)) : undefined;
|
|
871
|
-
const cheapest = index === undefined ? undefined : items[index];
|
|
872
|
-
return {
|
|
873
|
-
...part,
|
|
874
|
-
items,
|
|
875
|
-
defaultPick: cheapest?.variantId ? { itemId: cheapest._id, variantId: cheapest.variantId } : null,
|
|
876
|
-
};
|
|
877
|
-
})
|
|
878
|
-
.filter((part) => part.min > 0 || part.items.some(offered));
|
|
879
|
-
const cheapest = cheapestCompositePrice(parts.map((part) => ({ min: part.min, items: part.items.map(upcharge) })));
|
|
880
|
-
return {
|
|
881
|
-
...composite,
|
|
882
|
-
available: composite.available && parts.every((part) => part.min === 0 || part.items.some(offered)),
|
|
883
|
-
needsDate: parts.some((part) => part.items.some(bookable)),
|
|
884
|
-
fromPrice: composite.basePrice === null || cheapest === undefined ? null : composite.basePrice + cheapest,
|
|
885
|
-
parts,
|
|
886
|
-
};
|
|
887
|
-
}
|
|
888
679
|
export const MOCK_PARKED_ORDERS = [MOCK_PARKED_ORDER_1, MOCK_PARKED_ORDER_2];
|
|
889
680
|
// Compatibility Exports (reassigned by setMockDatabase)
|
|
890
681
|
export let MOCK_USER = MOCK_USERS[0];
|
|
@@ -969,9 +760,6 @@ export function setMockDatabase(config) {
|
|
|
969
760
|
if (config.bookings !== undefined) {
|
|
970
761
|
MOCK_BOOKINGS.splice(0, MOCK_BOOKINGS.length, ...config.bookings);
|
|
971
762
|
}
|
|
972
|
-
if (config.catalogVisibility !== undefined) {
|
|
973
|
-
MOCK_CATALOG_VISIBILITY.splice(0, MOCK_CATALOG_VISIBILITY.length, ...config.catalogVisibility);
|
|
974
|
-
}
|
|
975
763
|
if (MOCK_OUTLETS.length > 0) {
|
|
976
764
|
Object.assign(MOCK_OUTLET_MAIN, MOCK_OUTLETS[0]);
|
|
977
765
|
if (MOCK_OUTLET_MAIN.id === undefined && MOCK_OUTLET_MAIN._id !== undefined) {
|
|
@@ -1344,7 +1132,6 @@ export const buildModifierRows = (modifiers, lineQuantity) => {
|
|
|
1344
1132
|
amount: extendPrice(modifier.unitPrice * modifier.quantity, quantity),
|
|
1345
1133
|
tax: 0,
|
|
1346
1134
|
...(modifier.taxTableId ? { taxTableId: modifier.taxTableId } : {}),
|
|
1347
|
-
...(modifier.componentIndex !== undefined ? { componentIndex: modifier.componentIndex } : {}),
|
|
1348
1135
|
}));
|
|
1349
1136
|
return { rows, modifiersTotal: rows.reduce((sum, row) => sum + row.amount, 0) };
|
|
1350
1137
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -29,14 +29,13 @@ export declare const command: {
|
|
|
29
29
|
readonly addProductNote: import(".").AddProductNote;
|
|
30
30
|
readonly addProductFee: import(".").AddProductFee;
|
|
31
31
|
readonly getProductModifierSelections: import(".").GetProductModifierSelections;
|
|
32
|
-
readonly getCompositePrice: import(".").GetCompositePrice;
|
|
33
|
-
readonly getCompositeAvailability: import(".").GetCompositeAvailability;
|
|
34
32
|
readonly setProductModifierSelections: import(".").SetProductModifierSelections;
|
|
35
33
|
readonly setActiveProductFee: import(".").SetActiveProductFee;
|
|
36
34
|
readonly setActiveProductDiscount: import(".").SetActiveProductDiscount;
|
|
37
35
|
readonly getActiveProduct: import(".").GetActiveProduct;
|
|
38
36
|
readonly setActiveProduct: import(".").SetActiveProduct;
|
|
39
37
|
readonly adjustInventory: import(".").AdjustInventory;
|
|
38
|
+
readonly getCustomStockActions: import(".").GetCustomStockActions;
|
|
40
39
|
readonly addOrderNote: import(".").AddOrderNote;
|
|
41
40
|
readonly addCartFee: import(".").AddCartFee;
|
|
42
41
|
readonly getCurrentCart: import(".").GetCurrentCart;
|
|
@@ -162,7 +161,7 @@ export type { CalculateRefundTotal, CalculateRefundTotalParams, CalculateRefundT
|
|
|
162
161
|
export type { GetRemainingRefundableQuantities, GetRemainingRefundableQuantitiesParams, GetRemainingRefundableQuantitiesResponse, } from './actions/get-remaining-refundable-quantities/types';
|
|
163
162
|
export type { ProcessPartialRefund, ProcessPartialRefundParams, ProcessPartialRefundResponse, } from './actions/process-partial-refund/types';
|
|
164
163
|
export type { RedeemRefund, RedeemRefundParams, RedeemRefundResponse } from './actions/redeem-refund/types';
|
|
165
|
-
export type { GetRefundPlan, GetRefundPlanParams, GetRefundPlanResponse, RefundPlanSource, RefundPlanAllocation, RefundPlanLeg, } from './actions/get-refund-plan/types';
|
|
164
|
+
export type { GetRefundPlan, GetRefundPlanParams, GetRefundPlanResponse, RefundPlanSource, RefundPlanAllocation, RefundPlanLeg, RefundPlanRowType, RefundPlanTaxLine, RefundPlanAmounts, RefundPlanRow, RefundPlanSelectedRow, RefundPlanTotals, RefundPlanBreakdown, } from './actions/get-refund-plan/types';
|
|
166
165
|
export type { CheckPermission, CheckPermissionParams, CheckPermissionResponse } from './actions/check-permission/types';
|
|
167
166
|
export type { InitiateRefund, InitiateRefundParams, InitiateRefundResponse } from './actions/initiate-refund/types';
|
|
168
167
|
export type { GetCurrentCart, GetCurrentCartResponse } from './actions/get-current-cart/types';
|
|
@@ -176,14 +175,13 @@ export type { GetFinalContext, GetFinalContextResponse } from './actions/get-fin
|
|
|
176
175
|
export type { AddProductNote, AddProductNoteParams, AddProductNoteResponse } from './actions/add-product-note/types';
|
|
177
176
|
export type { AddProductFee, AddProductFeeParams, AddProductFeeResponse } from './actions/add-product-fee/types';
|
|
178
177
|
export type { GetProductModifierSelections, GetProductModifierSelectionsParams, GetProductModifierSelectionsResponse, ModifierSelection, ModifierChoiceSelection, } from './actions/get-product-modifier-selections/types';
|
|
179
|
-
export type { GetCompositePrice, GetCompositePriceParams, GetCompositePriceResponse, } from './actions/get-composite-price/types';
|
|
180
|
-
export type { GetCompositeAvailability, GetCompositeAvailabilityParams, GetCompositeAvailabilityResponse, CFCompositeSlot, } from './actions/get-composite-availability/types';
|
|
181
178
|
export type { SetProductModifierSelections, SetProductModifierSelectionsParams, SetProductModifierSelectionsResponse, } from './actions/set-product-modifier-selections/types';
|
|
182
179
|
export type { SetActiveProductFee, SetActiveProductFeeParams, SetActiveProductFeeResponse, } from './actions/set-active-product-fee/types';
|
|
183
180
|
export type { SetActiveProductDiscount, SetActiveProductDiscountParams, SetActiveProductDiscountResponse, } from './actions/set-active-product-discount/types';
|
|
184
181
|
export type { GetActiveProduct, GetActiveProductResponse } from './actions/get-active-product/types';
|
|
185
182
|
export type { SetActiveProduct, SetActiveProductParams, SetActiveProductResponse, } from './actions/set-active-product/types';
|
|
186
|
-
export type { AdjustInventory, AdjustInventoryParams, AdjustInventoryResponse } from './actions/adjust-inventory/types';
|
|
183
|
+
export type { AdjustInventory, AdjustInventoryParams, AdjustInventoryResponse, ManualStockReason, } from './actions/adjust-inventory/types';
|
|
184
|
+
export type { CustomStockActionPayload, GetCustomStockActions, GetCustomStockActionsResponse, } from './actions/get-custom-stock-actions/types';
|
|
187
185
|
export type { AddOrderNote, AddOrderNoteParams, AddOrderNoteResponse } from './actions/add-order-note/types';
|
|
188
186
|
export type { AddCartFee, AddCartFeeParams, AddCartFeeResponse } from './actions/add-cart-fee/types';
|
|
189
187
|
export type { ClearCart, ClearCartResponse } from './actions/clear-cart/types';
|
package/dist/index.js
CHANGED
|
@@ -28,14 +28,13 @@ import { updateCartItemQuantity } from './actions/update-cart-item-quantity/acti
|
|
|
28
28
|
import { addProductNote } from './actions/add-product-note/action';
|
|
29
29
|
import { addProductFee } from './actions/add-product-fee/action';
|
|
30
30
|
import { getProductModifierSelections } from './actions/get-product-modifier-selections/action';
|
|
31
|
-
import { getCompositePrice } from './actions/get-composite-price/action';
|
|
32
|
-
import { getCompositeAvailability } from './actions/get-composite-availability/action';
|
|
33
31
|
import { setProductModifierSelections } from './actions/set-product-modifier-selections/action';
|
|
34
32
|
import { setActiveProductFee } from './actions/set-active-product-fee/action';
|
|
35
33
|
import { setActiveProductDiscount } from './actions/set-active-product-discount/action';
|
|
36
34
|
import { getActiveProduct } from './actions/get-active-product/action';
|
|
37
35
|
import { setActiveProduct } from './actions/set-active-product/action';
|
|
38
36
|
import { adjustInventory } from './actions/adjust-inventory/action';
|
|
37
|
+
import { getCustomStockActions } from './actions/get-custom-stock-actions/action';
|
|
39
38
|
// Order Actions
|
|
40
39
|
import { addOrderNote } from './actions/add-order-note/action';
|
|
41
40
|
import { addCartFee } from './actions/add-cart-fee/action';
|
|
@@ -176,14 +175,13 @@ export const command = {
|
|
|
176
175
|
addProductNote,
|
|
177
176
|
addProductFee,
|
|
178
177
|
getProductModifierSelections,
|
|
179
|
-
getCompositePrice,
|
|
180
|
-
getCompositeAvailability,
|
|
181
178
|
setProductModifierSelections,
|
|
182
179
|
setActiveProductFee,
|
|
183
180
|
setActiveProductDiscount,
|
|
184
181
|
getActiveProduct,
|
|
185
182
|
setActiveProduct,
|
|
186
183
|
adjustInventory,
|
|
184
|
+
getCustomStockActions,
|
|
187
185
|
// Order Actions
|
|
188
186
|
addOrderNote,
|
|
189
187
|
addCartFee,
|
|
@@ -13,8 +13,6 @@ import { mockRemoveOrderNote } from '../../actions/remove-order-note/mock';
|
|
|
13
13
|
import { mockAddProductDiscount } from '../../actions/add-product-discount/mock';
|
|
14
14
|
import { mockAddProductFee } from '../../actions/add-product-fee/mock';
|
|
15
15
|
import { mockGetProductModifierSelections } from '../../actions/get-product-modifier-selections/mock';
|
|
16
|
-
import { mockGetCompositePrice } from '../../actions/get-composite-price/mock';
|
|
17
|
-
import { mockGetCompositeAvailability } from '../../actions/get-composite-availability/mock';
|
|
18
16
|
import { mockSetProductModifierSelections } from '../../actions/set-product-modifier-selections/mock';
|
|
19
17
|
import { mockRemoveProductDiscount } from '../../actions/remove-product-discount/mock';
|
|
20
18
|
import { mockRemoveProductFee } from '../../actions/remove-product-fee/mock';
|
|
@@ -28,6 +26,7 @@ import { mockRemoveProductFromCart } from '../../actions/remove-product-from-car
|
|
|
28
26
|
import { mockRemoveCartDiscount } from '../../actions/remove-cart-discount/mock';
|
|
29
27
|
import { mockUpdateCartItemQuantity } from '../../actions/update-cart-item-quantity/mock';
|
|
30
28
|
import { mockAdjustInventory } from '../../actions/adjust-inventory/mock';
|
|
29
|
+
import { mockGetCustomStockActions } from '../../actions/get-custom-stock-actions/mock';
|
|
31
30
|
import { mockAssignCustomer } from '../../actions/assign-customer/mock';
|
|
32
31
|
import { mockAuthenticateUser } from '../../actions/authenticate-user/mock';
|
|
33
32
|
import { mockCalculateRefundTotal } from '../../actions/calculate-refund-total/mock';
|
|
@@ -124,8 +123,6 @@ export const RENDER_MOCKS = {
|
|
|
124
123
|
addProductDiscount: mockAddProductDiscount,
|
|
125
124
|
addProductFee: mockAddProductFee,
|
|
126
125
|
getProductModifierSelections: mockGetProductModifierSelections,
|
|
127
|
-
getCompositePrice: mockGetCompositePrice,
|
|
128
|
-
getCompositeAvailability: mockGetCompositeAvailability,
|
|
129
126
|
setProductModifierSelections: mockSetProductModifierSelections,
|
|
130
127
|
setActiveProductFee: mockSetActiveProductFee,
|
|
131
128
|
setActiveProductDiscount: mockSetActiveProductDiscount,
|
|
@@ -136,6 +133,7 @@ export const RENDER_MOCKS = {
|
|
|
136
133
|
removeProductFromCart: mockRemoveProductFromCart,
|
|
137
134
|
updateCartItemQuantity: mockUpdateCartItemQuantity,
|
|
138
135
|
adjustInventory: mockAdjustInventory,
|
|
136
|
+
getCustomStockActions: mockGetCustomStockActions,
|
|
139
137
|
assignCustomer: mockAssignCustomer,
|
|
140
138
|
authenticateUser: mockAuthenticateUser,
|
|
141
139
|
calculateRefundTotal: mockCalculateRefundTotal,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExampleFunction, GetProducts, AddCustomSale, EditCustomSale, GetCustomers, AssignCustomer, AddCustomer, EditCustomer, GetCategories, GetOrders, GetRefunds, GetTaxTables, AddProductDiscount, AddProductToCart, RemoveProductFromCart, UpdateCartItemQuantity, AddCartDiscount, GetContext, GetFinalContext, AddProductNote, AddProductFee, GetProductModifierSelections,
|
|
1
|
+
import type { ExampleFunction, GetProducts, AddCustomSale, EditCustomSale, GetCustomers, AssignCustomer, AddCustomer, EditCustomer, GetCategories, GetOrders, GetRefunds, GetTaxTables, GetCustomStockActions, AddProductDiscount, AddProductToCart, RemoveProductFromCart, UpdateCartItemQuantity, AddCartDiscount, GetContext, GetFinalContext, AddProductNote, AddProductFee, GetProductModifierSelections, SetProductModifierSelections, SetActiveProductFee, SetActiveProductDiscount, GetActiveProduct, SetActiveProduct, AdjustInventory, AddOrderNote, AddCartFee, ClearCart, ParkOrder, ResumeParkedOrder, DeleteParkedOrder, VoidOrder, InitiateRefund, CashPayment, GetCashRoundingAmount, TapToPayPayment, TerminalPayment, ExtensionPayment, RedeemPayment, AddNonRevenueItem, AddCustomerNote, RemoveCustomerNote, RemoveCustomerFromCart, GoToStationHome, OpenCashDrawer, ShowNotification, ShowConfirmation, AuthenticateUser, PartialPayment, SwitchUser, SetRefundStockAction, SelectAllRefundItems, ResetRefundDetails, CalculateRefundTotal, GetRemainingRefundableQuantities, ProcessPartialRefund, RedeemRefund, GetRefundPlan, CheckPermission, GetCurrentCart, Print, SetActiveOrder, GetCustomTables, GetCustomTableData, UpsertCustomTableData, DeleteCustomTableData, GetCustomExtensions, GetCurrentCompanyCustomExtensions, GetCustomExtensionCustomTables, GetCustomTableFields, GetSecretsKeys, GetSecretVal, SetSecretVal, GetUsers, GetRoles, RemoveCartDiscount, GetActiveOrder, GetActiveCustomer, SetActiveCustomer, GetActiveOutlet, GetActiveStation, GetActiveSession, GetActiveUser, SetActiveUser, SetActiveRefund, RemoveProductDiscount, RemoveProductFee, RemoveProductNote, RemoveCartFee, RemoveOrderNote, RemoveCustomSale, RemoveNonRevenueItem, CanTransition, GetAvailableTransitions, ApplyTransition, IntegrationPayment, GetSmartGridLayout, SaveSmartGridLayout, SendEmail, SendSms, GetBookingResources, GetBookingAvailability, GetBookings, HoldBooking, AddBookingToCart, RemoveBookingFromCart, CancelBooking, CreatePaymentLink, ChargeMoto, GetTimeClockStatus } from '../../index';
|
|
2
2
|
export interface RenderProviderActions {
|
|
3
3
|
exampleFunction: ExampleFunction;
|
|
4
4
|
getProducts: GetProducts;
|
|
@@ -29,14 +29,13 @@ export interface RenderProviderActions {
|
|
|
29
29
|
addProductNote: AddProductNote;
|
|
30
30
|
addProductFee: AddProductFee;
|
|
31
31
|
getProductModifierSelections: GetProductModifierSelections;
|
|
32
|
-
getCompositePrice: GetCompositePrice;
|
|
33
|
-
getCompositeAvailability: GetCompositeAvailability;
|
|
34
32
|
setProductModifierSelections: SetProductModifierSelections;
|
|
35
33
|
setActiveProductFee: SetActiveProductFee;
|
|
36
34
|
setActiveProductDiscount: SetActiveProductDiscount;
|
|
37
35
|
getActiveProduct: GetActiveProduct;
|
|
38
36
|
setActiveProduct: SetActiveProduct;
|
|
39
37
|
adjustInventory: AdjustInventory;
|
|
38
|
+
getCustomStockActions: GetCustomStockActions;
|
|
40
39
|
addOrderNote: AddOrderNote;
|
|
41
40
|
addCartFee: AddCartFee;
|
|
42
41
|
clearCart: ClearCart;
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* Products Topic Definition
|
|
3
3
|
* Defines the products topic and its available event types
|
|
4
4
|
*/
|
|
5
|
-
import type { TopicDefinition } from
|
|
5
|
+
import type { TopicDefinition } from "../../types";
|
|
6
6
|
export declare const productsTopic: TopicDefinition;
|
|
7
|
-
export * from
|
|
7
|
+
export * from "./types";
|
|
@@ -3,46 +3,31 @@
|
|
|
3
3
|
* Defines the products topic and its available event types
|
|
4
4
|
*/
|
|
5
5
|
export const productsTopic = {
|
|
6
|
-
id:
|
|
7
|
-
name:
|
|
8
|
-
description:
|
|
6
|
+
id: "products",
|
|
7
|
+
name: "Products",
|
|
8
|
+
description: "Topic for product-related events",
|
|
9
9
|
eventTypes: [
|
|
10
10
|
{
|
|
11
|
-
id:
|
|
12
|
-
name:
|
|
13
|
-
description:
|
|
11
|
+
id: "product-created",
|
|
12
|
+
name: "Product Created",
|
|
13
|
+
description: "Published when a new product is synced/created"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
|
-
id:
|
|
17
|
-
name:
|
|
18
|
-
description:
|
|
16
|
+
id: "product-updated",
|
|
17
|
+
name: "Product Updated",
|
|
18
|
+
description: "Published when a product is synced/updated"
|
|
19
19
|
},
|
|
20
20
|
{
|
|
21
|
-
id:
|
|
22
|
-
name:
|
|
23
|
-
description: "Published when a
|
|
21
|
+
id: "set-active-product",
|
|
22
|
+
name: "Set Active Product",
|
|
23
|
+
description: "Published when a product is set as the active product"
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
|
-
id:
|
|
27
|
-
name:
|
|
28
|
-
description:
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
id: 'inventory-changed',
|
|
32
|
-
name: 'Inventory Changed',
|
|
33
|
-
description: "Published when a variant's stock at an outlet syncs; re-ask getProducts",
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
id: 'set-active-product',
|
|
37
|
-
name: 'Set Active Product',
|
|
38
|
-
description: 'Published when a product is set as the active product',
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
id: 'get-active-product',
|
|
42
|
-
name: 'Get Active Product',
|
|
43
|
-
description: 'Published when a product is retrieved as the active product',
|
|
44
|
-
},
|
|
45
|
-
],
|
|
26
|
+
id: "get-active-product",
|
|
27
|
+
name: "Get Active Product",
|
|
28
|
+
description: "Published when a product is retrieved as the active product"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
46
31
|
};
|
|
47
32
|
// Re-export types
|
|
48
|
-
export * from
|
|
33
|
+
export * from "./types";
|
|
@@ -2,19 +2,13 @@
|
|
|
2
2
|
* Products Topic Types
|
|
3
3
|
* Aggregated types for all product-related events
|
|
4
4
|
*/
|
|
5
|
-
export * from
|
|
6
|
-
export * from
|
|
7
|
-
export * from
|
|
8
|
-
export * from
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
import type {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
import type { CatalogVisibilityChangedPayload } from './catalog-visibility-changed/types';
|
|
16
|
-
import type { InventoryChangedPayload } from './inventory-changed/types';
|
|
17
|
-
import type { ProductSetActivePayload } from './product-set-active/types';
|
|
18
|
-
import type { ProductGetActivePayload } from './product-get-active/types';
|
|
19
|
-
export type ProductsEventPayload = ProductCreatedPayload | ProductUpdatedPayload | CompositeChangedPayload | CatalogVisibilityChangedPayload | InventoryChangedPayload | ProductSetActivePayload | ProductGetActivePayload;
|
|
20
|
-
export type ProductsEventType = 'product-created' | 'product-updated' | 'composite-changed' | 'catalog-visibility-changed' | 'inventory-changed' | 'set-active-product' | 'get-active-product';
|
|
5
|
+
export * from "./product-created/types";
|
|
6
|
+
export * from "./product-updated/types";
|
|
7
|
+
export * from "./product-set-active/types";
|
|
8
|
+
export * from "./product-get-active/types";
|
|
9
|
+
import type { ProductCreatedPayload } from "./product-created/types";
|
|
10
|
+
import type { ProductUpdatedPayload } from "./product-updated/types";
|
|
11
|
+
import type { ProductSetActivePayload } from "./product-set-active/types";
|
|
12
|
+
import type { ProductGetActivePayload } from "./product-get-active/types";
|
|
13
|
+
export type ProductsEventPayload = ProductCreatedPayload | ProductUpdatedPayload | ProductSetActivePayload | ProductGetActivePayload;
|
|
14
|
+
export type ProductsEventType = "product-created" | "product-updated" | "set-active-product" | "get-active-product";
|
|
@@ -3,10 +3,7 @@
|
|
|
3
3
|
* Aggregated types for all product-related events
|
|
4
4
|
*/
|
|
5
5
|
// Re-export all event types
|
|
6
|
-
export * from
|
|
7
|
-
export * from
|
|
8
|
-
export * from
|
|
9
|
-
export * from
|
|
10
|
-
export * from './inventory-changed/types';
|
|
11
|
-
export * from './product-set-active/types';
|
|
12
|
-
export * from './product-get-active/types';
|
|
6
|
+
export * from "./product-created/types";
|
|
7
|
+
export * from "./product-updated/types";
|
|
8
|
+
export * from "./product-set-active/types";
|
|
9
|
+
export * from "./product-get-active/types";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@final-commerce/command-frame",
|
|
3
|
-
"version": "0.9.0
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Commands Frame library",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"ignoreBranchesMissingTickets": true
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@final-commerce/common": "2.5.0
|
|
60
|
+
"@final-commerce/common": "2.5.0"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@commitlint/cli": "^19.0.0",
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Get composite availability action (read-only, B41)
|
|
3
|
-
* Calls the getCompositeAvailability action on the parent window
|
|
4
|
-
*/
|
|
5
|
-
import { commandFrameClient } from '../../client';
|
|
6
|
-
export const getCompositeAvailability = async (params) => {
|
|
7
|
-
return await commandFrameClient.call('getCompositeAvailability', params);
|
|
8
|
-
};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { MOCK_PRODUCTS, mockBookingAvailability, mockCompositeAtOutlet, mockIsBookable } from '../../demo/database';
|
|
2
|
-
// The host's answer (kaching `getCompositeAvailability`): the starts at which every bookable the picks name has the seats
|
|
3
|
-
// they need — of one resource, else of several together.
|
|
4
|
-
export const mockGetCompositeAvailability = async (params) => {
|
|
5
|
-
console.log('[Mock] getCompositeAvailability called', params);
|
|
6
|
-
const timestamp = new Date().toISOString();
|
|
7
|
-
const refuse = (reason) => ({ success: false, reason, slots: [], timeZone: null, timestamp });
|
|
8
|
-
const product = MOCK_PRODUCTS.find((candidate) => candidate.variants.some((v) => v._id === params?.variantId));
|
|
9
|
-
if (!product)
|
|
10
|
-
throw new Error(`Variant with ID ${params?.variantId} not found`);
|
|
11
|
-
if (!product.composite)
|
|
12
|
-
return refuse(`${product.name} is not a composite: it takes no composite picks`);
|
|
13
|
-
const composite = mockCompositeAtOutlet(product.composite);
|
|
14
|
-
const picks = params.composite ??
|
|
15
|
-
composite.parts.flatMap((part) => (part.defaultPick ? [part.defaultPick] : []));
|
|
16
|
-
const seats = new Map();
|
|
17
|
-
for (const pick of picks) {
|
|
18
|
-
const item = composite.parts.flatMap((part) => part.items).find((candidate) => candidate._id === pick.itemId);
|
|
19
|
-
const productId = item?.choices.find((choice) => choice.variantId === pick.variantId)?.productId;
|
|
20
|
-
if (!item || !productId || !mockIsBookable(productId))
|
|
21
|
-
continue;
|
|
22
|
-
const entry = seats.get(productId) ?? { seats: 0, resourceId: pick.resourceId };
|
|
23
|
-
seats.set(productId, { ...entry, seats: entry.seats + item.quantity * (pick.quantity ?? 1) });
|
|
24
|
-
}
|
|
25
|
-
if (!seats.size)
|
|
26
|
-
return refuse(`${product.name}: none of these picks is booked for a date`);
|
|
27
|
-
const from = params.fromDay ? new Date(`${params.fromDay}T00:00:00`) : new Date();
|
|
28
|
-
const to = new Date(from.getFullYear(), from.getMonth(), from.getDate() + Math.max(1, params.days ?? 1));
|
|
29
|
-
const perProduct = [...seats].map(([productId, need]) => {
|
|
30
|
-
const { slots, timeZone } = mockBookingAvailability(productId, from, to);
|
|
31
|
-
const fits = slots.filter((slot) => {
|
|
32
|
-
const resources = slot.resources.filter((resource) => !need.resourceId || resource.resourceId === need.resourceId);
|
|
33
|
-
return (slot.canStart &&
|
|
34
|
-
(need.resourceId
|
|
35
|
-
? resources.some((r) => r.free >= need.seats)
|
|
36
|
-
: resources.reduce((sum, r) => sum + r.free, 0) >= need.seats));
|
|
37
|
-
});
|
|
38
|
-
return { fits, timeZone };
|
|
39
|
-
});
|
|
40
|
-
const [first, ...rest] = perProduct;
|
|
41
|
-
const slots = first.fits
|
|
42
|
-
.filter((slot) => rest.every(({ fits }) => fits.some((other) => +new Date(other.startAt) === +new Date(slot.startAt))))
|
|
43
|
-
.map((slot) => ({ startAt: slot.startAt, dayKey: slot.dayKey ?? slot.startAt.slice(0, 10) }));
|
|
44
|
-
return { success: true, slots, timeZone: first.timeZone ?? null, timestamp };
|
|
45
|
-
};
|