@pisell/pisellos 2.2.315 → 2.2.317
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/model/strategy/adapter/promotion/evaluator.js +89 -104
- package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +3 -1
- package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +28 -4
- package/dist/modules/Holder/utils.d.ts +2 -0
- package/dist/modules/Holder/utils.js +32 -2
- package/dist/modules/OpenData/contactInfo.d.ts +20 -0
- package/dist/modules/OpenData/contactInfo.js +70 -0
- package/dist/modules/OpenData/index.d.ts +1 -0
- package/dist/modules/OpenData/index.js +1 -0
- package/dist/modules/OpenData/types.d.ts +9 -0
- package/dist/modules/Order/holderRelations.d.ts +14 -0
- package/dist/modules/Order/holderRelations.js +154 -0
- package/dist/modules/Order/index.d.ts +1 -1
- package/dist/modules/Order/index.js +791 -795
- package/dist/modules/Order/types.d.ts +21 -3
- package/dist/modules/Order/types.js +4 -2
- package/dist/modules/Order/utils/discountProductLineIdentity.d.ts +1 -1
- package/dist/modules/Order/utils/discountProductLineIdentity.js +142 -7
- package/dist/modules/Order/utils/orderCollectionIdentity.js +24 -10
- package/dist/modules/Order/utils.d.ts +2 -1
- package/dist/modules/Order/utils.js +36 -10
- package/dist/modules/Rules/index.js +62 -61
- package/dist/server/index.js +36 -28
- package/dist/server/modules/order/index.d.ts +4 -0
- package/dist/server/modules/order/index.js +255 -190
- package/dist/server/modules/order/types.d.ts +3 -0
- package/dist/server/modules/products/index.d.ts +28 -7
- package/dist/server/modules/products/index.js +1297 -770
- package/dist/server/modules/products/replication.d.ts +8 -0
- package/dist/server/modules/products/replication.js +69 -0
- package/dist/server/modules/products/types.d.ts +12 -1
- package/dist/server/modules/products/types.js +4 -0
- package/dist/shared/receipt/small-ticket.js +24 -12
- package/dist/shared/receipt/templateVisibility.d.ts +3 -0
- package/dist/shared/receipt/templateVisibility.js +6 -2
- package/dist/shared/sales/loadSalesOrderSnapshot.js +1 -1
- package/dist/solution/BaseSales/index.d.ts +4 -0
- package/dist/solution/BaseSales/index.js +1116 -935
- package/dist/solution/BaseSales/types.d.ts +2 -1
- package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +3 -1
- package/dist/solution/BaseSales/utils/parseSalesResponse.js +7 -3
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +14 -4
- package/dist/solution/BookingByStep/index.d.ts +2 -2
- package/dist/solution/BookingTicket/index.d.ts +15 -1
- package/dist/solution/BookingTicket/index.js +784 -501
- package/dist/solution/ScanOrder/index.js +65 -31
- package/dist/solution/ScanOrder/types.d.ts +3 -0
- package/dist/solution/UnifiedBookingSales/index.js +1 -1
- package/lib/model/strategy/adapter/promotion/evaluator.js +9 -14
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +3 -1
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +17 -1
- package/lib/modules/Holder/utils.d.ts +2 -0
- package/lib/modules/Holder/utils.js +27 -1
- package/lib/modules/OpenData/contactInfo.d.ts +20 -0
- package/lib/modules/OpenData/contactInfo.js +56 -0
- package/lib/modules/OpenData/index.d.ts +1 -0
- package/lib/modules/OpenData/index.js +12 -0
- package/lib/modules/OpenData/types.d.ts +9 -0
- package/lib/modules/Order/holderRelations.d.ts +14 -0
- package/lib/modules/Order/holderRelations.js +98 -0
- package/lib/modules/Order/index.d.ts +1 -1
- package/lib/modules/Order/index.js +46 -20
- package/lib/modules/Order/types.d.ts +21 -3
- package/lib/modules/Order/types.js +3 -2
- package/lib/modules/Order/utils/discountProductLineIdentity.d.ts +1 -1
- package/lib/modules/Order/utils/discountProductLineIdentity.js +51 -2
- package/lib/modules/Order/utils/orderCollectionIdentity.js +5 -0
- package/lib/modules/Order/utils.d.ts +2 -1
- package/lib/modules/Order/utils.js +28 -6
- package/lib/modules/Rules/index.js +2 -1
- package/lib/server/index.js +8 -2
- package/lib/server/modules/order/index.d.ts +4 -0
- package/lib/server/modules/order/index.js +46 -4
- package/lib/server/modules/order/types.d.ts +3 -0
- package/lib/server/modules/products/index.d.ts +28 -7
- package/lib/server/modules/products/index.js +226 -63
- package/lib/server/modules/products/replication.d.ts +8 -0
- package/lib/server/modules/products/replication.js +30 -0
- package/lib/server/modules/products/types.d.ts +12 -1
- package/lib/server/modules/products/types.js +3 -0
- package/lib/shared/receipt/small-ticket.js +22 -13
- package/lib/shared/receipt/templateVisibility.d.ts +3 -0
- package/lib/shared/receipt/templateVisibility.js +6 -2
- package/lib/shared/sales/loadSalesOrderSnapshot.js +1 -1
- package/lib/solution/BaseSales/index.d.ts +4 -0
- package/lib/solution/BaseSales/index.js +68 -2
- package/lib/solution/BaseSales/types.d.ts +2 -1
- package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +3 -1
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +4 -0
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +16 -8
- package/lib/solution/BookingByStep/index.d.ts +2 -2
- package/lib/solution/BookingTicket/index.d.ts +15 -1
- package/lib/solution/BookingTicket/index.js +132 -3
- package/lib/solution/ScanOrder/index.js +59 -20
- package/lib/solution/ScanOrder/types.d.ts +3 -0
- package/lib/solution/UnifiedBookingSales/index.js +1 -1
- package/package.json +1 -1
|
@@ -673,6 +673,6 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
|
|
|
673
673
|
getOrderInfo(order_id: number): Promise<any>;
|
|
674
674
|
getVouchers(): any[];
|
|
675
675
|
}
|
|
676
|
-
export type { AddProductToOrderOptions, OrderMetaList, PointCardSnapshotItem, VirtualCurrencySnapshotItem, RemoveProductsFromOrderOptions, SalesNote, SalesNoteDraftInput, SalesNoteLocalizedSelection, SalesNoteLocalizedText, SalesNoteRelation, SalesNoteTextInput, SetSalesNoteInput, UpdateOrderBookingParams, UpdateOrderProductParams, UpdateOrderProductQuantityParams, } from './types';
|
|
676
|
+
export type { OrderHolderRelation, AddProductToOrderOptions, OrderMetaList, PointCardSnapshotItem, VirtualCurrencySnapshotItem, RemoveProductsFromOrderOptions, SalesNote, SalesNoteDraftInput, SalesNoteLocalizedSelection, SalesNoteLocalizedText, SalesNoteRelation, SalesNoteTextInput, SetSalesNoteInput, UpdateOrderBookingParams, UpdateOrderProductParams, UpdateOrderProductQuantityParams, } from './types';
|
|
677
677
|
export { isFulfillmentTimingBooking } from './pickupTiming';
|
|
678
678
|
export type { PickupTimingBooking, PickupTimingBookingInput, PickupTimingBookingMetadata, PickupTimingSelectionMode, PickupTimingSource, } from './pickupTiming';
|
|
@@ -16,6 +16,7 @@ var _BaseModule = require("../BaseModule");
|
|
|
16
16
|
var _types = require("./types");
|
|
17
17
|
var _utils = require("./utils");
|
|
18
18
|
var _utils2 = require("../Product/utils");
|
|
19
|
+
var _holderRelations = require("./holderRelations");
|
|
19
20
|
var _weighedProduct = require("./utils/weighedProduct");
|
|
20
21
|
var _pickupTiming = require("./pickupTiming");
|
|
21
22
|
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
@@ -543,7 +544,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
543
544
|
this.store.rules = rules;
|
|
544
545
|
}
|
|
545
546
|
createDefaultRulesHooks() {
|
|
546
|
-
return (0, _utils.createDefaultOrderRulesHooks)(() => this.store.tempOrder?.bookings || []);
|
|
547
|
+
return (0, _utils.createDefaultOrderRulesHooks)(() => this.store.tempOrder?.bookings || [], () => this.store.tempOrder?.holder_relations);
|
|
547
548
|
}
|
|
548
549
|
|
|
549
550
|
/**
|
|
@@ -857,7 +858,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
857
858
|
discount_list: (0, _utils.normalizeOrderProductDiscountList)((0, _manualProductDiscount.syncManualProductDiscountProductNum)(mergedProduct.discount_list, mergedProduct.num))
|
|
858
859
|
};
|
|
859
860
|
}));
|
|
860
|
-
(0, _discountProductLineIdentity.ensureUniqueProductLineUids)(tempOrder);
|
|
861
|
+
(0, _discountProductLineIdentity.ensureUniqueProductLineUids)(tempOrder, discountList);
|
|
861
862
|
(0, _discountProductLineIdentity.consolidateDiscountFreeProductLines)(tempOrder);
|
|
862
863
|
}
|
|
863
864
|
if (result?.discountList) {
|
|
@@ -968,14 +969,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
968
969
|
}
|
|
969
970
|
} else {
|
|
970
971
|
for (const addAction of result.giftActions.toAdd) {
|
|
971
|
-
//
|
|
972
|
-
|
|
973
|
-
const sameStrategy = result.products.find(p => p.metadata?._giftInfo?.strategyId === addAction.strategyId);
|
|
974
|
-
if (sameStrategy && !sameStrategy.booking_uid && !sameStrategy.metadata?.booking_uid) {
|
|
975
|
-
sameStrategy.num = (Number(sameStrategy.num) || 0) + (addAction.giftCount || 1);
|
|
976
|
-
continue;
|
|
977
|
-
}
|
|
978
|
-
}
|
|
972
|
+
// 唯一候选也可能有规格/套餐。每次补赠都交给 SDK 判断,不能复用旧赠品的选择。
|
|
973
|
+
|
|
979
974
|
const giftMutationBaseline = options?.isCurrentOrder ? (0, _lodashEs.cloneDeep)({
|
|
980
975
|
products: tempOrder.products,
|
|
981
976
|
bookings: tempOrder.bookings
|
|
@@ -1118,7 +1113,9 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1118
1113
|
* sessionStorage 的 cacheId 分桶。写入失败由 BaseModule 静默降级。
|
|
1119
1114
|
*/
|
|
1120
1115
|
persistTempOrder() {
|
|
1121
|
-
if (!this.
|
|
1116
|
+
if (!this.store.tempOrder) return;
|
|
1117
|
+
(0, _holderRelations.ensureHolderRelationUuids)(this.store.tempOrder);
|
|
1118
|
+
if (!this.sessionStoragePersistEnabled) return;
|
|
1122
1119
|
this.checkSaveCache({
|
|
1123
1120
|
cacheId: this.cacheId,
|
|
1124
1121
|
fatherModule: this.fatherModule,
|
|
@@ -1827,7 +1824,10 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1827
1824
|
source_product_price: this.normalizeFingerprintMoney(metadata.source_product_price),
|
|
1828
1825
|
main_product_selling_price: this.normalizeFingerprintMoney(metadata.main_product_selling_price),
|
|
1829
1826
|
main_product_original_price: this.normalizeFingerprintMoney(metadata.main_product_original_price),
|
|
1830
|
-
product_discount_difference: this.normalizeFingerprintMoney(metadata.product_discount_difference)
|
|
1827
|
+
product_discount_difference: this.normalizeFingerprintMoney(metadata.product_discount_difference),
|
|
1828
|
+
...(!(0, _holderRelations.hasProductBooking)(product) ? {
|
|
1829
|
+
holder_relations: this.normalizeFingerprintValue((0, _holderRelations.getProductHolderRelations)(this.store.tempOrder || {}, product))
|
|
1830
|
+
} : {})
|
|
1831
1831
|
},
|
|
1832
1832
|
product_sku: this.normalizeFingerprintValue({
|
|
1833
1833
|
code: sku.code ?? '',
|
|
@@ -1863,7 +1863,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1863
1863
|
items.sort((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right)));
|
|
1864
1864
|
return JSON.stringify(items);
|
|
1865
1865
|
}
|
|
1866
|
-
buildProductStructuralFingerprintItem(product) {
|
|
1866
|
+
buildProductStructuralFingerprintItem(product, order = this.store.tempOrder || {}) {
|
|
1867
1867
|
const sku = product?.product_sku || {};
|
|
1868
1868
|
const metadata = product?.metadata || {};
|
|
1869
1869
|
const discountTypes = (product?.discount_list || []).map(discount => discount?.type ?? discount?.tag);
|
|
@@ -1878,7 +1878,10 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1878
1878
|
unique_identification_number: metadata.unique_identification_number ?? product?.unique_identification_number ?? '',
|
|
1879
1879
|
price_override: metadata.price_override ?? '',
|
|
1880
1880
|
is_manual_discount: metadata.is_manual_discount ?? '',
|
|
1881
|
-
product_discount_reason: metadata.product_discount_reason ?? ''
|
|
1881
|
+
product_discount_reason: metadata.product_discount_reason ?? '',
|
|
1882
|
+
...(!(0, _holderRelations.hasProductBooking)(product) ? {
|
|
1883
|
+
holder_relations: this.normalizeFingerprintValue((0, _holderRelations.getProductHolderRelations)(order, product))
|
|
1884
|
+
} : {})
|
|
1882
1885
|
},
|
|
1883
1886
|
product_sku: this.normalizeFingerprintValue({
|
|
1884
1887
|
code: sku.code ?? '',
|
|
@@ -1916,8 +1919,8 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1916
1919
|
})))
|
|
1917
1920
|
};
|
|
1918
1921
|
}
|
|
1919
|
-
buildOrderProductsStructuralFingerprint(products) {
|
|
1920
|
-
const items = (products || []).map(product => this.buildProductStructuralFingerprintItem(product));
|
|
1922
|
+
buildOrderProductsStructuralFingerprint(products, order = this.store.tempOrder || {}) {
|
|
1923
|
+
const items = (products || []).map(product => this.buildProductStructuralFingerprintItem(product, order));
|
|
1921
1924
|
items.sort((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right)));
|
|
1922
1925
|
return JSON.stringify(items);
|
|
1923
1926
|
}
|
|
@@ -1984,7 +1987,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
1984
1987
|
const manualDepositOverride = this.getManualDepositOverride(tempOrder);
|
|
1985
1988
|
if (currentFingerprint !== snapshot.productFingerprint) {
|
|
1986
1989
|
const currentStructuralFingerprint = this.buildOrderProductsStructuralFingerprint(tempOrder.products);
|
|
1987
|
-
const snapshotStructuralFingerprint = this.buildOrderProductsStructuralFingerprint(Array.isArray(snapshot.products) ? snapshot.products : []);
|
|
1990
|
+
const snapshotStructuralFingerprint = this.buildOrderProductsStructuralFingerprint(Array.isArray(snapshot.products) ? snapshot.products : [], snapshot);
|
|
1988
1991
|
if (currentStructuralFingerprint !== snapshotStructuralFingerprint) return null;
|
|
1989
1992
|
}
|
|
1990
1993
|
let summary = {
|
|
@@ -2205,9 +2208,16 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
2205
2208
|
product.metadata = metadata;
|
|
2206
2209
|
return String(uid);
|
|
2207
2210
|
}
|
|
2208
|
-
sanitizeOrderProductForTempOrder(product) {
|
|
2211
|
+
sanitizeOrderProductForTempOrder(product, deferHolderCleanup = false) {
|
|
2209
2212
|
if (product.metadata && typeof product.metadata === 'object') {
|
|
2210
2213
|
delete product.metadata.origin;
|
|
2214
|
+
if (!deferHolderCleanup && !(0, _holderRelations.hasProductBooking)(product)) {
|
|
2215
|
+
delete product.metadata.holder;
|
|
2216
|
+
delete product.metadata.holder_id;
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
if (product._extend?.holder_relations !== undefined) {
|
|
2220
|
+
delete product._extend.holder_relations;
|
|
2211
2221
|
}
|
|
2212
2222
|
return product;
|
|
2213
2223
|
}
|
|
@@ -3006,6 +3016,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3006
3016
|
const nextCustomerId = tempOrder.customer_id ?? null;
|
|
3007
3017
|
if (String(previousCustomerId ?? '') !== String(nextCustomerId ?? '')) {
|
|
3008
3018
|
this.clearCustomerWalletState(tempOrder);
|
|
3019
|
+
(0, _holderRelations.removeProductHolderRelations)(tempOrder, tempOrder.products.filter(product => !(0, _holderRelations.hasProductBooking)(product)));
|
|
3009
3020
|
}
|
|
3010
3021
|
this.persistTempOrder();
|
|
3011
3022
|
return {
|
|
@@ -3569,10 +3580,13 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3569
3580
|
const hasIncomingProductNote = this.hasOrderProductLineNote(normalizedIncoming);
|
|
3570
3581
|
const hasIncomingManualProductDiscount = isManualProductDiscountProduct(normalizedIncoming);
|
|
3571
3582
|
const hasIncomingBookingUid = this.hasLinkedBookingUid(productToAdd) || this.hasLinkedBookingUid(normalizedIncoming);
|
|
3583
|
+
const holderRelationsPatch = !hasIncomingBookingUid ? productToAdd._extend?.holder_relations : undefined;
|
|
3584
|
+
const hasIncomingHolder = Array.isArray(holderRelationsPatch) && holderRelationsPatch.length > 0;
|
|
3572
3585
|
const isIncomingCustomItem = productToAdd.metadata?.origin?.isCustomItem === true || productToAdd._origin?.isCustomItem === true;
|
|
3573
|
-
const shouldForceNewLine = disableMerge || !!booking || hasIncomingGoodPass || isIncomingPersistedEntitlementPass || hasIncomingBookingUid || isIncomingCustomItem || isWeighingProduct;
|
|
3586
|
+
const shouldForceNewLine = disableMerge || !!booking || hasIncomingGoodPass || isIncomingPersistedEntitlementPass || hasIncomingBookingUid || hasIncomingHolder || isIncomingCustomItem || isWeighingProduct;
|
|
3574
3587
|
const matchedIndex = shouldForceNewLine ? -1 : tempOrder.products.findIndex(item => {
|
|
3575
3588
|
if (this.hasGoodPassDiscount(item)) return false;
|
|
3589
|
+
if ((0, _holderRelations.getProductHolderRelations)(tempOrder, item).length > 0 || (0, _utils.hasAssignedHolderId)(item.metadata?.holder_id)) return false;
|
|
3576
3590
|
const isRuntimeEntitlementPass = this.isRuntimeEntitlementAppend(item, tempOrder);
|
|
3577
3591
|
if (isIncomingEntitlementAppend !== isRuntimeEntitlementPass) {
|
|
3578
3592
|
return false;
|
|
@@ -3663,6 +3677,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3663
3677
|
if (linked) {
|
|
3664
3678
|
tempOrder.bookings = [...(tempOrder.bookings || []), linked.booking];
|
|
3665
3679
|
}
|
|
3680
|
+
(0, _holderRelations.replaceProductHolderRelations)(tempOrder, committedProduct, holderRelationsPatch);
|
|
3666
3681
|
return committedProduct;
|
|
3667
3682
|
};
|
|
3668
3683
|
if (!matchedProduct) {
|
|
@@ -3772,6 +3787,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3772
3787
|
}));
|
|
3773
3788
|
const mutationSnapshot = salesNoteDrafts.length > 0 ? {
|
|
3774
3789
|
products: (0, _lodashEs.cloneDeep)(tempOrder.products || []),
|
|
3790
|
+
holder_relations: (0, _lodashEs.cloneDeep)(tempOrder.holder_relations),
|
|
3775
3791
|
bookings: (0, _lodashEs.cloneDeep)(tempOrder.bookings || []),
|
|
3776
3792
|
notes: (0, _lodashEs.cloneDeep)(tempOrder.notes || []),
|
|
3777
3793
|
extend: (0, _lodashEs.cloneDeep)(tempOrder._extend || {})
|
|
@@ -3796,6 +3812,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
3796
3812
|
const rollbackProductAndNotesMutation = () => {
|
|
3797
3813
|
if (!mutationSnapshot) return;
|
|
3798
3814
|
tempOrder.products = mutationSnapshot.products;
|
|
3815
|
+
if (mutationSnapshot.holder_relations === undefined) delete tempOrder.holder_relations;else tempOrder.holder_relations = mutationSnapshot.holder_relations;
|
|
3799
3816
|
tempOrder.bookings = mutationSnapshot.bookings;
|
|
3800
3817
|
tempOrder.notes = mutationSnapshot.notes;
|
|
3801
3818
|
tempOrder._extend = mutationSnapshot.extend;
|
|
@@ -4280,6 +4297,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4280
4297
|
if (uid) reapplyWeighedDiscountProductUids?.push(String(uid));
|
|
4281
4298
|
}
|
|
4282
4299
|
tempOrder.products[productIndex] = normalizedProduct;
|
|
4300
|
+
(0, _holderRelations.replaceProductHolderRelations)(tempOrder, normalizedProduct, updates._extend?.holder_relations);
|
|
4283
4301
|
this.syncTempOrderHolderFromBookings(tempOrder);
|
|
4284
4302
|
this.captureProductRuntime(tempOrder, updates, tempOrder.products[productIndex], tempOrder.products[productIndex].metadata?.unique_identification_number);
|
|
4285
4303
|
return tempOrder.products[productIndex].metadata?.unique_identification_number;
|
|
@@ -4557,6 +4575,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4557
4575
|
tempOrder.products = nextProductIndex >= 0 ? [...productsWithoutRemaining.slice(0, nextProductIndex), remainingProduct, ...productsWithoutRemaining.slice(nextProductIndex)] : [...productsWithoutRemaining, remainingProduct];
|
|
4558
4576
|
}
|
|
4559
4577
|
}
|
|
4578
|
+
(0, _holderRelations.removeProductHolderRelations)(tempOrder, productsBeforeRemove.filter(product => !tempOrder.products.includes(product)));
|
|
4560
4579
|
this.removeSalesNotesForMissingProductLines(tempOrder);
|
|
4561
4580
|
if (isCurrentOrder) {
|
|
4562
4581
|
await this.finalizeProductOrderMutation(tempOrder, {
|
|
@@ -4582,6 +4601,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4582
4601
|
async clearOrderCartLines() {
|
|
4583
4602
|
const tempOrder = this.ensureTempOrder();
|
|
4584
4603
|
this.ensureSalesNotesLoadedForMutation(tempOrder);
|
|
4604
|
+
(0, _holderRelations.removeProductHolderRelations)(tempOrder, tempOrder.products);
|
|
4585
4605
|
tempOrder.products = [];
|
|
4586
4606
|
tempOrder.bookings = [];
|
|
4587
4607
|
(0, _virtualSettlement.releaseTempOrderSettlementState)(tempOrder);
|
|
@@ -4611,6 +4631,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
4611
4631
|
async clearOrderForSettlementSwitch() {
|
|
4612
4632
|
const tempOrder = this.ensureTempOrder();
|
|
4613
4633
|
this.ensureSalesNotesLoadedForMutation(tempOrder);
|
|
4634
|
+
(0, _holderRelations.removeProductHolderRelations)(tempOrder, tempOrder.products);
|
|
4614
4635
|
tempOrder.products = [];
|
|
4615
4636
|
tempOrder.bookings = [];
|
|
4616
4637
|
this.removeSalesNotesForMissingProductLines(tempOrder);
|
|
@@ -5354,6 +5375,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
5354
5375
|
originalSalesSnapshot: {
|
|
5355
5376
|
summary: (0, _lodashEs.cloneDeep)(this.store.summary),
|
|
5356
5377
|
products: (0, _lodashEs.cloneDeep)(nextTempOrder.products || []),
|
|
5378
|
+
holder_relations: (0, _lodashEs.cloneDeep)(nextTempOrder.holder_relations),
|
|
5357
5379
|
bookings: (0, _lodashEs.cloneDeep)(nextTempOrder.bookings || []),
|
|
5358
5380
|
payments: (0, _lodashEs.cloneDeep)(nextTempOrder.payments || []),
|
|
5359
5381
|
surcharges: (0, _lodashEs.cloneDeep)(nextTempOrder.surcharges || []),
|
|
@@ -5506,6 +5528,9 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
5506
5528
|
nextTempOrder.metadata = raw.metadata && typeof raw.metadata === 'object' ? {
|
|
5507
5529
|
...raw.metadata
|
|
5508
5530
|
} : {};
|
|
5531
|
+
const holderRelations = (0, _holderRelations.restoreLegacyHolderRelations)(raw);
|
|
5532
|
+
if (holderRelations === undefined) delete nextTempOrder.holder_relations;else nextTempOrder.holder_relations = (0, _lodashEs.cloneDeep)(holderRelations);
|
|
5533
|
+
(0, _holderRelations.ensureHolderRelationUuids)(nextTempOrder);
|
|
5509
5534
|
nextTempOrder.holder = raw.holder && typeof raw.holder === 'object' ? {
|
|
5510
5535
|
...raw.holder
|
|
5511
5536
|
} : null;
|
|
@@ -5583,6 +5608,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
5583
5608
|
}
|
|
5584
5609
|
tempOrderExtend.productsByUid = productsByUid;
|
|
5585
5610
|
this.hydrateLinkedBookingIdentity(nextTempOrder);
|
|
5611
|
+
nextTempOrder.products.forEach(product => this.sanitizeOrderProductForTempOrder(product));
|
|
5586
5612
|
if (options?.ensureIdentity !== false) {
|
|
5587
5613
|
this.ensureExternalSaleNumber(nextTempOrder);
|
|
5588
5614
|
}
|
|
@@ -5743,7 +5769,7 @@ class OrderModule extends _BaseModule.BaseModule {
|
|
|
5743
5769
|
};
|
|
5744
5770
|
if (result.metadata) delete result.metadata.price_schema_version;
|
|
5745
5771
|
const restored = (0, _bundleDiscountHydration.restoreHydratedBundleDiscounts)(result, _utils.normalizeOrderProductDiscountList);
|
|
5746
|
-
return this.sanitizeOrderProductForTempOrder(this.normalizeVirtualSettlementProductIfEnabled(restored));
|
|
5772
|
+
return this.sanitizeOrderProductForTempOrder(this.normalizeVirtualSettlementProductIfEnabled(restored), true);
|
|
5747
5773
|
}
|
|
5748
5774
|
getLastOrderInfo() {
|
|
5749
5775
|
return this.store?.lastOrderInfo;
|
|
@@ -71,8 +71,8 @@ export interface OrderGiftSelectResult {
|
|
|
71
71
|
/**
|
|
72
72
|
* 赠品解析回调签名(SDK → OS 的返回值)。
|
|
73
73
|
*
|
|
74
|
-
* -
|
|
75
|
-
* -
|
|
74
|
+
* - 唯一且无规格/套餐的候选:SDK 自动构造商品
|
|
75
|
+
* - 有规格/套餐或多个候选:SDK 弹窗等用户确认后构造
|
|
76
76
|
* - 用户取消:抛错或返回空数组(OS 视为放弃本次添加)
|
|
77
77
|
*
|
|
78
78
|
* 返回数组时沿用旧协议,只写 tempOrder.products;返回对象时可同时写入预约 bookings。
|
|
@@ -243,6 +243,11 @@ export interface OrderProduct extends OrderProductIdentity {
|
|
|
243
243
|
product_cover?: string;
|
|
244
244
|
metadata: Record<string, any>;
|
|
245
245
|
note?: string;
|
|
246
|
+
/** 仅作按行更新输入;正式数据保存于订单顶层。 */
|
|
247
|
+
_extend?: {
|
|
248
|
+
holder_relations?: OrderHolderRelation[];
|
|
249
|
+
[key: string]: any;
|
|
250
|
+
};
|
|
246
251
|
}
|
|
247
252
|
export interface OrderSummary {
|
|
248
253
|
product_quantity: number;
|
|
@@ -340,6 +345,17 @@ export interface SalesNotesMutationSnapshot {
|
|
|
340
345
|
}
|
|
341
346
|
export type SalesNoteProtocolRelation = SalesNoteRelation;
|
|
342
347
|
export type SalesNoteProtocol = SalesNote;
|
|
348
|
+
/** 后端关系及 metadata 均为开放对象,未知字段必须往返保留。 */
|
|
349
|
+
export interface OrderHolderRelation {
|
|
350
|
+
/** 关系自身的 UUID;新选择/旧草稿可缺省,入单与提交时由 OS 补齐。 */
|
|
351
|
+
uuid?: string;
|
|
352
|
+
relation_model: string;
|
|
353
|
+
relation_uuid: string;
|
|
354
|
+
holder_type: 'form' | 'customer';
|
|
355
|
+
holder_id: number;
|
|
356
|
+
metadata?: Record<string, any>;
|
|
357
|
+
[key: string]: any;
|
|
358
|
+
}
|
|
343
359
|
export interface OrderTempOrder {
|
|
344
360
|
order_id: number | null;
|
|
345
361
|
external_sale_number: string;
|
|
@@ -379,6 +395,7 @@ export interface OrderTempOrder {
|
|
|
379
395
|
created_at: string | undefined;
|
|
380
396
|
request_unique_idempotency_token?: string;
|
|
381
397
|
products: OrderProduct[];
|
|
398
|
+
holder_relations?: OrderHolderRelation[];
|
|
382
399
|
notes: SalesNote[];
|
|
383
400
|
bookings: any[];
|
|
384
401
|
payments: any[];
|
|
@@ -398,7 +415,7 @@ export interface OrderTempOrder {
|
|
|
398
415
|
[key: string]: any;
|
|
399
416
|
};
|
|
400
417
|
}
|
|
401
|
-
export interface OrderSubmitProduct extends Omit<OrderProduct, 'unique_identification_number' | 'num'> {
|
|
418
|
+
export interface OrderSubmitProduct extends Omit<OrderProduct, 'unique_identification_number' | 'num' | '_extend'> {
|
|
402
419
|
product_quantity: number;
|
|
403
420
|
payment_price: string;
|
|
404
421
|
product_sku: OrderProductSku;
|
|
@@ -607,6 +624,7 @@ export interface SubmitSalesOrderParams {
|
|
|
607
624
|
schedule_date: string;
|
|
608
625
|
created_at?: string | undefined;
|
|
609
626
|
products: OrderSubmitProduct[];
|
|
627
|
+
holder_relations?: OrderHolderRelation[];
|
|
610
628
|
bookings: OrderSubmitBooking[];
|
|
611
629
|
payments: any[];
|
|
612
630
|
vouchers: any[];
|
|
@@ -32,8 +32,8 @@ let OrderHooks = exports.OrderHooks = /*#__PURE__*/function (OrderHooks) {
|
|
|
32
32
|
/**
|
|
33
33
|
* 赠品解析回调签名(SDK → OS 的返回值)。
|
|
34
34
|
*
|
|
35
|
-
* -
|
|
36
|
-
* -
|
|
35
|
+
* - 唯一且无规格/套餐的候选:SDK 自动构造商品
|
|
36
|
+
* - 有规格/套餐或多个候选:SDK 弹窗等用户确认后构造
|
|
37
37
|
* - 用户取消:抛错或返回空数组(OS 视为放弃本次添加)
|
|
38
38
|
*
|
|
39
39
|
* 返回数组时沿用旧协议,只写 tempOrder.products;返回对象时可同时写入预约 bookings。
|
|
@@ -63,6 +63,7 @@ let OrderHooks = exports.OrderHooks = /*#__PURE__*/function (OrderHooks) {
|
|
|
63
63
|
* Sales Notes 乐观写入前的可恢复快照。
|
|
64
64
|
* 该对象应视为 opaque token,只用于原样传回 restoreSalesNotesMutationSnapshot。
|
|
65
65
|
*/
|
|
66
|
+
/** 后端关系及 metadata 均为开放对象,未知字段必须往返保留。 */
|
|
66
67
|
/**
|
|
67
68
|
* 添加商品行时的顺序控制。
|
|
68
69
|
* 默认追加到 products 尾部;预约数量同步可插入到既有预约组的最新行之后,
|
|
@@ -31,7 +31,7 @@ export declare const DISCOUNT_SPLIT_ORIGIN_UID_KEY = "discountSplitOriginUid";
|
|
|
31
31
|
* 没有 UID 的裸商品不会被补写 UID。这是为了兼容 Rules/mock 的历史协议形状;
|
|
32
32
|
* 正常 Order 写路径会在 normalize 阶段提前创建 UID。
|
|
33
33
|
*/
|
|
34
|
-
export declare function ensureUniqueProductLineUids(tempOrder: OrderTempOrder): void;
|
|
34
|
+
export declare function ensureUniqueProductLineUids(tempOrder: OrderTempOrder, discounts?: Array<Record<string, any>>): void;
|
|
35
35
|
/**
|
|
36
36
|
* 把券移除后已经恢复原价的同源折扣拆分行重新合并。
|
|
37
37
|
*
|
|
@@ -9,6 +9,7 @@ exports.ensureUniqueProductLineUids = ensureUniqueProductLineUids;
|
|
|
9
9
|
var _lodashEs = require("lodash-es");
|
|
10
10
|
var _utils = require("../../../solution/ScanOrder/utils");
|
|
11
11
|
var _orderCollectionIdentity = require("./orderCollectionIdentity");
|
|
12
|
+
var _holderRelations = require("../holderRelations");
|
|
12
13
|
/**
|
|
13
14
|
* 商品券拆行的身份与回并工具。
|
|
14
15
|
*
|
|
@@ -72,16 +73,20 @@ function ensureProductsByUid(tempOrder) {
|
|
|
72
73
|
* 没有 UID 的裸商品不会被补写 UID。这是为了兼容 Rules/mock 的历史协议形状;
|
|
73
74
|
* 正常 Order 写路径会在 normalize 阶段提前创建 UID。
|
|
74
75
|
*/
|
|
75
|
-
function ensureUniqueProductLineUids(tempOrder) {
|
|
76
|
+
function ensureUniqueProductLineUids(tempOrder, discounts = []) {
|
|
76
77
|
// usedUids 只描述本次 Rules 返回的商品集合,不能直接依赖 productsByUid:
|
|
77
78
|
// productsByUid 可能还保留已删除行的历史 runtime,历史 UID 不应导致当前行被改号。
|
|
78
79
|
const usedUids = new Set();
|
|
79
80
|
const productsByUid = ensureProductsByUid(tempOrder);
|
|
81
|
+
const splitGroups = new Map();
|
|
80
82
|
tempOrder.products = (tempOrder.products || []).map(product => {
|
|
81
83
|
const sourceUid = getProductLineUid(product);
|
|
82
84
|
// 单测 mock 或兼容旧 Rules 时可能返回没有 UID 的裸商品。
|
|
83
85
|
// 这里不主动补 UID,避免一个“校验重复”的工具意外改变旧协议对象形状。
|
|
84
86
|
if (!sourceUid) return product;
|
|
87
|
+
const group = splitGroups.get(sourceUid) || [];
|
|
88
|
+
group.push(product);
|
|
89
|
+
splitGroups.set(sourceUid, group);
|
|
85
90
|
|
|
86
91
|
// 实际场景:可乐 ×5 首次进入 Rules 时只有一行。
|
|
87
92
|
// 使用三张券后 Rules 可能返回「可乐 ×2 + 三条可乐 ×1」,但四条都复制原 UID。
|
|
@@ -122,6 +127,50 @@ function ensureUniqueProductLineUids(tempOrder) {
|
|
|
122
127
|
usedUids.add(splitUid);
|
|
123
128
|
return product;
|
|
124
129
|
});
|
|
130
|
+
|
|
131
|
+
// 仅按本次券上的明确 Holder 分配迁移。数组顺序不能代表券对应的人。
|
|
132
|
+
// 未能明确分配时保留原 UID,不把整组关系复制给每一个拆分行。
|
|
133
|
+
for (const [sourceUid, products] of splitGroups) {
|
|
134
|
+
if (products.length < 2) continue;
|
|
135
|
+
const relations = (0, _holderRelations.getProductHolderRelations)(tempOrder, {
|
|
136
|
+
metadata: {
|
|
137
|
+
unique_identification_number: sourceUid
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
if (!relations.length || relations.some(relation => relation.holder_type !== 'form')) continue;
|
|
141
|
+
const assignments = new Map();
|
|
142
|
+
let remaining = [...relations];
|
|
143
|
+
let ambiguous = false;
|
|
144
|
+
for (const product of products) {
|
|
145
|
+
const holderIds = new Set();
|
|
146
|
+
for (const item of product.discount_list || []) {
|
|
147
|
+
const discount = discounts.find(candidate => String(candidate.id) === String(item.discount?.resource_id));
|
|
148
|
+
if (discount?.holder?.holder_type !== 'form') continue;
|
|
149
|
+
const value = discount.holder.holder_id;
|
|
150
|
+
(Array.isArray(value) ? value : [value]).forEach(id => {
|
|
151
|
+
const recordId = id && typeof id === 'object' ? id.form_record_id : id;
|
|
152
|
+
if (recordId !== undefined && recordId !== null && recordId !== '') holderIds.add(String(recordId));
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (!holderIds.size) continue;
|
|
156
|
+
const assigned = remaining.filter(relation => holderIds.has(String(relation.holder_id)));
|
|
157
|
+
if (assigned.length !== Number(product.num)) {
|
|
158
|
+
ambiguous = true;
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
assignments.set(product, assigned);
|
|
162
|
+
remaining = remaining.filter(relation => !assigned.includes(relation));
|
|
163
|
+
}
|
|
164
|
+
const unassigned = products.filter(product => !assignments.has(product));
|
|
165
|
+
if (ambiguous || unassigned.length > 1) continue;
|
|
166
|
+
if (unassigned.length === 1) {
|
|
167
|
+
if (remaining.length !== Number(unassigned[0].num)) continue;
|
|
168
|
+
assignments.set(unassigned[0], remaining);
|
|
169
|
+
} else if (remaining.length) continue;
|
|
170
|
+
for (const [product, assigned] of assignments) {
|
|
171
|
+
for (const relation of assigned) relation.relation_uuid = String(getProductLineUid(product));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
125
174
|
}
|
|
126
175
|
|
|
127
176
|
/**
|
|
@@ -154,7 +203,7 @@ function consolidateDiscountFreeProductLines(tempOrder) {
|
|
|
154
203
|
// - 手动改价/备注:用户显式表达了不同价格或不同制作要求;
|
|
155
204
|
// - 称重商品:每次称重的净重和金额属于独立交易事实;
|
|
156
205
|
// - 预约/holder/历史订单行:分别关联预约、持有人或后端 order_detail。
|
|
157
|
-
const hasMergeBoundary = hasDiscount || Boolean(product.metadata?._giftInfo || product._giftInfo) || Boolean(product.metadata?._promotion) || isManualProductDiscountLine(product) || hasProductLineNote(product) || Number(product.product_sku?.open_sold_weight || 0) === 1 || product.metadata?.is_edit_for_runtime === true || bookingId !== undefined && bookingId !== null && bookingId !== 0 && bookingId !== '0' || bookingUid !== undefined && bookingUid !== null && String(bookingUid) !== '' || holderId !== undefined && holderId !== null && String(holderId) !== '' || orderDetailId !== undefined && orderDetailId !== null && orderDetailId !== '';
|
|
206
|
+
const hasMergeBoundary = hasDiscount || Boolean(product.metadata?._giftInfo || product._giftInfo) || Boolean(product.metadata?._promotion) || isManualProductDiscountLine(product) || hasProductLineNote(product) || Number(product.product_sku?.open_sold_weight || 0) === 1 || product.metadata?.is_edit_for_runtime === true || bookingId !== undefined && bookingId !== null && bookingId !== 0 && bookingId !== '0' || bookingUid !== undefined && bookingUid !== null && String(bookingUid) !== '' || (0, _holderRelations.getProductHolderRelations)(tempOrder, product).length > 0 || holderId !== undefined && holderId !== null && String(holderId) !== '' || orderDetailId !== undefined && orderDetailId !== null && orderDetailId !== '';
|
|
158
207
|
if (hasMergeBoundary) {
|
|
159
208
|
consolidatedProducts.push(product);
|
|
160
209
|
continue;
|
|
@@ -331,6 +331,11 @@ function applyOrderCollectionUidRemaps(sourceOrder, uidRemaps) {
|
|
|
331
331
|
}
|
|
332
332
|
// 冲突 UID 仍由第一条持有;赠品父引用缺少可用的持久化行定位时不能全局改写。
|
|
333
333
|
if (remap.scope !== 'linked-owner') {
|
|
334
|
+
for (const relation of order.holder_relations || []) {
|
|
335
|
+
if (relation.relation_model === 'order_detail' && String(relation.relation_uuid) === remap.from) {
|
|
336
|
+
relation.relation_uuid = remap.to;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
334
339
|
for (const product of order.products || []) {
|
|
335
340
|
if (String(product?.metadata?.parent_unique_identification_number || '') === remap.from) {
|
|
336
341
|
product.metadata = {
|
|
@@ -173,7 +173,7 @@ export declare function resolveManualOverrideLineOriginalPrice(params: {
|
|
|
173
173
|
* // => -4
|
|
174
174
|
*/
|
|
175
175
|
export declare function resolveEffectivePerUnitDiscount(product: Record<string, any>): number;
|
|
176
|
-
export declare function createDefaultOrderRulesHooks(getBookings?: () => OrderTempOrder['bookings']): RulesParamsHooks;
|
|
176
|
+
export declare function createDefaultOrderRulesHooks(getBookings?: () => OrderTempOrder['bookings'], getHolderRelations?: () => OrderTempOrder['holder_relations']): RulesParamsHooks;
|
|
177
177
|
/**
|
|
178
178
|
* 通过 session 类商品的开始时间结束时间生成商品的时长
|
|
179
179
|
* @param {CartItem} cartItem
|
|
@@ -213,6 +213,7 @@ export declare function normalizeBookingSubType(booking: Record<string, any>): s
|
|
|
213
213
|
export declare function normalizeSubmitBooking<T extends {
|
|
214
214
|
metadata?: Record<string, any>;
|
|
215
215
|
}>(booking: T): T;
|
|
216
|
+
export declare function resolveTableOccupancyDuration(tempOrder: OrderTempOrder): number;
|
|
216
217
|
/** 提交用人数:有限且为正则向下取整,否则为 1 */
|
|
217
218
|
export declare function normalizeSubmitCollectPaxValue(value: unknown): number;
|
|
218
219
|
/** 从临时订单 metadata 解析合成 booking 的 collect_pax */
|
|
@@ -109,6 +109,7 @@ Object.defineProperty(exports, "resolveSafeProductNum", {
|
|
|
109
109
|
});
|
|
110
110
|
exports.resolveSubmitCollectPax = resolveSubmitCollectPax;
|
|
111
111
|
exports.resolveSubmitOrderType = resolveSubmitOrderType;
|
|
112
|
+
exports.resolveTableOccupancyDuration = resolveTableOccupancyDuration;
|
|
112
113
|
Object.defineProperty(exports, "shouldBuildManualProductDiscount", {
|
|
113
114
|
enumerable: true,
|
|
114
115
|
get: function () {
|
|
@@ -128,6 +129,7 @@ Object.defineProperty(exports, "syncManualProductDiscountProductNum", {
|
|
|
128
129
|
return _manualProductDiscount.syncManualProductDiscountProductNum;
|
|
129
130
|
}
|
|
130
131
|
});
|
|
132
|
+
var _lodashEs = require("lodash-es");
|
|
131
133
|
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
132
134
|
var _customParseFormat = _interopRequireDefault(require("dayjs/plugin/customParseFormat"));
|
|
133
135
|
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
@@ -138,6 +140,7 @@ var _utils2 = require("../../solution/ScanOrder/utils");
|
|
|
138
140
|
var _orderCollectionIdentity = require("./utils/orderCollectionIdentity");
|
|
139
141
|
var _salesNotes = require("./salesNotes");
|
|
140
142
|
var _pickupTiming = require("./pickupTiming");
|
|
143
|
+
var _holderRelations = require("./holderRelations");
|
|
141
144
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
142
145
|
_dayjs.default.extend(_customParseFormat.default);
|
|
143
146
|
const POINT_CARD_SNAPSHOT_TAG = 'point_card';
|
|
@@ -832,7 +835,7 @@ function resolveEffectivePerUnitDiscount(product) {
|
|
|
832
835
|
if (!Number.isFinite(originalPrice) || !Number.isFinite(finalPrice)) return fromList;
|
|
833
836
|
return fromList + (originalPrice - finalPrice);
|
|
834
837
|
}
|
|
835
|
-
function createDefaultOrderRulesHooks(getBookings) {
|
|
838
|
+
function createDefaultOrderRulesHooks(getBookings, getHolderRelations) {
|
|
836
839
|
const getProductStartDate = product => {
|
|
837
840
|
const productUid = String(product.metadata?.unique_identification_number ?? product.unique_identification_number ?? '');
|
|
838
841
|
const bookingUid = String(product.booking_uid ?? product.metadata?.booking_uid ?? '');
|
|
@@ -950,7 +953,9 @@ function createDefaultOrderRulesHooks(getBookings) {
|
|
|
950
953
|
// 勿写死 false:否则 Rules 不会走 total≠origin_total 的手动价推断,
|
|
951
954
|
// 无券时会把 bundle 价还原成 original_price(手动改价套餐会从 20 回到 30)。
|
|
952
955
|
isManualDiscount: resolveRulesManualDiscountFlag(metadataAny),
|
|
953
|
-
holder_id: product.metadata?.holder_id,
|
|
956
|
+
holder_id: (0, _holderRelations.hasProductBooking)(product) || !getHolderRelations ? product.metadata?.holder_id : (0, _holderRelations.getProductHolderRelations)({
|
|
957
|
+
holder_relations: getHolderRelations()
|
|
958
|
+
}, product).filter(relation => relation.holder_type === 'form').map(relation => relation.holder_id),
|
|
954
959
|
startDate: getProductStartDate(product),
|
|
955
960
|
main_product_selling_price: metadataAny.main_product_selling_price !== undefined ? new _decimal.default(Number(metadataAny.main_product_selling_price) || 0).minus(optionSellingSum).toDecimalPlaces(2).toString() : undefined,
|
|
956
961
|
inPromotion: metadataAny._promotion?.inPromotion === true,
|
|
@@ -1241,6 +1246,7 @@ function normalizeSubmitProduct(product, formatOptions = {}) {
|
|
|
1241
1246
|
} = product;
|
|
1242
1247
|
const {
|
|
1243
1248
|
num,
|
|
1249
|
+
_extend: _productExtend,
|
|
1244
1250
|
surcharge_fee: _productSurchargeFee,
|
|
1245
1251
|
discount_amount: _deprecatedDiscountAmount,
|
|
1246
1252
|
discount_type: _deprecatedDiscountType,
|
|
@@ -1427,6 +1433,7 @@ function createDefaultTempOrder(params) {
|
|
|
1427
1433
|
request_unique_idempotency_token: '',
|
|
1428
1434
|
vouchers: [],
|
|
1429
1435
|
products: [],
|
|
1436
|
+
holder_relations: [],
|
|
1430
1437
|
notes: [],
|
|
1431
1438
|
bookings: [],
|
|
1432
1439
|
payments: [],
|
|
@@ -1502,6 +1509,7 @@ function buildSubmitPayload(params) {
|
|
|
1502
1509
|
summary,
|
|
1503
1510
|
enhance
|
|
1504
1511
|
} = params;
|
|
1512
|
+
(0, _holderRelations.ensureHolderRelationUuids)(tempOrder);
|
|
1505
1513
|
const scheduleDate = tempOrder.schedule_date || tempOrder.created_at || formatDateTime(now);
|
|
1506
1514
|
const bookingUuid = (0, _orderCollectionIdentity.createUuidV4)();
|
|
1507
1515
|
const virtualSettlementMode = tempOrder.metadata?.currency_settlement_config?.settlement_type === 'virtual_currency';
|
|
@@ -1541,6 +1549,9 @@ function buildSubmitPayload(params) {
|
|
|
1541
1549
|
});
|
|
1542
1550
|
const payload = {
|
|
1543
1551
|
...tempOrderRest,
|
|
1552
|
+
...(tempOrder.holder_relations !== undefined ? {
|
|
1553
|
+
holder_relations: (0, _lodashEs.cloneDeep)(tempOrder.holder_relations)
|
|
1554
|
+
} : {}),
|
|
1544
1555
|
customer_id: tempOrder.customer_id ?? 1,
|
|
1545
1556
|
customer_name: tempOrder.customer_name || 'Walk-In',
|
|
1546
1557
|
country_calling_code: String(tempOrder.country_calling_code ?? ''),
|
|
@@ -1733,15 +1744,24 @@ function hasAssignedHolderId(value) {
|
|
|
1733
1744
|
* clearTempOrderHolderAssignments(tempOrder);
|
|
1734
1745
|
*/
|
|
1735
1746
|
function clearTempOrderHolderAssignments(tempOrder) {
|
|
1736
|
-
|
|
1747
|
+
const previousRelationCount = tempOrder.holder_relations?.length || 0;
|
|
1748
|
+
(0, _holderRelations.removeProductHolderRelations)(tempOrder, (tempOrder.products || []).filter(product => !(0, _holderRelations.hasProductBooking)(product)));
|
|
1749
|
+
let changed = previousRelationCount !== (tempOrder.holder_relations?.length || 0);
|
|
1737
1750
|
const resetHolderField = (target, key = 'holder_id') => {
|
|
1738
1751
|
if (!hasAssignedHolderId(target[key])) return;
|
|
1739
1752
|
target[key] = null;
|
|
1740
1753
|
changed = true;
|
|
1741
1754
|
};
|
|
1755
|
+
const clearHolder = target => {
|
|
1756
|
+
resetHolderField(target);
|
|
1757
|
+
if (target.holder !== undefined && target.holder !== null) {
|
|
1758
|
+
target.holder = null;
|
|
1759
|
+
changed = true;
|
|
1760
|
+
}
|
|
1761
|
+
};
|
|
1742
1762
|
for (const product of tempOrder.products || []) {
|
|
1743
1763
|
if (product.metadata && typeof product.metadata === 'object') {
|
|
1744
|
-
|
|
1764
|
+
clearHolder(product.metadata);
|
|
1745
1765
|
}
|
|
1746
1766
|
}
|
|
1747
1767
|
for (const booking of tempOrder.bookings || []) {
|
|
@@ -1759,11 +1779,13 @@ function clearTempOrderHolderAssignments(tempOrder) {
|
|
|
1759
1779
|
for (const entry of Object.values(productsByUid)) {
|
|
1760
1780
|
const origin = entry?.origin;
|
|
1761
1781
|
if (!origin || typeof origin !== 'object') continue;
|
|
1782
|
+
clearHolder(origin);
|
|
1762
1783
|
if (origin.metadata && typeof origin.metadata === 'object') {
|
|
1763
|
-
|
|
1784
|
+
clearHolder(origin.metadata);
|
|
1764
1785
|
}
|
|
1765
1786
|
if (origin._extend && typeof origin._extend === 'object') {
|
|
1766
|
-
|
|
1787
|
+
clearHolder(origin._extend);
|
|
1788
|
+
delete origin._extend.holder_relations;
|
|
1767
1789
|
}
|
|
1768
1790
|
}
|
|
1769
1791
|
}
|
|
@@ -8,6 +8,7 @@ var _BaseModule = require("../BaseModule");
|
|
|
8
8
|
var _types = require("./types");
|
|
9
9
|
var _utils = require("../../solution/ShopDiscount/utils");
|
|
10
10
|
var _utils2 = require("../Cart/utils");
|
|
11
|
+
var _utils3 = require("../Holder/utils");
|
|
11
12
|
var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
12
13
|
var _lodashEs = require("lodash-es");
|
|
13
14
|
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
@@ -59,7 +60,7 @@ class RulesModule extends _BaseModule.BaseModule {
|
|
|
59
60
|
if (discount.holder?.holder_type !== 'form') return true;
|
|
60
61
|
|
|
61
62
|
// getProduct 会裁剪商品字段,从原始商品读取配置,套餐子项沿用父商品。
|
|
62
|
-
const holderConfig =
|
|
63
|
+
const holderConfig = (0, _utils3.resolveProductHolderConfig)(holderSource);
|
|
63
64
|
const holderStatus = holderConfig?.status;
|
|
64
65
|
const holderEnabled = holderStatus === true || ['enable', '1'].includes(String(holderStatus).trim().toLowerCase());
|
|
65
66
|
if (!holderEnabled || holderConfig?.resource_id === undefined || holderConfig?.resource_id === null || holderConfig?.resource_id === '') {
|
package/lib/server/index.js
CHANGED
|
@@ -540,7 +540,7 @@ class Server {
|
|
|
540
540
|
|
|
541
541
|
// 监听 ProductsModule 同步完成事件,重新计算并推送查询结果
|
|
542
542
|
this.core.effects.on(_types2.ProductsHooks.onProductsSyncCompleted, payload => {
|
|
543
|
-
this.recomputeAndNotifyProductQuery({
|
|
543
|
+
return this.recomputeAndNotifyProductQuery({
|
|
544
544
|
changedIds: payload?.changedIds
|
|
545
545
|
});
|
|
546
546
|
});
|
|
@@ -836,6 +836,9 @@ class Server {
|
|
|
836
836
|
need_sync: 0,
|
|
837
837
|
is_draft_order: 0
|
|
838
838
|
};
|
|
839
|
+
if (!Array.isArray(fresh.holder_relations) && Array.isArray(checkoutData?.holder_relations)) {
|
|
840
|
+
syncedOrder.holder_relations = (0, _lodashEs.cloneDeep)(checkoutData.holder_relations);
|
|
841
|
+
}
|
|
839
842
|
await this.order.upsertOrdersFromRemote([syncedOrder], 'checkoutSync');
|
|
840
843
|
this.logInfo(`${title}: sync_sales 完整订单已同步到本地`, {
|
|
841
844
|
order_id: fresh.order_id,
|
|
@@ -5502,6 +5505,9 @@ class Server {
|
|
|
5502
5505
|
if (fresh.order_number !== undefined && fresh.order_number !== null) {
|
|
5503
5506
|
patch.order_number = fresh.order_number;
|
|
5504
5507
|
}
|
|
5508
|
+
if (Array.isArray(fresh.holder_relations)) {
|
|
5509
|
+
patch.holder_relations = (0, _lodashEs.cloneDeep)(fresh.holder_relations);
|
|
5510
|
+
}
|
|
5505
5511
|
return patch;
|
|
5506
5512
|
}
|
|
5507
5513
|
buildSyncedOrderForPrint(params) {
|
|
@@ -6241,7 +6247,7 @@ class Server {
|
|
|
6241
6247
|
const result = await this.computeProductQueryResult(subscriber.context, {
|
|
6242
6248
|
changedIds: options?.changedIds
|
|
6243
6249
|
});
|
|
6244
|
-
subscriber.callback(result);
|
|
6250
|
+
await subscriber.callback(result);
|
|
6245
6251
|
this.logInfo('recomputeAndNotifyProductQuery: 已推送', {
|
|
6246
6252
|
subscriberId
|
|
6247
6253
|
});
|
|
@@ -326,6 +326,10 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
326
326
|
private getIdentifiedPendingPayments;
|
|
327
327
|
private shouldProtectLocalOrderFromRemoteSnapshot;
|
|
328
328
|
private getUnmatchedIdentifiedPendingPayments;
|
|
329
|
+
/** 关系数组是完整快照,不能拼接或按商品子项生成 UID;扩展字段整体保留。 */
|
|
330
|
+
private applyHolderRelationsSnapshot;
|
|
331
|
+
/** 全量拉取缺少关系字段时,仍保留同一订单已有的关系快照。 */
|
|
332
|
+
private preserveOmittedHolderRelations;
|
|
329
333
|
private mergeOrderRecords;
|
|
330
334
|
private summarizeDuplicateOrders;
|
|
331
335
|
private logDuplicateOrders;
|