@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
@@ -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 { cheapestCompositeItem, cheapestCompositePrice, extendPrice, resolveUnit, toBase, } from '@final-commerce/common';
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, GetCompositePrice, GetCompositeAvailability, 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';
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 '../../types';
5
+ import type { TopicDefinition } from "../../types";
6
6
  export declare const productsTopic: TopicDefinition;
7
- export * from './types';
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: 'products',
7
- name: 'Products',
8
- description: 'Topic for product-related events',
6
+ id: "products",
7
+ name: "Products",
8
+ description: "Topic for product-related events",
9
9
  eventTypes: [
10
10
  {
11
- id: 'product-created',
12
- name: 'Product Created',
13
- description: 'Published when a new product is synced/created',
11
+ id: "product-created",
12
+ name: "Product Created",
13
+ description: "Published when a new product is synced/created"
14
14
  },
15
15
  {
16
- id: 'product-updated',
17
- name: 'Product Updated',
18
- description: 'Published when a product is synced/updated',
16
+ id: "product-updated",
17
+ name: "Product Updated",
18
+ description: "Published when a product is synced/updated"
19
19
  },
20
20
  {
21
- id: 'composite-changed',
22
- name: 'Composite Changed',
23
- description: "Published when a composite's part or item is synced; re-ask getProducts",
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: 'catalog-visibility-changed',
27
- name: 'Catalog Visibility Changed',
28
- description: 'Published when a product is hidden or shown at an outlet; re-ask getProducts',
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 './types';
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 './product-created/types';
6
- export * from './product-updated/types';
7
- export * from './composite-changed/types';
8
- export * from './catalog-visibility-changed/types';
9
- export * from './inventory-changed/types';
10
- export * from './product-set-active/types';
11
- export * from './product-get-active/types';
12
- import type { ProductCreatedPayload } from './product-created/types';
13
- import type { ProductUpdatedPayload } from './product-updated/types';
14
- import type { CompositeChangedPayload } from './composite-changed/types';
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 './product-created/types';
7
- export * from './product-updated/types';
8
- export * from './composite-changed/types';
9
- export * from './catalog-visibility-changed/types';
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-staging.1",
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-staging.1"
60
+ "@final-commerce/common": "2.5.0"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@commitlint/cli": "^19.0.0",
@@ -1,6 +0,0 @@
1
- /**
2
- * Get composite availability action (read-only, B41)
3
- * Calls the getCompositeAvailability action on the parent window
4
- */
5
- import type { GetCompositeAvailability } from './types';
6
- export declare const getCompositeAvailability: GetCompositeAvailability;
@@ -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,2 +0,0 @@
1
- import { GetCompositeAvailability } from './types';
2
- export declare const mockGetCompositeAvailability: GetCompositeAvailability;
@@ -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
- };