@final-commerce/command-frame 0.10.0-staging.4 → 0.10.0-staging.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/add-product-to-cart/mock.d.ts +3 -0
- package/dist/actions/add-product-to-cart/mock.js +7 -5
- 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-composite-availability/mock.js +4 -2
- package/dist/actions/get-composite-price/mock.js +11 -7
- package/dist/actions/get-composite-price/types.d.ts +13 -4
- 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/set-variant-unavailable/mock.js +14 -4
- package/dist/actions/set-variant-unavailable/types.d.ts +2 -0
- package/dist/actions/update-cart-item-quantity/mock.js +18 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/projects/render/mocks.js +2 -0
- package/dist/projects/render/types.d.ts +2 -1
- package/dist/pubsub/topics/products/index.js +5 -0
- package/dist/pubsub/topics/products/types.d.ts +4 -2
- package/dist/pubsub/topics/products/types.js +1 -0
- package/dist/pubsub/topics/products/variant-unavailability-changed/types.d.ts +19 -0
- package/dist/pubsub/topics/products/variant-unavailability-changed/types.js +1 -0
- package/package.json +2 -2
|
@@ -7,8 +7,11 @@ export declare function compositePicksRefusal(composite: CFComposite, picks: CFC
|
|
|
7
7
|
* left empty is not listed. A copy — change both in one step. */
|
|
8
8
|
export declare function mockPicksStillNeeded(composite: CFComposite, picks: CFCompositePick[]): {
|
|
9
9
|
partId: string;
|
|
10
|
+
name: string | null;
|
|
10
11
|
needed: number;
|
|
11
12
|
}[];
|
|
13
|
+
/** The parts whose picks already reach their `max` — a picker disables "+" on them. A copy of the host's. */
|
|
14
|
+
export declare const mockFullPartIds: (composite: CFComposite, picks: CFCompositePick[]) => string[];
|
|
12
15
|
type MockCompositeLine = {
|
|
13
16
|
price: number;
|
|
14
17
|
components: CFCartLineComponent[];
|
|
@@ -275,17 +275,19 @@ function mockSelectionsRefusal(modifiers, selections) {
|
|
|
275
275
|
}
|
|
276
276
|
return null;
|
|
277
277
|
}
|
|
278
|
+
const mockPartPicks = (part, picks) => picks
|
|
279
|
+
.filter((pick) => part.items.some((item) => item._id === pick.itemId))
|
|
280
|
+
.reduce((sum, pick) => sum + (pick.quantity ?? 1), 0);
|
|
278
281
|
/** The host's `picksStillNeeded` (kaching `resolveComposite.ts`): per part, what is left of its min; an Optional part
|
|
279
282
|
* left empty is not listed. A copy — change both in one step. */
|
|
280
283
|
export function mockPicksStillNeeded(composite, picks) {
|
|
281
284
|
return composite.parts.flatMap((part) => {
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
.reduce((sum, pick) => sum + (pick.quantity ?? 1), 0);
|
|
285
|
-
const needed = Math.max(0, part.min - count);
|
|
286
|
-
return needed > 0 ? [{ partId: part._id, needed }] : [];
|
|
285
|
+
const needed = Math.max(0, part.min - mockPartPicks(part, picks));
|
|
286
|
+
return needed > 0 ? [{ partId: part._id, name: part.name, needed }] : [];
|
|
287
287
|
});
|
|
288
288
|
}
|
|
289
|
+
/** The parts whose picks already reach their `max` — a picker disables "+" on them. A copy of the host's. */
|
|
290
|
+
export const mockFullPartIds = (composite, picks) => composite.parts.filter((part) => mockPartPicks(part, picks) >= part.max).map((part) => part._id);
|
|
289
291
|
/** kaching `buildCompositeLine` (B31): a component's share of ONE composite = the composite price split by the picked
|
|
290
292
|
* variant's price × units (all 0 → units) + its own upcharge; Σ = price. Item modifiers flat with `componentIndex`
|
|
291
293
|
* and quantity × the component's units. A copy — change both in one step. */
|
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
import { MOCK_PRODUCTS } from '../../demo/database';
|
|
2
|
+
// Same rules and messages as the kaching handler.
|
|
3
|
+
const STOCK_TYPE_BY_REASON = {
|
|
4
|
+
STOCK_RECEIVED: 'add',
|
|
5
|
+
RESTOCK_RETURN: 'add',
|
|
6
|
+
DAMAGE: 'subtract',
|
|
7
|
+
THEFT: 'subtract',
|
|
8
|
+
LOSS: 'subtract',
|
|
9
|
+
INVENTORY_RECOUNT: 'set',
|
|
10
|
+
};
|
|
2
11
|
export const mockAdjustInventory = async (params) => {
|
|
3
12
|
console.log('[Mock] adjustInventory called', params);
|
|
13
|
+
if (params?.specificAction != null) {
|
|
14
|
+
const { specificAction, stockType, customActionId } = params;
|
|
15
|
+
if (customActionId)
|
|
16
|
+
throw new Error('Pass either customActionId or specificAction, not both');
|
|
17
|
+
const reasonStockType = STOCK_TYPE_BY_REASON[specificAction];
|
|
18
|
+
if (!reasonStockType)
|
|
19
|
+
throw new Error(`Unknown specificAction: ${specificAction}`);
|
|
20
|
+
if (reasonStockType !== stockType) {
|
|
21
|
+
throw new Error(`specificAction ${specificAction} requires stockType '${reasonStockType}', got '${stockType}'`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
4
24
|
let newStock = 0;
|
|
5
25
|
// Real handler keys off variantId (falling back to the active product's
|
|
6
26
|
// variant); mirror that here by finding the owning product for the variant.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** The manual reasons a person can pick, as hub-api's InventorySpecificActionType names them. */
|
|
2
|
+
export type ManualStockReason = 'STOCK_RECEIVED' | 'RESTOCK_RETURN' | 'DAMAGE' | 'THEFT' | 'LOSS' | 'INVENTORY_RECOUNT';
|
|
1
3
|
export interface AdjustInventoryParams {
|
|
2
4
|
/** String to preserve precision. */
|
|
3
5
|
amount: string;
|
|
@@ -5,6 +7,17 @@ export interface AdjustInventoryParams {
|
|
|
5
7
|
stockType: 'add' | 'subtract' | 'set';
|
|
6
8
|
/** Variant to adjust. Omit to use the active product's selected variant. */
|
|
7
9
|
variantId?: string;
|
|
10
|
+
/**
|
|
11
|
+
* A company action from getCustomStockActions. The movement is recorded under its name;
|
|
12
|
+
* `stockType` must match its baseAction (ADD → 'add', REMOVE → 'subtract', RECOUNT → 'set').
|
|
13
|
+
*/
|
|
14
|
+
customActionId?: string;
|
|
15
|
+
/**
|
|
16
|
+
* A built-in reason to record instead of the host's default for `stockType`. Must match it:
|
|
17
|
+
* STOCK_RECEIVED / RESTOCK_RETURN → 'add', DAMAGE / THEFT / LOSS → 'subtract', INVENTORY_RECOUNT → 'set'.
|
|
18
|
+
* Rejected together with `customActionId`.
|
|
19
|
+
*/
|
|
20
|
+
specificAction?: ManualStockReason;
|
|
8
21
|
}
|
|
9
22
|
export interface AdjustInventoryResponse {
|
|
10
23
|
success: boolean;
|
|
@@ -5,9 +5,11 @@ export const mockGetCompositeAvailability = async (params) => {
|
|
|
5
5
|
console.log('[Mock] getCompositeAvailability called', params);
|
|
6
6
|
const timestamp = new Date().toISOString();
|
|
7
7
|
const refuse = (reason) => ({ success: false, reason, slots: [], timeZone: null, timestamp });
|
|
8
|
-
|
|
8
|
+
if (!params?.variantId)
|
|
9
|
+
return refuse('variantId is required');
|
|
10
|
+
const product = MOCK_PRODUCTS.find((candidate) => candidate.variants.some((v) => v._id === params.variantId));
|
|
9
11
|
if (!product)
|
|
10
|
-
|
|
12
|
+
return refuse(`Variant with ID ${params.variantId} not found`);
|
|
11
13
|
if (!product.composite)
|
|
12
14
|
return refuse(`${product.name} is not a composite: it takes no composite picks`);
|
|
13
15
|
const composite = mockCompositeAtOutlet(product.composite);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MOCK_CART, MOCK_PRODUCTS, buildModifierRows, mockCompositeAtOutlet, mockCompositeStockRefusal, mockHiddenProductIds, } from '../../demo/database';
|
|
2
|
-
import { compositePicksRefusal, mockCompositeLine, mockNeedsDateRefusal, mockPicksStillNeeded, } from '../add-product-to-cart/mock';
|
|
3
|
-
// The same line the mock addProductToCart builds, priced for
|
|
2
|
+
import { compositePicksRefusal, mockCompositeLine, mockFullPartIds, mockNeedsDateRefusal, mockPicksStillNeeded, } from '../add-product-to-cart/mock';
|
|
3
|
+
// The same line the mock addProductToCart builds, priced for `quantity` composites and added to nothing.
|
|
4
4
|
export const mockGetCompositePrice = async (params) => {
|
|
5
5
|
console.log('[Mock] getCompositePrice called', params);
|
|
6
6
|
const timestamp = new Date().toISOString();
|
|
@@ -12,6 +12,7 @@ export const mockGetCompositePrice = async (params) => {
|
|
|
12
12
|
success: false,
|
|
13
13
|
reason: `${product.name} is not a composite: it takes no composite picks`,
|
|
14
14
|
missing: [],
|
|
15
|
+
fullPartIds: [],
|
|
15
16
|
timestamp,
|
|
16
17
|
};
|
|
17
18
|
}
|
|
@@ -19,19 +20,22 @@ export const mockGetCompositePrice = async (params) => {
|
|
|
19
20
|
// What this outlet sells (the host's catalog-visibility rules).
|
|
20
21
|
const composite = mockCompositeAtOutlet(product.composite, undefined, params.compositeSlot);
|
|
21
22
|
const missing = mockPicksStillNeeded(composite, picks);
|
|
23
|
+
const fullPartIds = mockFullPartIds(composite, picks);
|
|
24
|
+
const quantity = params.quantity ?? 1;
|
|
22
25
|
if (mockHiddenProductIds().has(product._id)) {
|
|
23
|
-
return { success: false, reason: `${product.name} is not sold at this outlet`, missing, timestamp };
|
|
26
|
+
return { success: false, reason: `${product.name} is not sold at this outlet`, missing, fullPartIds, timestamp };
|
|
24
27
|
}
|
|
25
28
|
const line = mockNeedsDateRefusal(product.name, composite, params.compositeSlot) ??
|
|
26
29
|
compositePicksRefusal(composite, picks) ??
|
|
27
30
|
mockCompositeLine(composite, picks, !product.taxTable);
|
|
28
31
|
if (typeof line === 'string')
|
|
29
|
-
return { success: false, reason: line, missing, timestamp };
|
|
32
|
+
return { success: false, reason: line, missing, fullPartIds, timestamp };
|
|
30
33
|
const shortOfStock = mockCompositeStockRefusal([
|
|
31
34
|
...MOCK_CART.products,
|
|
32
|
-
{ variantId: params.variantId, quantity
|
|
35
|
+
{ variantId: params.variantId, quantity, components: line.components },
|
|
33
36
|
]);
|
|
34
37
|
if (shortOfStock)
|
|
35
|
-
return { success: false, reason: shortOfStock, missing, timestamp };
|
|
36
|
-
|
|
38
|
+
return { success: false, reason: shortOfStock, missing, fullPartIds, timestamp };
|
|
39
|
+
const unitTotal = line.price + buildModifierRows(line.modifiers, 1).modifiersTotal;
|
|
40
|
+
return { success: true, total: unitTotal * quantity, unitTotal, missing, fullPartIds, timestamp };
|
|
37
41
|
};
|
|
@@ -8,24 +8,33 @@ export interface GetCompositePriceParams {
|
|
|
8
8
|
compositeSlot?: {
|
|
9
9
|
startAt: string;
|
|
10
10
|
};
|
|
11
|
+
/** How many of this composite, as `addProductToCart({ quantity })` takes it. Defaults to 1. */
|
|
12
|
+
quantity?: number;
|
|
11
13
|
}
|
|
12
14
|
export interface GetCompositePriceResponse {
|
|
13
15
|
success: boolean;
|
|
14
16
|
/** Why these picks are refused — the same refusal and text `addProductToCart` would give. */
|
|
15
17
|
reason?: string;
|
|
16
18
|
/**
|
|
17
|
-
* What
|
|
18
|
-
*
|
|
19
|
+
* What `quantity` composites with these picks add to the cart, minor units: `unitTotal` × `quantity`. Before
|
|
20
|
+
* discounts, fees and tax. Show it; do not recompute it. Absent when refused.
|
|
19
21
|
*/
|
|
20
22
|
total?: number;
|
|
23
|
+
/** What ONE composite with these picks adds: the line price the host would build plus the picked items' modifiers,
|
|
24
|
+
* minor units. Absent when refused. */
|
|
25
|
+
unitTotal?: number;
|
|
21
26
|
/**
|
|
22
|
-
* The parts that still need picks before the composite can be added,
|
|
23
|
-
* required part is filled. Decided by the host — keep Add to cart
|
|
27
|
+
* The parts that still need picks before the composite can be added, with the part's `name` (null = untitled) and
|
|
28
|
+
* how many ("Pick 2 more side"); empty when every required part is filled. Decided by the host — keep Add to cart
|
|
29
|
+
* disabled while this is not empty.
|
|
24
30
|
*/
|
|
25
31
|
missing: {
|
|
26
32
|
partId: string;
|
|
33
|
+
name: string | null;
|
|
27
34
|
needed: number;
|
|
28
35
|
}[];
|
|
36
|
+
/** The parts whose picks already reach their `max` — disable "+" on them. Decided by the host. */
|
|
37
|
+
fullPartIds: string[];
|
|
29
38
|
timestamp: string;
|
|
30
39
|
}
|
|
31
40
|
export type GetCompositePrice = (params: GetCompositePriceParams) => Promise<GetCompositePriceResponse>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const mockGetCustomStockActions = async () => {
|
|
2
|
+
console.log('[Mock] getCustomStockActions called');
|
|
3
|
+
return {
|
|
4
|
+
customStockActions: [
|
|
5
|
+
{ _id: 'mock_custom_action_1', name: 'Opening stock', baseAction: 'ADD' },
|
|
6
|
+
{ _id: 'mock_custom_action_2', name: 'Exhibition loan', baseAction: 'REMOVE' },
|
|
7
|
+
{ _id: 'mock_custom_action_3', name: 'Year-end count', baseAction: 'RECOUNT' },
|
|
8
|
+
],
|
|
9
|
+
timestamp: new Date().toISOString(),
|
|
10
|
+
};
|
|
11
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface CustomStockActionPayload {
|
|
2
|
+
_id: string;
|
|
3
|
+
/** Name the company gave the action, shown in pickers and stock history. */
|
|
4
|
+
name: string;
|
|
5
|
+
/** What the action does to stock — pass the matching `stockType` to adjustInventory. */
|
|
6
|
+
baseAction: 'ADD' | 'REMOVE' | 'RECOUNT';
|
|
7
|
+
}
|
|
8
|
+
export interface GetCustomStockActionsResponse {
|
|
9
|
+
customStockActions: CustomStockActionPayload[];
|
|
10
|
+
timestamp: string;
|
|
11
|
+
}
|
|
12
|
+
export type GetCustomStockActions = () => Promise<GetCustomStockActionsResponse>;
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import { MOCK_OUTLET, MOCK_PRODUCTS } from '../../demo/database';
|
|
2
2
|
export const mockSetVariantUnavailable = async (params) => {
|
|
3
3
|
console.log('[Mock] setVariantUnavailable called', params);
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
const answer = (success, reason) => ({
|
|
5
|
+
success,
|
|
6
|
+
reason,
|
|
7
|
+
variantId: params?.variantId ?? '',
|
|
8
|
+
outletId: MOCK_OUTLET.id,
|
|
9
|
+
unavailable: !!params?.unavailable,
|
|
10
|
+
timestamp: new Date().toISOString(),
|
|
11
|
+
});
|
|
12
|
+
// Same refusals and texts as the host, resolved instead of thrown.
|
|
13
|
+
if (!params?.variantId || typeof params.unavailable !== 'boolean') {
|
|
14
|
+
return answer(false, 'variantId and unavailable are required');
|
|
15
|
+
}
|
|
6
16
|
const { variantId, unavailable } = params;
|
|
7
17
|
const variant = MOCK_PRODUCTS.flatMap((product) => product.variants).find((v) => v._id === variantId);
|
|
8
18
|
if (!variant)
|
|
9
|
-
|
|
19
|
+
return answer(false, `Variant with ID ${variantId} not found`);
|
|
10
20
|
variant.unavailable = unavailable;
|
|
11
|
-
return
|
|
21
|
+
return answer(true);
|
|
12
22
|
};
|
|
@@ -8,7 +8,9 @@ export interface SetVariantUnavailableParams {
|
|
|
8
8
|
unavailable: boolean;
|
|
9
9
|
}
|
|
10
10
|
export interface SetVariantUnavailableResponse {
|
|
11
|
+
/** False when the host refused: missing params, no active outlet or company, unknown variant, offline. */
|
|
11
12
|
success: boolean;
|
|
13
|
+
reason?: string;
|
|
12
14
|
variantId: string;
|
|
13
15
|
outletId: string;
|
|
14
16
|
unavailable: boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { MOCK_CART, MOCK_PRODUCTS, mockPublishEvent } from '../../demo/database';
|
|
2
|
-
import { extendPrice, isValidQuantity } from '@final-commerce/common';
|
|
1
|
+
import { MOCK_BOOKINGS, MOCK_CART, MOCK_PRODUCTS, mockCompositeStockRefusal, mockPublishEvent, } from '../../demo/database';
|
|
2
|
+
import { ReservationStatus, extendPrice, isValidQuantity } from '@final-commerce/common';
|
|
3
3
|
export const mockUpdateCartItemQuantity = (params) => {
|
|
4
4
|
console.log('[Mock] updateCartItemQuantity called', params);
|
|
5
5
|
if (!params?.internalId) {
|
|
@@ -16,6 +16,10 @@ export const mockUpdateCartItemQuantity = (params) => {
|
|
|
16
16
|
}
|
|
17
17
|
const product = MOCK_CART.products[productIndex];
|
|
18
18
|
const previousQuantity = product.quantity;
|
|
19
|
+
// Same refusal and text as the host: a line holding bookings keeps its quantity — its holds are that many seats.
|
|
20
|
+
if (quantity !== 0 && MOCK_CART.reservations?.some((reservation) => reservation.lineItemInternalId === internalId)) {
|
|
21
|
+
throw new Error(`${product.name} holds a booking — its quantity is the seats held: remove the line and add it again with the new quantity (addProductToCart with compositeSlot)`);
|
|
22
|
+
}
|
|
19
23
|
// The line resolved its unit when it was added; a piece-sold line has none and stays whole.
|
|
20
24
|
if (quantity !== 0 &&
|
|
21
25
|
!isValidQuantity(quantity, (product.unit ?? { unitId: 'piece', ratioToBase: 1, precision: 0 }))) {
|
|
@@ -26,6 +30,12 @@ export const mockUpdateCartItemQuantity = (params) => {
|
|
|
26
30
|
// If quantity is 0, remove the item
|
|
27
31
|
if (quantity === 0) {
|
|
28
32
|
MOCK_CART.products.splice(productIndex, 1);
|
|
33
|
+
// Like the host's `dropCompositeLine`: the line's reservations leave with it and their holds are released.
|
|
34
|
+
const linked = (MOCK_CART.reservations ?? []).filter((reservation) => reservation.lineItemInternalId === internalId);
|
|
35
|
+
MOCK_CART.reservations = (MOCK_CART.reservations ?? []).filter((reservation) => !linked.includes(reservation));
|
|
36
|
+
for (const booking of MOCK_BOOKINGS.filter(({ id }) => linked.some(({ bookingId }) => bookingId === id))) {
|
|
37
|
+
booking.status = ReservationStatus.CANCELLED;
|
|
38
|
+
}
|
|
29
39
|
// Recalculate totals
|
|
30
40
|
const lineTotal = extendPrice(product.price, previousQuantity);
|
|
31
41
|
MOCK_CART.subtotal -= lineTotal;
|
|
@@ -50,6 +60,12 @@ export const mockUpdateCartItemQuantity = (params) => {
|
|
|
50
60
|
if (quantity > previousQuantity && (source?.notSoldInPos || variant?.notSoldInPos)) {
|
|
51
61
|
throw new Error(`${source?.name} is not sold in POS`);
|
|
52
62
|
}
|
|
63
|
+
// A raised composite line draws on its components' shelves, like the host's `compositeStockRefusal`.
|
|
64
|
+
if (quantity > previousQuantity && product.components?.length) {
|
|
65
|
+
const refusal = mockCompositeStockRefusal(MOCK_CART.products.map((line) => (line.internalId === internalId ? { ...line, quantity } : line)));
|
|
66
|
+
if (refusal)
|
|
67
|
+
throw new Error(refusal);
|
|
68
|
+
}
|
|
53
69
|
// Update quantity
|
|
54
70
|
product.quantity = quantity;
|
|
55
71
|
// Difference of the two ROUNDED extensions — rounding the delta itself would let the
|
package/dist/index.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export declare const command: {
|
|
|
38
38
|
readonly setActiveProduct: import(".").SetActiveProduct;
|
|
39
39
|
readonly adjustInventory: import(".").AdjustInventory;
|
|
40
40
|
readonly setVariantUnavailable: import(".").SetVariantUnavailable;
|
|
41
|
+
readonly getCustomStockActions: import(".").GetCustomStockActions;
|
|
41
42
|
readonly addOrderNote: import(".").AddOrderNote;
|
|
42
43
|
readonly addCartFee: import(".").AddCartFee;
|
|
43
44
|
readonly getCurrentCart: import(".").GetCurrentCart;
|
|
@@ -184,8 +185,9 @@ export type { SetActiveProductFee, SetActiveProductFeeParams, SetActiveProductFe
|
|
|
184
185
|
export type { SetActiveProductDiscount, SetActiveProductDiscountParams, SetActiveProductDiscountResponse, } from './actions/set-active-product-discount/types';
|
|
185
186
|
export type { GetActiveProduct, GetActiveProductResponse } from './actions/get-active-product/types';
|
|
186
187
|
export type { SetActiveProduct, SetActiveProductParams, SetActiveProductResponse, } from './actions/set-active-product/types';
|
|
187
|
-
export type { AdjustInventory, AdjustInventoryParams, AdjustInventoryResponse } from './actions/adjust-inventory/types';
|
|
188
188
|
export type { SetVariantUnavailable, SetVariantUnavailableParams, SetVariantUnavailableResponse, } from './actions/set-variant-unavailable/types';
|
|
189
|
+
export type { AdjustInventory, AdjustInventoryParams, AdjustInventoryResponse, ManualStockReason, } from './actions/adjust-inventory/types';
|
|
190
|
+
export type { CustomStockActionPayload, GetCustomStockActions, GetCustomStockActionsResponse, } from './actions/get-custom-stock-actions/types';
|
|
189
191
|
export type { AddOrderNote, AddOrderNoteParams, AddOrderNoteResponse } from './actions/add-order-note/types';
|
|
190
192
|
export type { AddCartFee, AddCartFeeParams, AddCartFeeResponse } from './actions/add-cart-fee/types';
|
|
191
193
|
export type { ClearCart, ClearCartResponse } from './actions/clear-cart/types';
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,7 @@ import { getActiveProduct } from './actions/get-active-product/action';
|
|
|
37
37
|
import { setActiveProduct } from './actions/set-active-product/action';
|
|
38
38
|
import { adjustInventory } from './actions/adjust-inventory/action';
|
|
39
39
|
import { setVariantUnavailable } from './actions/set-variant-unavailable/action';
|
|
40
|
+
import { getCustomStockActions } from './actions/get-custom-stock-actions/action';
|
|
40
41
|
// Order Actions
|
|
41
42
|
import { addOrderNote } from './actions/add-order-note/action';
|
|
42
43
|
import { addCartFee } from './actions/add-cart-fee/action';
|
|
@@ -186,6 +187,7 @@ export const command = {
|
|
|
186
187
|
setActiveProduct,
|
|
187
188
|
adjustInventory,
|
|
188
189
|
setVariantUnavailable,
|
|
190
|
+
getCustomStockActions,
|
|
189
191
|
// Order Actions
|
|
190
192
|
addOrderNote,
|
|
191
193
|
addCartFee,
|
|
@@ -29,6 +29,7 @@ import { mockRemoveCartDiscount } from '../../actions/remove-cart-discount/mock'
|
|
|
29
29
|
import { mockUpdateCartItemQuantity } from '../../actions/update-cart-item-quantity/mock';
|
|
30
30
|
import { mockAdjustInventory } from '../../actions/adjust-inventory/mock';
|
|
31
31
|
import { mockSetVariantUnavailable } from '../../actions/set-variant-unavailable/mock';
|
|
32
|
+
import { mockGetCustomStockActions } from '../../actions/get-custom-stock-actions/mock';
|
|
32
33
|
import { mockAssignCustomer } from '../../actions/assign-customer/mock';
|
|
33
34
|
import { mockAuthenticateUser } from '../../actions/authenticate-user/mock';
|
|
34
35
|
import { mockCalculateRefundTotal } from '../../actions/calculate-refund-total/mock';
|
|
@@ -138,6 +139,7 @@ export const RENDER_MOCKS = {
|
|
|
138
139
|
updateCartItemQuantity: mockUpdateCartItemQuantity,
|
|
139
140
|
adjustInventory: mockAdjustInventory,
|
|
140
141
|
setVariantUnavailable: mockSetVariantUnavailable,
|
|
142
|
+
getCustomStockActions: mockGetCustomStockActions,
|
|
141
143
|
assignCustomer: mockAssignCustomer,
|
|
142
144
|
authenticateUser: mockAuthenticateUser,
|
|
143
145
|
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, SetVariantUnavailable, 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, GetCompositePrice, GetCompositeAvailability, SetProductModifierSelections, SetActiveProductFee, SetActiveProductDiscount, GetActiveProduct, SetActiveProduct, AdjustInventory, SetVariantUnavailable, 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;
|
|
@@ -38,6 +38,7 @@ export interface RenderProviderActions {
|
|
|
38
38
|
setActiveProduct: SetActiveProduct;
|
|
39
39
|
adjustInventory: AdjustInventory;
|
|
40
40
|
setVariantUnavailable: SetVariantUnavailable;
|
|
41
|
+
getCustomStockActions: GetCustomStockActions;
|
|
41
42
|
addOrderNote: AddOrderNote;
|
|
42
43
|
addCartFee: AddCartFee;
|
|
43
44
|
clearCart: ClearCart;
|
|
@@ -27,6 +27,11 @@ export const productsTopic = {
|
|
|
27
27
|
name: 'Catalog Visibility Changed',
|
|
28
28
|
description: 'Published when a product is hidden or shown at an outlet; re-ask getProducts',
|
|
29
29
|
},
|
|
30
|
+
{
|
|
31
|
+
id: 'variant-unavailability-changed',
|
|
32
|
+
name: 'Variant Unavailability Changed',
|
|
33
|
+
description: 'Published when a variant is marked sold out at an outlet or unmarked; re-ask getProducts',
|
|
34
|
+
},
|
|
30
35
|
{
|
|
31
36
|
id: 'inventory-changed',
|
|
32
37
|
name: 'Inventory Changed',
|
|
@@ -6,6 +6,7 @@ export * from './product-created/types';
|
|
|
6
6
|
export * from './product-updated/types';
|
|
7
7
|
export * from './composite-changed/types';
|
|
8
8
|
export * from './catalog-visibility-changed/types';
|
|
9
|
+
export * from './variant-unavailability-changed/types';
|
|
9
10
|
export * from './inventory-changed/types';
|
|
10
11
|
export * from './product-set-active/types';
|
|
11
12
|
export * from './product-get-active/types';
|
|
@@ -13,8 +14,9 @@ import type { ProductCreatedPayload } from './product-created/types';
|
|
|
13
14
|
import type { ProductUpdatedPayload } from './product-updated/types';
|
|
14
15
|
import type { CompositeChangedPayload } from './composite-changed/types';
|
|
15
16
|
import type { CatalogVisibilityChangedPayload } from './catalog-visibility-changed/types';
|
|
17
|
+
import type { VariantUnavailabilityChangedPayload } from './variant-unavailability-changed/types';
|
|
16
18
|
import type { InventoryChangedPayload } from './inventory-changed/types';
|
|
17
19
|
import type { ProductSetActivePayload } from './product-set-active/types';
|
|
18
20
|
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';
|
|
21
|
+
export type ProductsEventPayload = ProductCreatedPayload | ProductUpdatedPayload | CompositeChangedPayload | CatalogVisibilityChangedPayload | VariantUnavailabilityChangedPayload | InventoryChangedPayload | ProductSetActivePayload | ProductGetActivePayload;
|
|
22
|
+
export type ProductsEventType = 'product-created' | 'product-updated' | 'composite-changed' | 'catalog-visibility-changed' | 'variant-unavailability-changed' | 'inventory-changed' | 'set-active-product' | 'get-active-product';
|
|
@@ -7,6 +7,7 @@ export * from './product-created/types';
|
|
|
7
7
|
export * from './product-updated/types';
|
|
8
8
|
export * from './composite-changed/types';
|
|
9
9
|
export * from './catalog-visibility-changed/types';
|
|
10
|
+
export * from './variant-unavailability-changed/types';
|
|
10
11
|
export * from './inventory-changed/types';
|
|
11
12
|
export * from './product-set-active/types';
|
|
12
13
|
export * from './product-get-active/types';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { TopicEvent } from '../../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Payload for variant-unavailability-changed: a variant was marked sold out at an outlet, or the mark was removed
|
|
4
|
+
* (`isDeleted`). `getProducts` reports the mark as `variant.unavailable` and a composite refuses a marked item —
|
|
5
|
+
* debounce, then re-ask `getProducts`.
|
|
6
|
+
*/
|
|
7
|
+
export interface VariantUnavailabilityChangedPayload {
|
|
8
|
+
unavailability: {
|
|
9
|
+
_id: string;
|
|
10
|
+
productId: string;
|
|
11
|
+
variantId: string;
|
|
12
|
+
outletId: string;
|
|
13
|
+
isDeleted?: boolean;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Typed event for variant-unavailability-changed
|
|
18
|
+
*/
|
|
19
|
+
export type VariantUnavailabilityChangedEvent = TopicEvent<VariantUnavailabilityChangedPayload>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@final-commerce/command-frame",
|
|
3
|
-
"version": "0.10.0-staging.
|
|
3
|
+
"version": "0.10.0-staging.6",
|
|
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.6.0-staging.
|
|
60
|
+
"@final-commerce/common": "2.6.0-staging.4"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@commitlint/cli": "^19.0.0",
|