@pisell/pisellos 2.2.291 → 2.2.293
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/core/index.d.ts +7 -0
- package/dist/core/index.js +108 -65
- package/dist/model/strategy/adapter/itemRule/adapter.d.ts +4 -1
- package/dist/model/strategy/adapter/itemRule/adapter.js +135 -35
- package/dist/model/strategy/adapter/itemRule/evaluator.d.ts +8 -1
- package/dist/model/strategy/adapter/itemRule/evaluator.js +25 -1
- package/dist/model/strategy/adapter/itemRule/type.d.ts +44 -0
- package/dist/model/strategy/adapter/itemRule/type.js +19 -1
- package/dist/model/strategy/adapter/promotion/index.js +0 -9
- package/dist/modules/BookingContext/index.d.ts +3 -0
- package/dist/modules/BookingContext/index.js +42 -13
- package/dist/modules/BookingContext/types.d.ts +4 -4
- package/dist/modules/BookingContext/types.js +3 -3
- package/dist/modules/OpenData/types.d.ts +1 -0
- package/dist/modules/Order/index.d.ts +18 -3
- package/dist/modules/Order/index.js +885 -485
- package/dist/modules/Order/salesNotes.d.ts +31 -0
- package/dist/modules/Order/salesNotes.js +492 -0
- package/dist/modules/Order/types.d.ts +93 -5
- package/dist/modules/Order/types.js +5 -0
- package/dist/modules/Order/utils.d.ts +12 -0
- package/dist/modules/Order/utils.js +96 -31
- package/dist/modules/Product/types.d.ts +2 -0
- package/dist/modules/ProductList/clientDataVariants.d.ts +50 -0
- package/dist/modules/ProductList/clientDataVariants.js +216 -0
- package/dist/modules/ProductList/index.d.ts +18 -3
- package/dist/modules/ProductList/index.js +220 -38
- package/dist/modules/ProductList/types.d.ts +10 -0
- package/dist/modules/Quotation/index.d.ts +22 -0
- package/dist/modules/Quotation/index.js +293 -28
- package/dist/modules/ResourcePlanner/index.d.ts +0 -22
- package/dist/modules/ResourcePlanner/index.js +1 -180
- package/dist/modules/ResourcePlanner/localClock.d.ts +33 -0
- package/dist/modules/ResourcePlanner/localClock.js +183 -0
- package/dist/modules/ResourcePlanner/planner.d.ts +5 -14
- package/dist/modules/ResourcePlanner/planner.js +2111 -958
- package/dist/modules/ResourcePlanner/types.d.ts +359 -187
- package/dist/modules/ResourcePlanner/types.js +33 -1
- package/dist/plugins/request.d.ts +1 -0
- package/dist/server/index.d.ts +17 -2
- package/dist/server/index.js +1134 -932
- package/dist/server/modules/floor-plan/index.d.ts +4 -0
- package/dist/server/modules/floor-plan/index.js +240 -98
- package/dist/server/modules/menu/index.js +48 -23
- package/dist/server/modules/order/index.d.ts +17 -7
- package/dist/server/modules/order/index.js +419 -207
- package/dist/server/modules/products/index.d.ts +10 -4
- package/dist/server/modules/products/index.js +177 -84
- package/dist/server/modules/resource/index.js +21 -13
- package/dist/server/utils/product.d.ts +1 -1
- package/dist/server/utils/product.js +186 -22
- package/dist/server/utils/small-ticket.d.ts +9 -1
- package/dist/server/utils/small-ticket.js +131 -84
- package/dist/solution/BaseSales/index.d.ts +26 -3
- package/dist/solution/BaseSales/index.js +1384 -905
- package/dist/solution/BaseSales/types.d.ts +2 -0
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +3 -0
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +10 -3
- package/dist/solution/BaseSales/utils.js +6 -3
- package/dist/solution/BookingByStep/index.d.ts +4 -4
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.js +4 -2
- package/dist/solution/BookingTicket/utils/addProductDecision.d.ts +2 -1
- package/dist/solution/BookingTicket/utils/addProductDecision.js +6 -3
- package/dist/solution/BookingTicket/utils/orderCustomer.js +3 -2
- package/dist/solution/RegisterAndLogin/config.d.ts +9 -3
- package/dist/solution/RegisterAndLogin/config.js +95 -40
- package/dist/solution/RegisterAndLogin/index.js +4 -1
- package/dist/solution/ScanOrder/index.d.ts +1 -0
- package/dist/solution/ScanOrder/index.js +31 -27
- package/dist/solution/ScanOrder/types.d.ts +2 -0
- package/dist/solution/ScanOrder/utils.d.ts +1 -0
- package/dist/solution/ScanOrder/utils.js +8 -3
- package/dist/solution/UnifiedBookingSales/index.d.ts +128 -74
- package/dist/solution/UnifiedBookingSales/index.js +3877 -963
- package/dist/solution/UnifiedBookingSales/remoteOccupancyCache.d.ts +49 -0
- package/dist/solution/UnifiedBookingSales/remoteOccupancyCache.js +430 -0
- package/dist/solution/UnifiedBookingSales/types.d.ts +161 -77
- package/dist/solution/UnifiedBookingSales/types.js +4 -9
- package/dist/solution/VenueBooking/index.d.ts +3 -0
- package/dist/solution/VenueBooking/index.js +549 -497
- package/dist/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/dist/solution/VenueBooking/utils/dateSummary.js +3 -1
- package/dist/solution/VenueBooking/utils/slotMerge.d.ts +2 -0
- package/dist/solution/VenueBooking/utils/slotMerge.js +3 -1
- package/dist/utils/platform.d.ts +8 -0
- package/dist/utils/platform.js +15 -0
- package/lib/core/index.d.ts +7 -0
- package/lib/core/index.js +20 -2
- package/lib/model/strategy/adapter/itemRule/adapter.d.ts +4 -1
- package/lib/model/strategy/adapter/itemRule/adapter.js +73 -4
- package/lib/model/strategy/adapter/itemRule/evaluator.d.ts +8 -1
- package/lib/model/strategy/adapter/itemRule/evaluator.js +23 -1
- package/lib/model/strategy/adapter/itemRule/type.d.ts +44 -0
- package/lib/model/strategy/adapter/itemRule/type.js +19 -1
- package/lib/modules/BookingContext/index.d.ts +3 -0
- package/lib/modules/BookingContext/index.js +35 -8
- package/lib/modules/BookingContext/types.d.ts +4 -4
- package/lib/modules/BookingContext/types.js +3 -3
- package/lib/modules/OpenData/types.d.ts +1 -0
- package/lib/modules/Order/index.d.ts +18 -3
- package/lib/modules/Order/index.js +325 -28
- package/lib/modules/Order/salesNotes.d.ts +31 -0
- package/lib/modules/Order/salesNotes.js +382 -0
- package/lib/modules/Order/types.d.ts +93 -5
- package/lib/modules/Order/types.js +4 -0
- package/lib/modules/Order/utils.d.ts +12 -0
- package/lib/modules/Order/utils.js +85 -16
- package/lib/modules/Product/types.d.ts +2 -0
- package/lib/modules/ProductList/clientDataVariants.d.ts +50 -0
- package/lib/modules/ProductList/clientDataVariants.js +204 -0
- package/lib/modules/ProductList/index.d.ts +18 -3
- package/lib/modules/ProductList/index.js +137 -8
- package/lib/modules/ProductList/types.d.ts +10 -0
- package/lib/modules/Quotation/index.d.ts +22 -0
- package/lib/modules/Quotation/index.js +158 -11
- package/lib/modules/ResourcePlanner/index.d.ts +0 -22
- package/lib/modules/ResourcePlanner/index.js +9 -129
- package/lib/modules/ResourcePlanner/localClock.d.ts +33 -0
- package/lib/modules/ResourcePlanner/localClock.js +205 -0
- package/lib/modules/ResourcePlanner/planner.d.ts +5 -14
- package/lib/modules/ResourcePlanner/planner.js +1807 -783
- package/lib/modules/ResourcePlanner/types.d.ts +359 -187
- package/lib/modules/ResourcePlanner/types.js +13 -1
- package/lib/plugins/request.d.ts +1 -0
- package/lib/server/index.d.ts +17 -2
- package/lib/server/index.js +149 -21
- package/lib/server/modules/floor-plan/index.d.ts +4 -0
- package/lib/server/modules/floor-plan/index.js +60 -7
- package/lib/server/modules/menu/index.js +26 -4
- package/lib/server/modules/order/index.d.ts +17 -7
- package/lib/server/modules/order/index.js +194 -57
- package/lib/server/modules/products/index.d.ts +10 -4
- package/lib/server/modules/products/index.js +93 -23
- package/lib/server/modules/resource/index.js +12 -2
- package/lib/server/utils/product.d.ts +1 -1
- package/lib/server/utils/product.js +163 -3
- package/lib/server/utils/small-ticket.d.ts +9 -1
- package/lib/server/utils/small-ticket.js +123 -79
- package/lib/solution/BaseSales/index.d.ts +26 -3
- package/lib/solution/BaseSales/index.js +396 -70
- package/lib/solution/BaseSales/types.d.ts +2 -0
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +3 -0
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +9 -2
- package/lib/solution/BaseSales/utils.js +3 -0
- package/lib/solution/BookingByStep/index.d.ts +4 -4
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.js +2 -1
- package/lib/solution/BookingTicket/utils/addProductDecision.d.ts +2 -1
- package/lib/solution/BookingTicket/utils/addProductDecision.js +5 -2
- package/lib/solution/BookingTicket/utils/orderCustomer.js +2 -1
- package/lib/solution/RegisterAndLogin/config.d.ts +9 -3
- package/lib/solution/RegisterAndLogin/config.js +49 -8
- package/lib/solution/RegisterAndLogin/index.js +4 -1
- package/lib/solution/ScanOrder/index.d.ts +1 -0
- package/lib/solution/ScanOrder/index.js +5 -1
- package/lib/solution/ScanOrder/types.d.ts +2 -0
- package/lib/solution/ScanOrder/utils.d.ts +1 -0
- package/lib/solution/ScanOrder/utils.js +4 -0
- package/lib/solution/UnifiedBookingSales/index.d.ts +128 -74
- package/lib/solution/UnifiedBookingSales/index.js +2592 -424
- package/lib/solution/UnifiedBookingSales/remoteOccupancyCache.d.ts +49 -0
- package/lib/solution/UnifiedBookingSales/remoteOccupancyCache.js +316 -0
- package/lib/solution/UnifiedBookingSales/types.d.ts +161 -77
- package/lib/solution/UnifiedBookingSales/types.js +4 -6
- package/lib/solution/VenueBooking/index.d.ts +3 -0
- package/lib/solution/VenueBooking/index.js +33 -9
- package/lib/solution/VenueBooking/utils/dateSummary.d.ts +1 -0
- package/lib/solution/VenueBooking/utils/dateSummary.js +3 -1
- package/lib/solution/VenueBooking/utils/slotMerge.d.ts +2 -0
- package/lib/solution/VenueBooking/utils/slotMerge.js +3 -1
- package/lib/utils/platform.d.ts +8 -0
- package/lib/utils/platform.js +22 -0
- package/package.json +1 -1
|
@@ -101,6 +101,7 @@ Object.defineProperty(exports, "resolveSafeProductNum", {
|
|
|
101
101
|
}
|
|
102
102
|
});
|
|
103
103
|
exports.resolveSubmitCollectPax = resolveSubmitCollectPax;
|
|
104
|
+
exports.resolveSubmitOrderType = resolveSubmitOrderType;
|
|
104
105
|
Object.defineProperty(exports, "shouldBuildManualProductDiscount", {
|
|
105
106
|
enumerable: true,
|
|
106
107
|
get: function () {
|
|
@@ -125,6 +126,7 @@ var _decimal = _interopRequireDefault(require("decimal.js"));
|
|
|
125
126
|
var _utils = require("../Holder/utils");
|
|
126
127
|
var _utils2 = require("../../solution/ScanOrder/utils");
|
|
127
128
|
var _orderCollectionIdentity = require("./utils/orderCollectionIdentity");
|
|
129
|
+
var _salesNotes = require("./salesNotes");
|
|
128
130
|
var _manualProductDiscount = require("./utils/manualProductDiscount");
|
|
129
131
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
130
132
|
/**
|
|
@@ -855,6 +857,11 @@ function normalizeSubmitPlatform(platform) {
|
|
|
855
857
|
if (lower === 'h5') return 'H5';
|
|
856
858
|
return value;
|
|
857
859
|
}
|
|
860
|
+
function normalizeSubmitProductionCode(value) {
|
|
861
|
+
if (value === undefined || value === null) return undefined;
|
|
862
|
+
const productionCode = String(value).trim();
|
|
863
|
+
return productionCode || undefined;
|
|
864
|
+
}
|
|
858
865
|
|
|
859
866
|
// 后端 checkout 协议字段 option_group_item_id;tempOrder 内部也保持同一字段名。
|
|
860
867
|
function formatSubmitOptionItems(options) {
|
|
@@ -866,6 +873,9 @@ function formatSubmitOptionItems(options) {
|
|
|
866
873
|
option_group_item_id: d?.option_group_item_id,
|
|
867
874
|
option_group_id: d?.option_group_id
|
|
868
875
|
};
|
|
876
|
+
const productionCode = normalizeSubmitProductionCode(d?.production_code);
|
|
877
|
+
delete option.production_code;
|
|
878
|
+
if (productionCode !== undefined) option.production_code = productionCode;
|
|
869
879
|
const addPrice = d?.add_price ?? d?.price;
|
|
870
880
|
if (addPrice !== undefined) option.add_price = String(addPrice);
|
|
871
881
|
delete option.price;
|
|
@@ -906,9 +916,13 @@ function formatSubmitBundleItems(bundle) {
|
|
|
906
916
|
const num = toBundleNumber(rawBundle.num ?? rawBundle.quantity, 1);
|
|
907
917
|
const bundleMapId = resolveSubmitBundleMapId(rawBundle);
|
|
908
918
|
const hasSubmitBundleDiscounts = Array.isArray(rawBundle.discount_list) && rawBundle.discount_list.length > 0;
|
|
919
|
+
const productionCode = normalizeSubmitProductionCode(rawBundle.production_code);
|
|
909
920
|
return {
|
|
910
921
|
is_charge_tax: rawBundle.is_charge_tax ?? 0,
|
|
911
922
|
bundle_variant_id: rawBundle.bundle_variant_id ?? 0,
|
|
923
|
+
...(productionCode !== undefined ? {
|
|
924
|
+
production_code: productionCode
|
|
925
|
+
} : {}),
|
|
912
926
|
num,
|
|
913
927
|
quantity: toBundleNumber(rawBundle.quantity ?? rawBundle.num, num),
|
|
914
928
|
extension_id: rawBundle.extension_id ?? 0,
|
|
@@ -965,8 +979,10 @@ function normalizeSubmitProduct(product) {
|
|
|
965
979
|
discountway: _deprecatedDiscountway,
|
|
966
980
|
product_discount_reason: _deprecatedProductDiscountReason,
|
|
967
981
|
discount_per: _deprecatedDiscountPer,
|
|
982
|
+
production_code: rawProductionCode,
|
|
968
983
|
...productRest
|
|
969
984
|
} = submitProduct;
|
|
985
|
+
const productionCode = normalizeSubmitProductionCode(rawProductionCode);
|
|
970
986
|
delete productRest[`product_${'option'}_item`];
|
|
971
987
|
const rawMetadata = submitProduct.metadata || {};
|
|
972
988
|
const bookingUid = rawMetadata.booking_uid;
|
|
@@ -1000,6 +1016,9 @@ function normalizeSubmitProduct(product) {
|
|
|
1000
1016
|
};
|
|
1001
1017
|
return {
|
|
1002
1018
|
...productRest,
|
|
1019
|
+
...(productionCode !== undefined ? {
|
|
1020
|
+
production_code: productionCode
|
|
1021
|
+
} : {}),
|
|
1003
1022
|
...(bookingUid ? {
|
|
1004
1023
|
booking_uid: bookingUid
|
|
1005
1024
|
} : {}),
|
|
@@ -1110,6 +1129,7 @@ function createDefaultTempOrder(params) {
|
|
|
1110
1129
|
request_unique_idempotency_token: '',
|
|
1111
1130
|
vouchers: [],
|
|
1112
1131
|
products: [],
|
|
1132
|
+
notes: [],
|
|
1113
1133
|
bookings: [],
|
|
1114
1134
|
payments: [],
|
|
1115
1135
|
surcharges: [],
|
|
@@ -1119,10 +1139,58 @@ function createDefaultTempOrder(params) {
|
|
|
1119
1139
|
holder: null,
|
|
1120
1140
|
metadata: {},
|
|
1121
1141
|
_extend: {
|
|
1122
|
-
productsByUid: {}
|
|
1142
|
+
productsByUid: {},
|
|
1143
|
+
salesNotesState: {
|
|
1144
|
+
loaded: true,
|
|
1145
|
+
dirty: false
|
|
1146
|
+
}
|
|
1123
1147
|
}
|
|
1124
1148
|
};
|
|
1125
1149
|
}
|
|
1150
|
+
function hasBoundBookingResource(bookings) {
|
|
1151
|
+
if (!Array.isArray(bookings)) return false;
|
|
1152
|
+
return bookings.some(booking => {
|
|
1153
|
+
if (!booking || typeof booking !== 'object') return false;
|
|
1154
|
+
if (Number(booking.parent_id) === 0) return false;
|
|
1155
|
+
const resources = booking.resources;
|
|
1156
|
+
if (!Array.isArray(resources)) return false;
|
|
1157
|
+
return resources.some(resource => {
|
|
1158
|
+
if (!resource || typeof resource !== 'object') return false;
|
|
1159
|
+
const relationId = String(resource.relation_id ?? '').trim();
|
|
1160
|
+
return relationId !== '' && relationId !== '0';
|
|
1161
|
+
});
|
|
1162
|
+
});
|
|
1163
|
+
}
|
|
1164
|
+
function isPersistedSubmitOrderId(orderId) {
|
|
1165
|
+
if (orderId === undefined || orderId === null || orderId === '') return false;
|
|
1166
|
+
const normalizedOrderId = Number(orderId);
|
|
1167
|
+
return Number.isFinite(normalizedOrderId) && normalizedOrderId > 0;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
/**
|
|
1171
|
+
* 解析 checkout 的订单类型。
|
|
1172
|
+
* dine_in 普通落库单在新增桌台资源后,即使原类型仍是 virtual,也必须按 table-order 提交。
|
|
1173
|
+
*/
|
|
1174
|
+
function resolveSubmitOrderType(params) {
|
|
1175
|
+
const {
|
|
1176
|
+
requestedType,
|
|
1177
|
+
tempOrderType,
|
|
1178
|
+
orderId,
|
|
1179
|
+
businessCode,
|
|
1180
|
+
tempOrderBusinessCode,
|
|
1181
|
+
bookings
|
|
1182
|
+
} = params;
|
|
1183
|
+
const currentType = requestedType ?? tempOrderType;
|
|
1184
|
+
const resolvedBusinessCode = businessCode ?? tempOrderBusinessCode;
|
|
1185
|
+
if (isPersistedSubmitOrderId(orderId) && resolvedBusinessCode === 'dine_in' && currentType === 'virtual' && hasBoundBookingResource(bookings)) {
|
|
1186
|
+
return 'table-order';
|
|
1187
|
+
}
|
|
1188
|
+
if (currentType) return currentType;
|
|
1189
|
+
if (Array.isArray(bookings) && bookings.length > 0) {
|
|
1190
|
+
return businessCode === 'dine_in' ? 'table-order' : 'appointment_booking';
|
|
1191
|
+
}
|
|
1192
|
+
return 'virtual';
|
|
1193
|
+
}
|
|
1126
1194
|
function buildSubmitPayload(params) {
|
|
1127
1195
|
const {
|
|
1128
1196
|
tempOrder,
|
|
@@ -1156,22 +1224,18 @@ function buildSubmitPayload(params) {
|
|
|
1156
1224
|
total_refund_amount: _totalRefundAmount,
|
|
1157
1225
|
create_date: _createDate,
|
|
1158
1226
|
holder_id: _holderId,
|
|
1227
|
+
notes: _notes,
|
|
1159
1228
|
...tempOrderRest
|
|
1160
1229
|
} = tempOrder;
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
}
|
|
1171
|
-
} else {
|
|
1172
|
-
submitType = 'virtual';
|
|
1173
|
-
}
|
|
1174
|
-
}
|
|
1230
|
+
const resolvedBusinessCode = businessCode ?? tempOrder.business_code;
|
|
1231
|
+
const submitType = resolveSubmitOrderType({
|
|
1232
|
+
requestedType: type,
|
|
1233
|
+
tempOrderType: tempOrder.type,
|
|
1234
|
+
orderId: tempOrder.order_id,
|
|
1235
|
+
businessCode,
|
|
1236
|
+
tempOrderBusinessCode: tempOrder.business_code,
|
|
1237
|
+
bookings: tempOrder.bookings
|
|
1238
|
+
});
|
|
1175
1239
|
const payload = {
|
|
1176
1240
|
...tempOrderRest,
|
|
1177
1241
|
customer_id: tempOrder.customer_id ?? 1,
|
|
@@ -1185,7 +1249,7 @@ function buildSubmitPayload(params) {
|
|
|
1185
1249
|
platform: normalizeSubmitPlatform(platform),
|
|
1186
1250
|
request_unique_idempotency_token: params?.request_unique_idempotency_token || tempOrder.request_unique_idempotency_token || `${tempOrder.external_sale_number}_${now.getTime()}`,
|
|
1187
1251
|
type: submitType,
|
|
1188
|
-
business_code:
|
|
1252
|
+
business_code: resolvedBusinessCode,
|
|
1189
1253
|
sales_channel: tempOrder.sales_channel || 'my_pisel',
|
|
1190
1254
|
order_sales_channel: channel ?? tempOrder.order_sales_channel ?? 'online_store',
|
|
1191
1255
|
status: tempOrder.status || 'normal',
|
|
@@ -1218,6 +1282,11 @@ function buildSubmitPayload(params) {
|
|
|
1218
1282
|
...rest
|
|
1219
1283
|
};
|
|
1220
1284
|
})(),
|
|
1285
|
+
...(tempOrder._extend?.salesNotesState?.dirty ? {
|
|
1286
|
+
notes: (0, _salesNotes.encodeSalesNotes)(tempOrder.notes || [], {
|
|
1287
|
+
allowUnresolvedOrderTarget: true
|
|
1288
|
+
})
|
|
1289
|
+
} : {}),
|
|
1221
1290
|
products: (tempOrder.products || []).map(product => normalizeSubmitProduct(product))
|
|
1222
1291
|
};
|
|
1223
1292
|
if (!enhance) return payload;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { PisellCore } from '../../types';
|
|
2
|
+
import type { RequestPlugin } from '../../plugins';
|
|
3
|
+
import type { ProductData } from '../Product/types';
|
|
4
|
+
export declare const PRODUCT_QUERY_DATA_VARIANT_RELATIONS: readonly ["category", "collection", "resourceRelation", "bundleGroup.bundleItem", "optionGroup.optionItem", "variantGroup.variantItem", "dataVariants"];
|
|
5
|
+
/**
|
|
6
|
+
* 判断当前商品查询是否会被本地 OS Server 接管。
|
|
7
|
+
*
|
|
8
|
+
* H5 RequestPlugin 即使收到 osServer=true 仍会直接请求远端接口,因此必须按
|
|
9
|
+
* RequestPlugin 实际 baseUrl 对应的已注册路由判断,不能只看请求选项。
|
|
10
|
+
*/
|
|
11
|
+
export declare function isProductQueryHandledByOsServer(core: PisellCore | undefined, request: RequestPlugin | undefined): boolean;
|
|
12
|
+
export interface ResolveClientDataVariantsParams {
|
|
13
|
+
core: PisellCore | undefined;
|
|
14
|
+
otherParams?: Record<string, any>;
|
|
15
|
+
products: ProductData[];
|
|
16
|
+
queryPayload: Record<string, any>;
|
|
17
|
+
handledByOsServer: boolean;
|
|
18
|
+
scheduleList?: unknown;
|
|
19
|
+
menuList?: unknown;
|
|
20
|
+
/** Quote fast paths require hydrated relations; legacy list resolution does not. */
|
|
21
|
+
requireCompleteDataVariantRelations?: boolean;
|
|
22
|
+
/** Quote fast paths require every referenced rule; legacy list resolution is best-effort. */
|
|
23
|
+
requireEvaluatorReady?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export type ResolveClientDataVariantsResult = {
|
|
26
|
+
status: 'handled-by-os-server' | 'empty' | 'data-variants-unavailable' | 'evaluator-unavailable' | 'evaluator-not-ready';
|
|
27
|
+
products: ProductData[];
|
|
28
|
+
} | {
|
|
29
|
+
status: 'resolved';
|
|
30
|
+
products: ProductData[];
|
|
31
|
+
} | {
|
|
32
|
+
status: 'error';
|
|
33
|
+
products: ProductData[];
|
|
34
|
+
error: unknown;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Strict client-side Data Variant resolution for quote fast paths.
|
|
38
|
+
*
|
|
39
|
+
* Unlike resolveClientDataVariants, callers can distinguish a complete local
|
|
40
|
+
* result from a capability/readiness/error fallback and decide to query the
|
|
41
|
+
* remote product endpoint instead.
|
|
42
|
+
*/
|
|
43
|
+
export declare function tryResolveClientDataVariants({ core, otherParams, products, queryPayload, handledByOsServer, scheduleList: explicitScheduleList, menuList: explicitMenuList, requireCompleteDataVariantRelations, requireEvaluatorReady, }: ResolveClientDataVariantsParams): ResolveClientDataVariantsResult;
|
|
44
|
+
/**
|
|
45
|
+
* 未启用商品 OS 路由时,在客户端补做 Data Variant 解析。
|
|
46
|
+
*
|
|
47
|
+
* 商品列表和预约报价必须共用这个边界,避免 H5 的弹窗报价绕过客户端智能定价。
|
|
48
|
+
* OS Server 已接管时直接信任服务端结果,确保同一批商品只评估一次。
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveClientDataVariants({ core, otherParams, products, queryPayload, handledByOsServer, scheduleList: explicitScheduleList, menuList: explicitMenuList, }: ResolveClientDataVariantsParams): ProductData[];
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.PRODUCT_QUERY_DATA_VARIANT_RELATIONS = void 0;
|
|
7
|
+
exports.isProductQueryHandledByOsServer = isProductQueryHandledByOsServer;
|
|
8
|
+
exports.resolveClientDataVariants = resolveClientDataVariants;
|
|
9
|
+
exports.tryResolveClientDataVariants = tryResolveClientDataVariants;
|
|
10
|
+
const PRODUCT_QUERY_DATA_VARIANT_RELATIONS = exports.PRODUCT_QUERY_DATA_VARIANT_RELATIONS = ['category', 'collection', 'resourceRelation', 'bundleGroup.bundleItem', 'optionGroup.optionItem', 'variantGroup.variantItem', 'dataVariants'];
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 判断当前商品查询是否会被本地 OS Server 接管。
|
|
14
|
+
*
|
|
15
|
+
* H5 RequestPlugin 即使收到 osServer=true 仍会直接请求远端接口,因此必须按
|
|
16
|
+
* RequestPlugin 实际 baseUrl 对应的已注册路由判断,不能只看请求选项。
|
|
17
|
+
*/
|
|
18
|
+
function isProductQueryHandledByOsServer(core, request) {
|
|
19
|
+
const server = core?.server;
|
|
20
|
+
if (!server || typeof server.hasRoute !== 'function') return false;
|
|
21
|
+
const requestBaseUrl = String(request?.baseUrl || '/shop').replace(/\/+$/, '');
|
|
22
|
+
return server.hasRoute('post', `${requestBaseUrl}/product/query`) === true;
|
|
23
|
+
}
|
|
24
|
+
function getBundleItems(product) {
|
|
25
|
+
if (!Array.isArray(product.bundle_group)) return [];
|
|
26
|
+
return product.bundle_group.flatMap(group => Array.isArray(group?.bundle_item) ? group.bundle_item : []);
|
|
27
|
+
}
|
|
28
|
+
function hasCompleteDataVariantRelations(products) {
|
|
29
|
+
return products.every(product => Array.isArray(product?.data_variants));
|
|
30
|
+
}
|
|
31
|
+
function hasAnyDataVariants(products) {
|
|
32
|
+
return products.some(product => (product.data_variants?.length || 0) > 0 || getBundleItems(product).some(item => Array.isArray(item?.data_variants) && item.data_variants.length > 0));
|
|
33
|
+
}
|
|
34
|
+
function collectReferencedRuleIds(products) {
|
|
35
|
+
const ids = new Set();
|
|
36
|
+
const remember = variants => {
|
|
37
|
+
if (!Array.isArray(variants)) return;
|
|
38
|
+
variants.forEach(variant => {
|
|
39
|
+
const id = String(variant?.data_variant_rule_id ?? '').trim();
|
|
40
|
+
if (id) ids.add(id);
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
products.forEach(product => {
|
|
44
|
+
remember(product.data_variants);
|
|
45
|
+
getBundleItems(product).forEach(item => remember(item?.data_variants));
|
|
46
|
+
});
|
|
47
|
+
return ids;
|
|
48
|
+
}
|
|
49
|
+
function isEvaluatorReady(evaluator, products) {
|
|
50
|
+
if (typeof evaluator.isReady === 'function') {
|
|
51
|
+
if (evaluator.isReady() === false) return false;
|
|
52
|
+
}
|
|
53
|
+
if (evaluator.isReady === false || evaluator.ready === false) return false;
|
|
54
|
+
|
|
55
|
+
// The built-in evaluator is installed before its strategy request completes.
|
|
56
|
+
// A referenced Data Variant cannot be evaluated authoritatively until those
|
|
57
|
+
// configs have arrived. Evaluators without this capability remain compatible.
|
|
58
|
+
if (typeof evaluator.getStrategyConfigs === 'function') {
|
|
59
|
+
const configs = evaluator.getStrategyConfigs();
|
|
60
|
+
if (!Array.isArray(configs) || configs.length === 0) return false;
|
|
61
|
+
const availableRuleIds = new Set(configs.map(config => String(config?.metadata?.id ?? '').trim()).filter(Boolean));
|
|
62
|
+
return Array.from(collectReferencedRuleIds(products)).every(id => availableRuleIds.has(id));
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Strict client-side Data Variant resolution for quote fast paths.
|
|
69
|
+
*
|
|
70
|
+
* Unlike resolveClientDataVariants, callers can distinguish a complete local
|
|
71
|
+
* result from a capability/readiness/error fallback and decide to query the
|
|
72
|
+
* remote product endpoint instead.
|
|
73
|
+
*/
|
|
74
|
+
function tryResolveClientDataVariants({
|
|
75
|
+
core,
|
|
76
|
+
otherParams = {},
|
|
77
|
+
products,
|
|
78
|
+
queryPayload,
|
|
79
|
+
handledByOsServer,
|
|
80
|
+
scheduleList: explicitScheduleList,
|
|
81
|
+
menuList: explicitMenuList,
|
|
82
|
+
requireCompleteDataVariantRelations = true,
|
|
83
|
+
requireEvaluatorReady = true
|
|
84
|
+
}) {
|
|
85
|
+
if (handledByOsServer) {
|
|
86
|
+
return {
|
|
87
|
+
status: 'handled-by-os-server',
|
|
88
|
+
products
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (products.length === 0) {
|
|
92
|
+
return {
|
|
93
|
+
status: 'empty',
|
|
94
|
+
products
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
if (requireCompleteDataVariantRelations && !hasCompleteDataVariantRelations(products)) {
|
|
98
|
+
return {
|
|
99
|
+
status: 'data-variants-unavailable',
|
|
100
|
+
products
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Explicit empty arrays mean the query hydrated the relation and there is no
|
|
105
|
+
// rule to apply. This is an authoritative local base-price result even when
|
|
106
|
+
// no evaluator has been installed.
|
|
107
|
+
if (!hasAnyDataVariants(products)) {
|
|
108
|
+
return {
|
|
109
|
+
status: 'resolved',
|
|
110
|
+
products
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const evaluator = core?.context?.dataVariantEvaluator;
|
|
114
|
+
if (!evaluator || typeof evaluator.resolveProducts !== 'function') {
|
|
115
|
+
return {
|
|
116
|
+
status: 'evaluator-unavailable',
|
|
117
|
+
products
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
if (requireEvaluatorReady && !isEvaluatorReady(evaluator, products)) {
|
|
122
|
+
return {
|
|
123
|
+
status: 'evaluator-not-ready',
|
|
124
|
+
products
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
} catch (error) {
|
|
128
|
+
return {
|
|
129
|
+
status: 'error',
|
|
130
|
+
products,
|
|
131
|
+
error
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const strategyContext = queryPayload.strategy_context && typeof queryPayload.strategy_context === 'object' ? queryPayload.strategy_context : {};
|
|
135
|
+
const fatherModule = String(otherParams.fatherModule || '').trim();
|
|
136
|
+
const scheduleModule = (fatherModule ? core?.getModule(`${fatherModule}_schedule`) : null) || core?.getModule('schedule');
|
|
137
|
+
const moduleScheduleList = scheduleModule?.getScheduleList?.();
|
|
138
|
+
const contextScheduleList = core?.context?.scheduleList;
|
|
139
|
+
const contextMenuList = core?.context?.menuList;
|
|
140
|
+
const businessData = {
|
|
141
|
+
products,
|
|
142
|
+
scheduleDateTime: queryPayload.schedule_datetime || queryPayload.schedule_date,
|
|
143
|
+
scheduleList: Array.isArray(explicitScheduleList) && explicitScheduleList.length > 0 ? explicitScheduleList : Array.isArray(moduleScheduleList) && moduleScheduleList.length > 0 ? moduleScheduleList : Array.isArray(contextScheduleList) ? contextScheduleList : [],
|
|
144
|
+
menuList: Array.isArray(explicitMenuList) ? explicitMenuList : Array.isArray(otherParams.menuList) ? otherParams.menuList : Array.isArray(contextMenuList) ? contextMenuList : [],
|
|
145
|
+
customerId: queryPayload.customer_id,
|
|
146
|
+
channel: strategyContext.channel,
|
|
147
|
+
orderType: strategyContext.orderType || strategyContext.order_type,
|
|
148
|
+
businessCode: strategyContext.business_code ?? strategyContext.businessCode,
|
|
149
|
+
availableWalletIds: strategyContext.available_wallet_ids,
|
|
150
|
+
custom: strategyContext
|
|
151
|
+
};
|
|
152
|
+
try {
|
|
153
|
+
const result = evaluator.resolveProducts(businessData);
|
|
154
|
+
if (!Array.isArray(result?.products)) {
|
|
155
|
+
return {
|
|
156
|
+
status: 'error',
|
|
157
|
+
products,
|
|
158
|
+
error: new Error('Data Variant evaluator returned an invalid product list')
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
status: 'resolved',
|
|
163
|
+
products: result.products
|
|
164
|
+
};
|
|
165
|
+
} catch (error) {
|
|
166
|
+
return {
|
|
167
|
+
status: 'error',
|
|
168
|
+
products,
|
|
169
|
+
error
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* 未启用商品 OS 路由时,在客户端补做 Data Variant 解析。
|
|
176
|
+
*
|
|
177
|
+
* 商品列表和预约报价必须共用这个边界,避免 H5 的弹窗报价绕过客户端智能定价。
|
|
178
|
+
* OS Server 已接管时直接信任服务端结果,确保同一批商品只评估一次。
|
|
179
|
+
*/
|
|
180
|
+
function resolveClientDataVariants({
|
|
181
|
+
core,
|
|
182
|
+
otherParams = {},
|
|
183
|
+
products,
|
|
184
|
+
queryPayload,
|
|
185
|
+
handledByOsServer,
|
|
186
|
+
scheduleList: explicitScheduleList,
|
|
187
|
+
menuList: explicitMenuList
|
|
188
|
+
}) {
|
|
189
|
+
const result = tryResolveClientDataVariants({
|
|
190
|
+
core,
|
|
191
|
+
otherParams,
|
|
192
|
+
products,
|
|
193
|
+
queryPayload,
|
|
194
|
+
handledByOsServer,
|
|
195
|
+
scheduleList: explicitScheduleList,
|
|
196
|
+
menuList: explicitMenuList,
|
|
197
|
+
requireCompleteDataVariantRelations: false,
|
|
198
|
+
requireEvaluatorReady: false
|
|
199
|
+
});
|
|
200
|
+
if (result.status === 'error') {
|
|
201
|
+
console.error('[ClientDataVariants] Data Variant 客户端解析失败', result.error);
|
|
202
|
+
}
|
|
203
|
+
return result.products;
|
|
204
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Module, PisellCore } from '../../types';
|
|
2
2
|
import { BaseModule } from '../BaseModule';
|
|
3
|
-
import { ProductListLoadProductsParams } from './types';
|
|
3
|
+
import { ProductListLoadProductsParams, ProductListStoreQueryParams } from './types';
|
|
4
4
|
import { ProductData } from '../Product/types';
|
|
5
5
|
export * from './types';
|
|
6
6
|
export declare class ProductList extends BaseModule implements Module {
|
|
@@ -9,6 +9,7 @@ export declare class ProductList extends BaseModule implements Module {
|
|
|
9
9
|
private store;
|
|
10
10
|
private request;
|
|
11
11
|
private otherParams;
|
|
12
|
+
private rawProductPriceSources;
|
|
12
13
|
constructor(name?: string, version?: string);
|
|
13
14
|
initialize(core: PisellCore, options: any): Promise<void>;
|
|
14
15
|
/**
|
|
@@ -25,19 +26,33 @@ export declare class ProductList extends BaseModule implements Module {
|
|
|
25
26
|
* @example
|
|
26
27
|
* const products = await productList.getAddTimeProducts({ schedule_date: '2026-06-16' });
|
|
27
28
|
*/
|
|
28
|
-
getAddTimeProducts(params?: ProductListLoadProductsParams): Promise<
|
|
29
|
+
getAddTimeProducts(params?: ProductListLoadProductsParams): Promise<ProductData[]>;
|
|
29
30
|
loadProducts({ category_ids, product_ids, collection, menu_list_ids, customer_id: paramsCustomerId, with_count, schedule_datetime, schedule_date, cacheId, with_schedule, extension_type, status, strategy_context, }?: ProductListLoadProductsParams, options?: {
|
|
30
31
|
callback?: (result: any) => void;
|
|
31
32
|
subscriberId?: string;
|
|
32
|
-
}): Promise<
|
|
33
|
+
}): Promise<ProductData[]>;
|
|
33
34
|
loadProductsPrice({ ids, customer_id, schedule_date, channel, }: {
|
|
34
35
|
ids?: number[];
|
|
35
36
|
customer_id?: number;
|
|
36
37
|
schedule_date?: string;
|
|
37
38
|
channel?: string;
|
|
38
39
|
}): Promise<any>;
|
|
40
|
+
/**
|
|
41
|
+
* Remember raw remote product records before client-side Data Variant
|
|
42
|
+
* evaluation. Quote-only reads can then always start from a clean baseline.
|
|
43
|
+
*/
|
|
44
|
+
rememberRawProductQueryResult(products: Array<ProductData | Record<string, any>>): void;
|
|
45
|
+
private replaceRawProductQueryResult;
|
|
46
|
+
/**
|
|
47
|
+
* Return isolated raw price sources for the requested products.
|
|
48
|
+
*
|
|
49
|
+
* Missing IDs are intentionally omitted so callers can remotely fetch only
|
|
50
|
+
* the incomplete part of a batch quote.
|
|
51
|
+
*/
|
|
52
|
+
getRawProductPriceSources(ids: number[]): Map<number, ProductData>;
|
|
39
53
|
getProducts(): Promise<ProductData[]>;
|
|
40
54
|
getProduct(id: number): Promise<ProductData | undefined>;
|
|
55
|
+
queryProducts(params?: ProductListStoreQueryParams): Promise<ProductData[]>;
|
|
41
56
|
getProductByIds(ids: number[]): Promise<ProductData[] | undefined>;
|
|
42
57
|
addProduct(products: ProductData[]): Promise<void>;
|
|
43
58
|
selectProducts(products: ProductData[]): Promise<void>;
|