@pisell/pisellos 2.3.87 → 2.3.89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/modules/Order/types.d.ts +2 -0
  2. package/dist/modules/Order/utils.js +1 -0
  3. package/dist/modules/Product/types.d.ts +2 -0
  4. package/dist/modules/ResourcePlanner/planner.js +54 -17
  5. package/dist/modules/ResourcePlanner/types.d.ts +3 -0
  6. package/dist/modules/Rules/index.js +11 -8
  7. package/dist/solution/BaseSales/types.d.ts +2 -0
  8. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +3 -0
  9. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +7 -1
  10. package/dist/solution/BaseSales/utils.js +6 -3
  11. package/dist/solution/BookingByStep/index.d.ts +2 -2
  12. package/dist/solution/BookingTicket/utils/addProductDecision.js +3 -1
  13. package/dist/solution/ScanOrder/types.d.ts +2 -0
  14. package/dist/solution/ScanOrder/utils.js +6 -3
  15. package/dist/solution/UnifiedBookingSales/index.js +62 -32
  16. package/lib/model/strategy/adapter/promotion/index.js +46 -1
  17. package/lib/modules/Order/types.d.ts +2 -0
  18. package/lib/modules/Order/utils.js +1 -0
  19. package/lib/modules/Product/types.d.ts +2 -0
  20. package/lib/modules/ResourcePlanner/planner.js +48 -17
  21. package/lib/modules/ResourcePlanner/types.d.ts +3 -0
  22. package/lib/modules/Rules/index.js +8 -6
  23. package/lib/solution/BaseSales/types.d.ts +2 -0
  24. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.d.ts +3 -0
  25. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +6 -0
  26. package/lib/solution/BaseSales/utils.js +3 -0
  27. package/lib/solution/BookingByStep/index.d.ts +2 -2
  28. package/lib/solution/BookingTicket/utils/addProductDecision.js +2 -0
  29. package/lib/solution/ScanOrder/types.d.ts +2 -0
  30. package/lib/solution/ScanOrder/utils.js +3 -0
  31. package/lib/solution/UnifiedBookingSales/index.js +37 -1
  32. package/package.json +1 -1
@@ -191,6 +191,8 @@ export interface OrderLocalizedText {
191
191
  export interface OrderProduct extends OrderProductIdentity {
192
192
  order_detail_id: number | null;
193
193
  num: number;
194
+ /** Product 或当前 Variant 的生产编码 */
195
+ production_code?: string;
194
196
  bundle_edit?: number;
195
197
  product_sku: OrderProductSku;
196
198
  gift_card?: number;
@@ -868,6 +868,7 @@ function formatSubmitBundleItems(bundle) {
868
868
  return {
869
869
  is_charge_tax: (_rawBundle$is_charge_ = rawBundle.is_charge_tax) !== null && _rawBundle$is_charge_ !== void 0 ? _rawBundle$is_charge_ : 0,
870
870
  bundle_variant_id: (_rawBundle$bundle_var = rawBundle.bundle_variant_id) !== null && _rawBundle$bundle_var !== void 0 ? _rawBundle$bundle_var : 0,
871
+ production_code: rawBundle.production_code,
871
872
  num: num,
872
873
  quantity: toBundleNumber((_rawBundle$quantity = rawBundle.quantity) !== null && _rawBundle$quantity !== void 0 ? _rawBundle$quantity : rawBundle.num, num),
873
874
  extension_id: (_rawBundle$extension_ = rawBundle.extension_id) !== null && _rawBundle$extension_ !== void 0 ? _rawBundle$extension_ : 0,
@@ -77,6 +77,8 @@ export interface ProductData {
77
77
  is_gst: number;
78
78
  /** 商品编码 */
79
79
  code: string;
80
+ /** ERP/生产侧商品编码;有规格时以选中 Variant 的值为准 */
81
+ production_code?: string;
80
82
  /** 商品条码 */
81
83
  barcode: string;
82
84
  /** 是否支持配送 */
@@ -52,6 +52,23 @@ function normalizeBookingCount(bookingCount) {
52
52
  }
53
53
  return normalized;
54
54
  }
55
+ function resolveRequestedDurationMinutes(product, request) {
56
+ var _request$durationMinu;
57
+ var configured = Math.max(1, Number(product.durationMinutes || 30) || 30);
58
+ if (product.kind !== 'duration') return configured;
59
+ var override = (_request$durationMinu = request.durationMinutesByProductId) === null || _request$durationMinu === void 0 ? void 0 : _request$durationMinu[String(product.id)];
60
+ var normalized = Number(override);
61
+ return Number.isInteger(normalized) && normalized > 0 ? normalized : configured;
62
+ }
63
+ function resolveRequestedDurationStartTimes(product, request) {
64
+ var _request$durationStar;
65
+ if (product.kind !== 'duration') return [];
66
+ var values = (_request$durationStar = request.durationStartTimesByProductId) === null || _request$durationStar === void 0 ? void 0 : _request$durationStar[String(product.id)];
67
+ if (!Array.isArray(values)) return [];
68
+ return Array.from(new Set(values.filter(function (value) {
69
+ return typeof value === 'string' && /^([01]\d|2[0-3]):[0-5]\d$/.test(value);
70
+ })));
71
+ }
55
72
  function toDateTime(value, _timezoneName) {
56
73
  try {
57
74
  return localDateTimeToScalar(parseLocalDateTime(value));
@@ -962,11 +979,29 @@ function dedupeProductRanges(ranges) {
962
979
  return left.startAt.localeCompare(right.startAt);
963
980
  });
964
981
  }
982
+ function createDurationTimeRange(product, start, durationMinutes, projection, fixedOffsetMinutes) {
983
+ var bookingEnd = addMinutesZoned(start, durationMinutes, projection.meta.timezone);
984
+ return {
985
+ key: "".concat(String(product.id), ":").concat(start, ":").concat(bookingEnd),
986
+ productId: product.id,
987
+ source: 'duration_window',
988
+ startAt: formatDateTime(start, projection.meta.timezone, fixedOffsetMinutes),
989
+ endAt: formatDateTime(bookingEnd, projection.meta.timezone, fixedOffsetMinutes),
990
+ bookingStartAt: formatDateTime(start, projection.meta.timezone, fixedOffsetMinutes),
991
+ bookingEndAt: formatDateTime(bookingEnd, projection.meta.timezone, fixedOffsetMinutes),
992
+ date: formatDate(start, projection.meta.timezone),
993
+ startTime: formatTime(start, projection.meta.timezone),
994
+ endTime: formatTime(bookingEnd, projection.meta.timezone),
995
+ timezone: projection.meta.timezone,
996
+ scheduleRefs: []
997
+ };
998
+ }
965
999
  export function getProductTimeRanges(projection) {
966
1000
  var _extractFixedOffsetMi3, _request$productIds;
967
1001
  var request = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
968
1002
  var normalizedPartySize = normalizePartySize(request.partySize);
969
1003
  var dateRange = resolveProjectionDateRange(projection, request.dateRange);
1004
+ var slotStepMinutes = projection.meta.defaults.slotStepMinutes;
970
1005
  var fixedOffsetMinutes = (_extractFixedOffsetMi3 = extractFixedOffsetMinutes(projection.meta.now)) !== null && _extractFixedOffsetMi3 !== void 0 ? _extractFixedOffsetMi3 : captureRuntimeOffsetMinutes();
971
1006
  var resourceWindowIndex = buildResourceWindowIndex(projection);
972
1007
  var filteredProductIdSet = (_request$productIds = request.productIds) !== null && _request$productIds !== void 0 && _request$productIds.length ? new Set(request.productIds.map(String)) : null;
@@ -978,6 +1013,7 @@ export function getProductTimeRanges(projection) {
978
1013
  productId: product.id,
979
1014
  title: product.title,
980
1015
  kind: product.kind,
1016
+ slotStepMinutes: slotStepMinutes,
981
1017
  ranges: []
982
1018
  };
983
1019
  }
@@ -986,6 +1022,7 @@ export function getProductTimeRanges(projection) {
986
1022
  productId: product.id,
987
1023
  title: product.title,
988
1024
  kind: product.kind,
1025
+ slotStepMinutes: slotStepMinutes,
989
1026
  ranges: getSessionRangesForProduct(projection, product, dateRange)
990
1027
  };
991
1028
  }
@@ -1007,9 +1044,9 @@ export function getProductTimeRanges(projection) {
1007
1044
  return current === null ? ranges : intersectRangeLists(current, ranges);
1008
1045
  }, null) || [] : null;
1009
1046
  var baseRanges = resourceRanges === null ? operatingRanges : intersectRangeLists(resourceRanges, operatingRanges);
1010
- var durationMinutes = Math.max(1, Number(product.durationMinutes || 30) || 30);
1011
- var timeSliceMinutes = projection.meta.defaults.slotStepMinutes;
1047
+ var durationMinutes = resolveRequestedDurationMinutes(product, request);
1012
1048
  var durationAnchor = ceilToTenMinutes(toDateTime(projection.meta.durationCandidateAnchorAt, projection.meta.timezone), projection.meta.timezone);
1049
+ var requestedStartTimes = resolveRequestedDurationStartTimes(product, request);
1013
1050
  var ranges = [];
1014
1051
  baseRanges.forEach(function (range) {
1015
1052
  if (range.end <= durationAnchor) return;
@@ -1022,28 +1059,28 @@ export function getProductTimeRanges(projection) {
1022
1059
  if (bookingEnd > range.end) break;
1023
1060
  var bookingDate = formatDate(cursor);
1024
1061
  if (bookingDate >= dateRange.startDate && bookingDate <= dateRange.endDate) {
1025
- ranges.push({
1026
- key: "".concat(String(product.id), ":").concat(cursor, ":").concat(bookingEnd),
1027
- productId: product.id,
1028
- source: 'duration_window',
1029
- startAt: formatDateTime(cursor, projection.meta.timezone, fixedOffsetMinutes),
1030
- endAt: formatDateTime(bookingEnd, projection.meta.timezone, fixedOffsetMinutes),
1031
- bookingStartAt: formatDateTime(cursor, projection.meta.timezone, fixedOffsetMinutes),
1032
- bookingEndAt: formatDateTime(bookingEnd, projection.meta.timezone, fixedOffsetMinutes),
1033
- date: formatDate(cursor, projection.meta.timezone),
1034
- startTime: formatTime(cursor, projection.meta.timezone),
1035
- endTime: formatTime(bookingEnd, projection.meta.timezone),
1036
- timezone: projection.meta.timezone,
1037
- scheduleRefs: []
1038
- });
1062
+ ranges.push(createDurationTimeRange(product, cursor, durationMinutes, projection, fixedOffsetMinutes));
1039
1063
  }
1040
- cursor = addMinutesZoned(cursor, timeSliceMinutes, projection.meta.timezone);
1064
+ cursor = addMinutesZoned(cursor, slotStepMinutes, projection.meta.timezone);
1041
1065
  }
1042
1066
  });
1067
+ if (dateRange.startDate === dateRange.endDate && requestedStartTimes.length > 0) {
1068
+ requestedStartTimes.forEach(function (startTime) {
1069
+ var start = toDateTimeInDate(dateRange.startDate, startTime, projection.meta.timezone);
1070
+ if (!Number.isFinite(start)) return;
1071
+ var end = addMinutesZoned(start, durationMinutes, projection.meta.timezone);
1072
+ var startsInOperatingRange = operatingRanges.some(function (range) {
1073
+ return range.start <= start && start < range.end;
1074
+ });
1075
+ if (!startsInOperatingRange) return;
1076
+ ranges.push(createDurationTimeRange(product, start, durationMinutes, projection, fixedOffsetMinutes));
1077
+ });
1078
+ }
1043
1079
  return {
1044
1080
  productId: product.id,
1045
1081
  title: product.title,
1046
1082
  kind: product.kind,
1083
+ slotStepMinutes: slotStepMinutes,
1047
1084
  ranges: dedupeProductRanges(ranges)
1048
1085
  };
1049
1086
  });
@@ -211,6 +211,7 @@ export interface ProductTimeRangeGroup {
211
211
  productId: AvailabilityId;
212
212
  title?: string;
213
213
  kind: AvailabilityProductKind;
214
+ slotStepMinutes?: number;
214
215
  ranges: ProductTimeRange[];
215
216
  }
216
217
  export interface AvailabilityAssignment extends AvailabilityAbsoluteRange {
@@ -231,6 +232,8 @@ export interface GetProductTimeRangesRequest {
231
232
  dateRange?: Partial<AvailabilityDateRange>;
232
233
  resourceIds?: AvailabilityId[];
233
234
  partySize?: number;
235
+ durationMinutesByProductId?: Record<string, number>;
236
+ durationStartTimesByProductId?: Record<string, string[]>;
234
237
  }
235
238
  export interface QueryAvailabilityBaseRequest {
236
239
  productIds?: AvailabilityId[];
@@ -2223,7 +2223,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2223
2223
  }, {
2224
2224
  key: "checkPackageSubItemUsageRules",
2225
2225
  value: function checkPackageSubItemUsageRules(discount, flatItem) {
2226
- var _flatItem$product;
2226
+ var _flatItem$product, _flatItem$originProdu, _flatItem$parentProdu10;
2227
2227
  var limitedData = discount.limited_relation_product_data;
2228
2228
  var usageRules = limitedData === null || limitedData === void 0 ? void 0 : limitedData.package_sub_item_usage_rules;
2229
2229
  var rules = ['original_price'].concat(_toConsumableArray((usageRules === null || usageRules === void 0 ? void 0 : usageRules.rules) || []));
@@ -2236,7 +2236,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2236
2236
  // 套餐适用范围配置
2237
2237
  var packageScope = usageRules === null || usageRules === void 0 ? void 0 : usageRules.package_scope;
2238
2238
  var _ref18 = packageScope || {},
2239
- scopeType = _ref18.type,
2239
+ _ref18$type = _ref18.type,
2240
+ scopeType = _ref18$type === void 0 ? 'product_all' : _ref18$type,
2240
2241
  _ref18$exclude_bundle = _ref18.exclude_bundle_product_ids,
2241
2242
  exclude_bundle_product_ids = _ref18$exclude_bundle === void 0 ? [] : _ref18$exclude_bundle,
2242
2243
  _ref18$include_bundle = _ref18.include_bundle_product_ids,
@@ -2246,6 +2247,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2246
2247
  var isMainProduct = flatItem.type === 'main'; // 单独购买
2247
2248
  var isBundleItem = flatItem.type === 'bundle'; // 套餐中购买
2248
2249
  var bundleMainProductId = (_flatItem$product = flatItem.product) === null || _flatItem$product === void 0 ? void 0 : _flatItem$product.product_id;
2250
+ // 主商品id
2251
+ var mainProductId = (flatItem === null || flatItem === void 0 || (_flatItem$originProdu = flatItem.originProduct) === null || _flatItem$originProdu === void 0 || (_flatItem$originProdu = _flatItem$originProdu._productOrigin) === null || _flatItem$originProdu === void 0 ? void 0 : _flatItem$originProdu.id) || (flatItem === null || flatItem === void 0 || (_flatItem$parentProdu10 = flatItem.parentProduct) === null || _flatItem$parentProdu10 === void 0 ? void 0 : _flatItem$parentProdu10.id) || 0;
2249
2252
 
2250
2253
  // 主商品直接可用
2251
2254
  if (isMainProduct) {
@@ -2258,12 +2261,12 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2258
2261
  return true; // 单独购买时可用
2259
2262
  }
2260
2263
  if (isBundleItem) {
2261
- var _flatItem$bundleItem10, _flatItem$bundleItem11, _flatItem$originProdu, _flatItem$parentProdu10;
2264
+ var _flatItem$bundleItem10, _flatItem$bundleItem11;
2262
2265
  // 套餐中购买时,判断是否为原价
2263
2266
  var priceType = (_flatItem$bundleItem10 = flatItem.bundleItem) === null || _flatItem$bundleItem10 === void 0 ? void 0 : _flatItem$bundleItem10.price_type;
2264
2267
  var priceTypeExt = (_flatItem$bundleItem11 = flatItem.bundleItem) === null || _flatItem$bundleItem11 === void 0 ? void 0 : _flatItem$bundleItem11.price_type_ext;
2265
2268
  // 主商品id
2266
- var mainProductId = (flatItem === null || flatItem === void 0 || (_flatItem$originProdu = flatItem.originProduct) === null || _flatItem$originProdu === void 0 || (_flatItem$originProdu = _flatItem$originProdu._productOrigin) === null || _flatItem$originProdu === void 0 ? void 0 : _flatItem$originProdu.id) || (flatItem === null || flatItem === void 0 || (_flatItem$parentProdu10 = flatItem.parentProduct) === null || _flatItem$parentProdu10 === void 0 ? void 0 : _flatItem$parentProdu10.id) || 0;
2269
+ // const mainProductId = flatItem?.originProduct?._productOrigin?.id || flatItem?.parentProduct?.id || 0;
2267
2270
  // original_price 对应:
2268
2271
  // 1. price_type: "markup" && price_type_ext: "product_price"
2269
2272
  // markup_price 对应:
@@ -2288,13 +2291,13 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2288
2291
  if (!filter) {
2289
2292
  isScopeValid = true;
2290
2293
  } else {
2291
- isScopeValid = !exclude_bundle_product_ids.includes(Number(bundleMainProductId));
2294
+ isScopeValid = !exclude_bundle_product_ids.includes(Number(mainProductId));
2292
2295
  }
2293
2296
  }
2294
2297
 
2295
2298
  // 包含套餐判断, products值兼容旧数据
2296
2299
  if (scopeType === 'specific_packages' || scopeType === 'products') {
2297
- isScopeValid = include_bundle_product_ids.includes(Number(bundleMainProductId));
2300
+ isScopeValid = include_bundle_product_ids.includes(Number(mainProductId));
2298
2301
  }
2299
2302
 
2300
2303
  // 价格和套餐适用范围都符合,则可用
@@ -2357,13 +2360,13 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2357
2360
  if (!filter) {
2358
2361
  _isScopeValid = true;
2359
2362
  } else {
2360
- _isScopeValid = !exclude_bundle_product_ids.includes(Number(bundleMainProductId));
2363
+ _isScopeValid = !exclude_bundle_product_ids.includes(Number(mainProductId));
2361
2364
  }
2362
2365
  }
2363
2366
 
2364
2367
  // 包含套餐判断, products值兼容旧数据
2365
2368
  if (scopeType === 'specific_packages' || scopeType === 'products') {
2366
- _isScopeValid = include_bundle_product_ids.includes(Number(bundleMainProductId));
2369
+ _isScopeValid = include_bundle_product_ids.includes(Number(mainProductId));
2367
2370
  }
2368
2371
 
2369
2372
  // 价格和套餐适用范围都符合,则可用
@@ -112,6 +112,8 @@ export interface BaseSalesUpdateOrderProductQuantityParams extends BaseSalesOrde
112
112
  export interface BaseSalesOrderProduct extends BaseSalesOrderProductIdentity {
113
113
  order_detail_id: number | null;
114
114
  num: number;
115
+ /** Product 或当前 Variant 的生产编码 */
116
+ production_code?: string;
115
117
  product_sku: BaseSalesProductSku;
116
118
  /**
117
119
  * 券后 **行 composite 单价** = `metadata.main_product_selling_price`
@@ -3,6 +3,7 @@ import type { ProductData } from '../../../modules/Product/types';
3
3
  export interface BaseProductDetailOptionItem {
4
4
  option_group_item_id?: number | string;
5
5
  option_group_id?: number | string;
6
+ production_code?: string;
6
7
  num?: number | string;
7
8
  quantity?: number | string;
8
9
  price?: number | string;
@@ -10,6 +11,7 @@ export interface BaseProductDetailOptionItem {
10
11
  [key: string]: any;
11
12
  }
12
13
  export interface BaseProductDetailBundleItem {
14
+ production_code?: string;
13
15
  option?: BaseProductDetailOptionItem[];
14
16
  [key: string]: any;
15
17
  }
@@ -18,6 +20,7 @@ export interface BaseProductDetailPayload {
18
20
  product_id?: number | string | null;
19
21
  variant_id?: number | string | null;
20
22
  product_variant_id?: number | string | null;
23
+ production_code?: string;
21
24
  quantity?: number | string;
22
25
  num?: number | string;
23
26
  option?: BaseProductDetailOptionItem[];
@@ -30,6 +30,10 @@ function toPriceString(value) {
30
30
  if (!Number.isFinite(parsedValue)) return fallback;
31
31
  return parsedValue.toFixed(2);
32
32
  }
33
+ function normalizeProductionCode(value) {
34
+ if (value === undefined || value === null) return '';
35
+ return String(value).trim();
36
+ }
33
37
  function isBlankValue(value) {
34
38
  return value === undefined || value === null || typeof value === 'string' && value.trim() === '';
35
39
  }
@@ -104,7 +108,7 @@ function findVariantById(origin, variantId) {
104
108
  * 注意:这里不生成 identity,缺省时由 OrderModule 自动补齐。
105
109
  */
106
110
  export function transformBaseProductToOrderProduct(params) {
107
- var _ref10, _ref11, _ref12, _payload$product_id, _ref13, _ref14, _payload$product_vari, _payload$_origin, _payload$_origin2, _ref15, _findVariantById, _ref16, _ref17, _ref18, _ref19, _ref20, _matchedVariant$price, _ref21, _ref22, _payload$price, _ref23, _payload$line_total, _payload$_extend, _ref24, _ref25, _payload$product_sku$, _payload$product_sku, _payload$bundle, _payload$quantity, _payload$_extend2, _extend, _extend2, _ref26, _ref27, _origin$base_price, _ref28, _ref29, _payload$line_total2, _payload$_extend3, _payload$_extend4, _extend3, _payload$_extend5, _payload$_extend6, _ref30, _ref31, _payload$tax_fee, _ref32, _ref33, _payload$is_charge_ta;
111
+ var _ref10, _ref11, _ref12, _payload$product_id, _ref13, _ref14, _payload$product_vari, _payload$_origin, _payload$_origin2, _ref15, _findVariantById, _origin$production_co, _ref16, _ref17, _ref18, _ref19, _ref20, _matchedVariant$price, _ref21, _ref22, _payload$price, _ref23, _payload$line_total, _payload$_extend, _ref24, _ref25, _payload$product_sku$, _payload$product_sku, _payload$bundle, _payload$quantity, _payload$_extend2, _extend, _extend2, _ref26, _ref27, _origin$base_price, _ref28, _ref29, _payload$line_total2, _payload$_extend3, _payload$_extend4, _extend3, _payload$_extend5, _payload$_extend6, _ref30, _ref31, _payload$tax_fee, _ref32, _ref33, _payload$is_charge_ta;
108
112
  var payload = params.payload,
109
113
  _params$fallbackProdu = params.fallbackProductId,
110
114
  fallbackProductId = _params$fallbackProdu === void 0 ? null : _params$fallbackProdu;
@@ -116,6 +120,7 @@ export function transformBaseProductToOrderProduct(params) {
116
120
  var callbackOrigin = payload.origin || ((_payload$_origin = payload._origin) === null || _payload$_origin === void 0 ? void 0 : _payload$_origin.sourceProduct) || ((_payload$_origin2 = payload._origin) === null || _payload$_origin2 === void 0 ? void 0 : _payload$_origin2.sourceItem) || payload._origin || {};
117
121
  var origin = _objectSpread(_objectSpread({}, sourceProduct || {}), callbackOrigin || {});
118
122
  var matchedVariant = (_ref15 = (_findVariantById = findVariantById(callbackOrigin, productVariantId)) !== null && _findVariantById !== void 0 ? _findVariantById : findVariantById(sourceProduct, productVariantId)) !== null && _ref15 !== void 0 ? _ref15 : findVariantById(origin, productVariantId);
123
+ var productionCode = normalizeProductionCode(Object.prototype.hasOwnProperty.call(payload, 'production_code') ? payload.production_code : productVariantId > 0 ? matchedVariant === null || matchedVariant === void 0 ? void 0 : matchedVariant.production_code : (_origin$production_co = origin === null || origin === void 0 ? void 0 : origin.production_code) !== null && _origin$production_co !== void 0 ? _origin$production_co : sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.production_code);
119
124
  var hasPriceOverride = payload.price_override !== undefined && payload.price_override !== null && payload.price_override !== '';
120
125
  // 手动改价后 payload.price 是分摊后的主商品售价,不能再作为券前 source。
121
126
  // 此时优先从商品/variant 快照读取目录价;售价仍由 line_total - bundle 推导。
@@ -198,6 +203,7 @@ export function transformBaseProductToOrderProduct(params) {
198
203
  return _objectSpread(_objectSpread({
199
204
  product_id: productId,
200
205
  product_variant_id: productVariantId,
206
+ production_code: productionCode,
201
207
  unique_identification_number: uniqueIdentificationNumber ? String(uniqueIdentificationNumber) : undefined,
202
208
  num: resolvedQuantity,
203
209
  product_sku: _objectSpread(_objectSpread({}, payload.product_sku && _typeof(payload.product_sku) === 'object' ? payload.product_sku : {}), {}, {
@@ -256,11 +256,14 @@ export function normalizeOrderProduct(product) {
256
256
  sellingPrice: composedSellingPrice,
257
257
  quantity: getSafeProductNum(product.num)
258
258
  });
259
- return {
259
+ return _objectSpread(_objectSpread({
260
260
  order_detail_id: product.order_detail_id || null,
261
261
  product_id: product.product_id,
262
262
  num: getSafeProductNum(product.num),
263
- product_variant_id: product.product_variant_id,
263
+ product_variant_id: product.product_variant_id
264
+ }, product.production_code !== undefined && product.production_code !== null ? {
265
+ production_code: String(product.production_code).trim()
266
+ } : {}), {}, {
264
267
  product_sku: productSku,
265
268
  selling_price: composedSellingPrice,
266
269
  original_price: finalOriginalPrice,
@@ -270,5 +273,5 @@ export function normalizeOrderProduct(product) {
270
273
  product_bundle: normalizedBundle,
271
274
  metadata: metadata,
272
275
  note: product.note != null ? String(product.note) : ''
273
- };
276
+ });
274
277
  }
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
326
326
  date: string;
327
327
  status: string;
328
328
  week: string;
329
- weekNum: 0 | 1 | 2 | 5 | 3 | 4 | 6;
329
+ weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
@@ -345,7 +345,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
345
345
  count: number;
346
346
  left: number;
347
347
  summaryCount: number;
348
- status: "sold_out" | "lots_of_space" | "filling_up_fast";
348
+ status: "lots_of_space" | "filling_up_fast" | "sold_out";
349
349
  }[];
350
350
  /**
351
351
  * 找到多个资源的公共可用时间段
@@ -319,7 +319,7 @@ export function transformDetailToProductAndBooking(cacheItem, ctx) {
319
319
  * 把 cacheItem._extend.other 中的字段 + 顶层运行态拼成 `BaseProductDetailPayload`。
320
320
  */
321
321
  function buildBasePayloadFromCacheItem(cacheItem, ctx) {
322
- var _cacheItem$_extend, _cacheItem$_extend$qu, _cacheItem$_extend2, _cacheItem$product_id, _cacheItem$id, _ref5, _other$product_varian, _extend$skuValue, _extend$_skuValue, _extend$price, _extend$price2;
322
+ var _cacheItem$_extend, _cacheItem$_extend$qu, _cacheItem$_extend2, _cacheItem$product_id, _cacheItem$id, _ref5, _other$product_varian, _other$production_cod, _extend$skuValue, _extend$_skuValue, _extend$price, _extend$price2;
323
323
  var other = (cacheItem === null || cacheItem === void 0 || (_cacheItem$_extend = cacheItem._extend) === null || _cacheItem$_extend === void 0 ? void 0 : _cacheItem$_extend.other) || {};
324
324
  var quantity = (ctx === null || ctx === void 0 ? void 0 : ctx.quantity) != null && ctx.quantity > 0 ? ctx.quantity : (_cacheItem$_extend$qu = cacheItem === null || cacheItem === void 0 || (_cacheItem$_extend2 = cacheItem._extend) === null || _cacheItem$_extend2 === void 0 ? void 0 : _cacheItem$_extend2.quantity) !== null && _cacheItem$_extend$qu !== void 0 ? _cacheItem$_extend$qu : 1;
325
325
  var resolvedPid = (_cacheItem$product_id = cacheItem === null || cacheItem === void 0 ? void 0 : cacheItem.product_id) !== null && _cacheItem$product_id !== void 0 ? _cacheItem$product_id : cacheItem === null || cacheItem === void 0 ? void 0 : cacheItem.id;
@@ -329,6 +329,8 @@ function buildBasePayloadFromCacheItem(cacheItem, ctx) {
329
329
  id: (_cacheItem$id = cacheItem === null || cacheItem === void 0 ? void 0 : cacheItem.id) !== null && _cacheItem$id !== void 0 ? _cacheItem$id : cacheItem === null || cacheItem === void 0 ? void 0 : cacheItem.product_id,
330
330
  product_id: resolvedPid,
331
331
  variant_id: (_ref5 = (_other$product_varian = other === null || other === void 0 ? void 0 : other.product_variant_id) !== null && _other$product_varian !== void 0 ? _other$product_varian : other === null || other === void 0 ? void 0 : other.variant_id) !== null && _ref5 !== void 0 ? _ref5 : 0,
332
+ // SKUOptionsSelection 已按 Product / Variant 解析好主商品编码;显式空串也需保留。
333
+ production_code: (_other$production_cod = other === null || other === void 0 ? void 0 : other.production_code) !== null && _other$production_cod !== void 0 ? _other$production_cod : cacheItem === null || cacheItem === void 0 ? void 0 : cacheItem.production_code,
332
334
  quantity: quantity,
333
335
  // 规格弹窗本次选择是 option 权威源,避免目录/旧订单里的空 option 覆盖它。
334
336
  product_sku: productSku ? _objectSpread(_objectSpread({}, productSku), {}, {
@@ -44,6 +44,8 @@ export interface ScanOrderProductSku {
44
44
  export interface ScanOrderOrderProduct extends ScanOrderOrderProductIdentity {
45
45
  order_detail_id: number | null;
46
46
  num: number;
47
+ /** Product 或当前 Variant 的生产编码 */
48
+ production_code?: string;
47
49
  product_sku: ScanOrderProductSku;
48
50
  /**
49
51
  * 券后 **行 composite 单价** = `metadata.main_product_selling_price`
@@ -660,11 +660,14 @@ export function normalizeOrderProduct(product) {
660
660
  sellingPrice: composedSellingPrice,
661
661
  quantity: getSafeProductNum(product.num)
662
662
  });
663
- return {
663
+ return _objectSpread(_objectSpread({
664
664
  order_detail_id: product.order_detail_id || null,
665
665
  product_id: product.product_id,
666
666
  num: getSafeProductNum(product.num),
667
- product_variant_id: product.product_variant_id,
667
+ product_variant_id: product.product_variant_id
668
+ }, product.production_code !== undefined && product.production_code !== null ? {
669
+ production_code: String(product.production_code).trim()
670
+ } : {}), {}, {
668
671
  product_sku: productSku,
669
672
  selling_price: composedSellingPrice,
670
673
  original_price: manualOriginalPrice,
@@ -674,7 +677,7 @@ export function normalizeOrderProduct(product) {
674
677
  product_bundle: normalizedBundle,
675
678
  metadata: metadata,
676
679
  note: product.note != null ? String(product.note) : ''
677
- };
680
+ });
678
681
  }
679
682
 
680
683
  /**
@@ -52,6 +52,30 @@ function normalizePositiveInteger(value) {
52
52
  if (!Number.isInteger(normalized) || normalized <= 0) return undefined;
53
53
  return normalized;
54
54
  }
55
+ function getCandidateDurationMinutes(candidate) {
56
+ var startAt = candidate.bookingStartAt || candidate.startAt;
57
+ var endAt = candidate.bookingEndAt || candidate.endAt;
58
+ try {
59
+ var start = localDateTimeToScalar(parseLocalDateTime(startAt));
60
+ var end = localDateTimeToScalar(parseLocalDateTime(endAt));
61
+ var minutes = Math.round((end - start) / 60000);
62
+ return Number.isInteger(minutes) && minutes > 0 ? minutes : undefined;
63
+ } catch (_error) {
64
+ return undefined;
65
+ }
66
+ }
67
+ function getCandidateStartTime(candidate) {
68
+ if (/^([01]\d|2[0-3]):[0-5]\d$/.test(candidate.startTime || '')) {
69
+ return candidate.startTime;
70
+ }
71
+ var startAt = candidate.bookingStartAt || candidate.startAt;
72
+ try {
73
+ var start = parseLocalDateTime(startAt);
74
+ return "".concat(String(start.hour).padStart(2, '0'), ":").concat(String(start.minute).padStart(2, '0'));
75
+ } catch (_error) {
76
+ return undefined;
77
+ }
78
+ }
55
79
  function isRecord(value) {
56
80
  return !!value && _typeof(value) === 'object' && !Array.isArray(value);
57
81
  }
@@ -4332,7 +4356,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
4332
4356
  key: "commitAvailabilitySelection",
4333
4357
  value: (function () {
4334
4358
  var _commitAvailabilitySelection = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee37(contextId, params) {
4335
- var normalizedContextId, _params$bookingCount, _ref46, _params$orderProduct$, _params$orderProduct, _params$orderProduct2, _params$orderProduct3, _params$orderProduct$2, _params$orderProduct4, _params$orderProduct5, _editingLine$product_, _baseProjection$meta$, _refreshedProjection$, _baseProjection$meta$2, _this$otherParams$pla, _this$otherParams17, _ref47, _params$orderProduct$3, _params$orderProduct6, _existingBooking$meta, _ref48, _ref49, _params$orderProduct$4, _params$orderProduct7, _params$orderProduct8, _existingBooking$meta2, _existingBooking$hold, bookingCount, orderProductQuantity, partySize, _yield$this$ensureAva3, context, projectionEntry, refreshed, boundEditingUids, orderProductId, editingLine, _editingLine$product_2, baseProjection, commitWriteGuard, prepareParams, fallbackResources, commitSnapshot, refreshedProjection, _baseProjection$meta$3, latestContext, refreshedRanges, refreshedCandidateBase, product, validation, allowPosAvailabilityOverride, forced, capacityConflict, revalidationEntry, revalidatedContext, refreshedCandidate, existingBooking, existingBookingUid, booking, transformed, productLineUid, bookingUid, productLineUids, bookingUids, _transformed$product_, _transformed$product_2, _transformed$product_3, _ref50, _transformed$product_4, _this$getTempOrder4, _this$getTempOrder5, _this$getTempOrder6, beforeProductLineUids, beforeBookingUids, products, addedLines, addedBookings, nextContext, result;
4359
+ var normalizedContextId, _params$bookingCount, _ref46, _params$orderProduct$, _params$orderProduct, _params$orderProduct2, _params$orderProduct3, _params$orderProduct$2, _params$orderProduct4, _params$orderProduct5, _editingLine$product_, _baseProjection$meta$, _refreshedProjection$, _baseProjection$meta$2, _this$otherParams$pla, _this$otherParams17, _ref47, _params$orderProduct$3, _params$orderProduct6, _existingBooking$meta, _ref48, _ref49, _params$orderProduct$4, _params$orderProduct7, _params$orderProduct8, _existingBooking$meta2, _existingBooking$hold, bookingCount, orderProductQuantity, partySize, _yield$this$ensureAva3, context, projectionEntry, refreshed, boundEditingUids, orderProductId, editingLine, _editingLine$product_2, baseProjection, commitWriteGuard, prepareParams, fallbackResources, commitSnapshot, refreshedProjection, _baseProjection$meta$3, latestContext, candidateDurationMinutes, candidateStartTime, refreshedRanges, refreshedCandidateBase, product, validation, allowPosAvailabilityOverride, forced, capacityConflict, revalidationEntry, revalidatedContext, refreshedCandidate, existingBooking, existingBookingUid, booking, transformed, productLineUid, bookingUid, productLineUids, bookingUids, _transformed$product_, _transformed$product_2, _transformed$product_3, _ref50, _transformed$product_4, _this$getTempOrder4, _this$getTempOrder5, _this$getTempOrder6, beforeProductLineUids, beforeBookingUids, products, addedLines, addedBookings, nextContext, result;
4336
4360
  return _regeneratorRuntime().wrap(function _callee37$(_context37) {
4337
4361
  while (1) switch (_context37.prev = _context37.next) {
4338
4362
  case 0:
@@ -4560,20 +4584,26 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
4560
4584
  });
4561
4585
  case 67:
4562
4586
  this.assertAvailabilityCommitWriteCAS(commitWriteGuard);
4563
- refreshedRanges = getProjectionProductTimeRanges(refreshedProjection, {
4587
+ candidateDurationMinutes = getCandidateDurationMinutes(params.candidate);
4588
+ candidateStartTime = getCandidateStartTime(params.candidate);
4589
+ refreshedRanges = getProjectionProductTimeRanges(refreshedProjection, _objectSpread({
4564
4590
  productIds: [params.candidate.productId],
4565
4591
  dateRange: {
4566
4592
  startDate: params.candidate.startAt.slice(0, 10),
4567
4593
  endDate: params.candidate.startAt.slice(0, 10)
4568
4594
  }
4569
- }).flatMap(function (group) {
4595
+ }, candidateDurationMinutes ? _objectSpread({
4596
+ durationMinutesByProductId: _defineProperty({}, String(params.candidate.productId), candidateDurationMinutes)
4597
+ }, candidateStartTime ? {
4598
+ durationStartTimesByProductId: _defineProperty({}, String(params.candidate.productId), [candidateStartTime])
4599
+ } : {}) : {})).flatMap(function (group) {
4570
4600
  return group.ranges;
4571
4601
  });
4572
4602
  refreshedCandidateBase = refreshedRanges.find(function (candidate) {
4573
4603
  return candidate.startAt === params.candidate.startAt && candidate.endAt === params.candidate.endAt && candidate.bookingStartAt === params.candidate.bookingStartAt && candidate.bookingEndAt === params.candidate.bookingEndAt;
4574
4604
  });
4575
4605
  if (refreshedCandidateBase) {
4576
- _context37.next = 72;
4606
+ _context37.next = 74;
4577
4607
  break;
4578
4608
  }
4579
4609
  throw new AvailabilityError('REVALIDATION_FAILED', '缓存重校验后候选时间已不在商品配置中', {
@@ -4581,18 +4611,18 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
4581
4611
  candidate: params.candidate,
4582
4612
  refreshedSnapshotId: refreshedProjection.meta.snapshotId
4583
4613
  });
4584
- case 72:
4614
+ case 74:
4585
4615
  product = refreshedProjection.products.find(function (item) {
4586
4616
  return sameAvailabilityId(item.id, refreshedCandidateBase.productId);
4587
4617
  });
4588
4618
  if (product) {
4589
- _context37.next = 75;
4619
+ _context37.next = 77;
4590
4620
  break;
4591
4621
  }
4592
4622
  throw new AvailabilityError('REVALIDATION_FAILED', '缓存重校验后商品不在 projection 中', {
4593
4623
  productId: refreshedCandidateBase.productId
4594
4624
  });
4595
- case 75:
4625
+ case 77:
4596
4626
  validation = validateAvailabilitySelection(refreshedProjection, {
4597
4627
  candidate: refreshedCandidateBase,
4598
4628
  requirementSelections: params.requirementSelections,
@@ -4621,7 +4651,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
4621
4651
  });
4622
4652
  }
4623
4653
  if (validation.ok) {
4624
- _context37.next = 81;
4654
+ _context37.next = 83;
4625
4655
  break;
4626
4656
  }
4627
4657
  capacityConflict = validation.conflicts.find(function (conflict) {
@@ -4631,7 +4661,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
4631
4661
  validation: validation,
4632
4662
  refreshedSnapshotId: refreshedProjection.meta.snapshotId
4633
4663
  });
4634
- case 81:
4664
+ case 83:
4635
4665
  // Revalidation failure must leave the caller's candidate reusable. Only publish the
4636
4666
  // refreshed projection/version after candidate and resource validation has passed;
4637
4667
  // otherwise a second Confirm from the still-open modal would incorrectly become stale.
@@ -4644,7 +4674,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
4644
4674
  incrementVersion: true
4645
4675
  });
4646
4676
  revalidatedContext = this.getAvailabilityContextEntry(normalizedContextId);
4647
- _context37.next = 85;
4677
+ _context37.next = 87;
4648
4678
  return this.emitAvailabilityDiagnostic({
4649
4679
  action: 'refresh',
4650
4680
  contextId: normalizedContextId,
@@ -4655,7 +4685,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
4655
4685
  previousOrderRevision: baseProjection.meta.orderRevision,
4656
4686
  reason: 'commit_cached_occupancy_revalidation'
4657
4687
  });
4658
- case 85:
4688
+ case 87:
4659
4689
  commitWriteGuard = {
4660
4690
  contextId: normalizedContextId,
4661
4691
  expectedVersion: revalidatedContext.activeVersion,
@@ -4667,13 +4697,13 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
4667
4697
  existingBooking = editingLine ? this.findLinkedBooking(editingLine) : undefined;
4668
4698
  existingBookingUid = existingBooking ? getBookingUid(existingBooking) : '';
4669
4699
  if (!(params.mode === 'edit' && !existingBookingUid)) {
4670
- _context37.next = 91;
4700
+ _context37.next = 93;
4671
4701
  break;
4672
4702
  }
4673
4703
  throw new AvailabilityError('PRODUCT_LINE_NOT_FOUND', '编辑商品行缺少关联 booking', {
4674
4704
  productLineUid: params.productLineUid
4675
4705
  });
4676
- case 91:
4706
+ case 93:
4677
4707
  this.assertAvailabilityCommitWriteCAS(commitWriteGuard);
4678
4708
  booking = buildBookingFromAvailabilitySelection({
4679
4709
  assignments: validation.assignments,
@@ -4689,13 +4719,13 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
4689
4719
  quantity: bookingCount
4690
4720
  }), 'unified_booking_sales', product);
4691
4721
  if (transformed) {
4692
- _context37.next = 96;
4722
+ _context37.next = 98;
4693
4723
  break;
4694
4724
  }
4695
4725
  throw new AvailabilityError('INVALID_TARGET_FILTER', 'orderProduct 无法转换为订单行', {
4696
4726
  orderProduct: params.orderProduct
4697
4727
  });
4698
- case 96:
4728
+ case 98:
4699
4729
  transformed.num = bookingCount;
4700
4730
  transformed.metadata = _objectSpread(_objectSpread({}, transformed.metadata || {}), {}, {
4701
4731
  unified_booking_sales: true,
@@ -4708,7 +4738,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
4708
4738
  productLineUids = [];
4709
4739
  bookingUids = [];
4710
4740
  if (!(params.mode === 'edit' && editingLine && params.productLineUid)) {
4711
- _context37.next = 115;
4741
+ _context37.next = 117;
4712
4742
  break;
4713
4743
  }
4714
4744
  transformed.product_sku = (_transformed$product_ = transformed.product_sku) !== null && _transformed$product_ !== void 0 ? _transformed$product_ : editingLine.product_sku;
@@ -4718,7 +4748,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
4718
4748
  unique_identification_number: params.productLineUid,
4719
4749
  booking_uid: existingBookingUid
4720
4750
  });
4721
- _context37.next = 109;
4751
+ _context37.next = 111;
4722
4752
  return this.updateOrderProduct(_objectSpread(_objectSpread({
4723
4753
  product_id: (_transformed$product_3 = transformed.product_id) !== null && _transformed$product_3 !== void 0 ? _transformed$product_3 : editingLine.product_id,
4724
4754
  product_variant_id: (_ref50 = (_transformed$product_4 = transformed.product_variant_id) !== null && _transformed$product_4 !== void 0 ? _transformed$product_4 : editingLine.product_variant_id) !== null && _ref50 !== void 0 ? _ref50 : 0,
@@ -4730,23 +4760,23 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
4730
4760
  } : {}), params.allowBookingDiscountReapply !== undefined ? {
4731
4761
  allow_booking_discount_reapply: params.allowBookingDiscountReapply
4732
4762
  } : {}));
4733
- case 109:
4763
+ case 111:
4734
4764
  productLineUid = params.productLineUid;
4735
4765
  bookingUid = existingBookingUid;
4736
4766
  productLineUids = [productLineUid];
4737
4767
  bookingUids = [bookingUid];
4738
- _context37.next = 127;
4768
+ _context37.next = 129;
4739
4769
  break;
4740
- case 115:
4770
+ case 117:
4741
4771
  beforeProductLineUids = new Set((((_this$getTempOrder4 = this.getTempOrder()) === null || _this$getTempOrder4 === void 0 ? void 0 : _this$getTempOrder4.products) || []).map(function (line) {
4742
4772
  return getProductLineUid(line);
4743
4773
  }).filter(Boolean));
4744
4774
  beforeBookingUids = new Set((((_this$getTempOrder5 = this.getTempOrder()) === null || _this$getTempOrder5 === void 0 ? void 0 : _this$getTempOrder5.bookings) || []).map(function (item) {
4745
4775
  return getBookingUid(item);
4746
4776
  }).filter(Boolean));
4747
- _context37.next = 119;
4777
+ _context37.next = 121;
4748
4778
  return this.addProductToOrder(transformed, booking);
4749
- case 119:
4779
+ case 121:
4750
4780
  products = _context37.sent;
4751
4781
  addedLines = products.filter(function (line) {
4752
4782
  var _line$product_id, _line$metadata;
@@ -4770,7 +4800,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
4770
4800
  }
4771
4801
  productLineUid = productLineUids[productLineUids.length - 1] || '';
4772
4802
  bookingUid = bookingUids[bookingUids.length - 1] || '';
4773
- case 127:
4803
+ case 129:
4774
4804
  this.invalidateAvailabilityContextsAfterCommit();
4775
4805
  nextContext = this.getAvailabilityContextEntry(normalizedContextId);
4776
4806
  result = {
@@ -4784,21 +4814,21 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
4784
4814
  productLineUids: productLineUids,
4785
4815
  bookingUids: bookingUids
4786
4816
  };
4787
- _context37.next = 132;
4817
+ _context37.next = 134;
4788
4818
  return this.core.effects.emit("".concat(this.name, ":").concat(UnifiedBookingSalesHooks.onAvailabilitySelectionCommitted), result);
4789
- case 132:
4819
+ case 134:
4790
4820
  return _context37.abrupt("return", result);
4791
- case 133:
4792
- _context37.prev = 133;
4793
- _context37.next = 136;
4821
+ case 135:
4822
+ _context37.prev = 135;
4823
+ _context37.next = 138;
4794
4824
  return this.releaseAvailabilityCommitLock(normalizedContextId);
4795
- case 136:
4796
- return _context37.finish(133);
4797
- case 137:
4825
+ case 138:
4826
+ return _context37.finish(135);
4827
+ case 139:
4798
4828
  case "end":
4799
4829
  return _context37.stop();
4800
4830
  }
4801
- }, _callee37, this, [[5,, 133, 137]]);
4831
+ }, _callee37, this, [[5,, 135, 139]]);
4802
4832
  }));
4803
4833
  function commitAvailabilitySelection(_x32, _x33) {
4804
4834
  return _commitAvailabilitySelection.apply(this, arguments);
@@ -1 +1,46 @@
1
- "use strict";
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "BUY_X_GET_Y_FREE_STRATEGY", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _examples.BUY_X_GET_Y_FREE_STRATEGY;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "ITEM_REWARD_STRATEGY", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _examples.ITEM_REWARD_STRATEGY;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "PromotionAdapter", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _adapter.PromotionAdapter;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "PromotionEvaluator", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _evaluator.PromotionEvaluator;
28
+ }
29
+ });
30
+ Object.defineProperty(exports, "X_ITEMS_FOR_Y_PRICE_STRATEGY", {
31
+ enumerable: true,
32
+ get: function () {
33
+ return _examples.X_ITEMS_FOR_Y_PRICE_STRATEGY;
34
+ }
35
+ });
36
+ Object.defineProperty(exports, "default", {
37
+ enumerable: true,
38
+ get: function () {
39
+ return _adapter.default;
40
+ }
41
+ });
42
+ var _evaluator = require("./evaluator");
43
+ var _adapter = _interopRequireWildcard(require("./adapter"));
44
+ var _examples = require("./examples");
45
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
46
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -191,6 +191,8 @@ export interface OrderLocalizedText {
191
191
  export interface OrderProduct extends OrderProductIdentity {
192
192
  order_detail_id: number | null;
193
193
  num: number;
194
+ /** Product 或当前 Variant 的生产编码 */
195
+ production_code?: string;
194
196
  bundle_edit?: number;
195
197
  product_sku: OrderProductSku;
196
198
  gift_card?: number;
@@ -909,6 +909,7 @@ function formatSubmitBundleItems(bundle) {
909
909
  return {
910
910
  is_charge_tax: rawBundle.is_charge_tax ?? 0,
911
911
  bundle_variant_id: rawBundle.bundle_variant_id ?? 0,
912
+ production_code: rawBundle.production_code,
912
913
  num,
913
914
  quantity: toBundleNumber(rawBundle.quantity ?? rawBundle.num, num),
914
915
  extension_id: rawBundle.extension_id ?? 0,
@@ -77,6 +77,8 @@ export interface ProductData {
77
77
  is_gst: number;
78
78
  /** 商品编码 */
79
79
  code: string;
80
+ /** ERP/生产侧商品编码;有规格时以选中 Variant 的值为准 */
81
+ production_code?: string;
80
82
  /** 商品条码 */
81
83
  barcode: string;
82
84
  /** 是否支持配送 */
@@ -48,6 +48,19 @@ function normalizeBookingCount(bookingCount) {
48
48
  }
49
49
  return normalized;
50
50
  }
51
+ function resolveRequestedDurationMinutes(product, request) {
52
+ const configured = Math.max(1, Number(product.durationMinutes || 30) || 30);
53
+ if (product.kind !== 'duration') return configured;
54
+ const override = request.durationMinutesByProductId?.[String(product.id)];
55
+ const normalized = Number(override);
56
+ return Number.isInteger(normalized) && normalized > 0 ? normalized : configured;
57
+ }
58
+ function resolveRequestedDurationStartTimes(product, request) {
59
+ if (product.kind !== 'duration') return [];
60
+ const values = request.durationStartTimesByProductId?.[String(product.id)];
61
+ if (!Array.isArray(values)) return [];
62
+ return Array.from(new Set(values.filter(value => typeof value === 'string' && /^([01]\d|2[0-3]):[0-5]\d$/.test(value))));
63
+ }
51
64
  function toDateTime(value, _timezoneName) {
52
65
  try {
53
66
  return (0, _localClock.localDateTimeToScalar)((0, _localClock.parseLocalDateTime)(value));
@@ -865,9 +878,27 @@ function dedupeProductRanges(ranges) {
865
878
  });
866
879
  return Array.from(map.values()).sort((left, right) => left.startAt.localeCompare(right.startAt));
867
880
  }
881
+ function createDurationTimeRange(product, start, durationMinutes, projection, fixedOffsetMinutes) {
882
+ const bookingEnd = addMinutesZoned(start, durationMinutes, projection.meta.timezone);
883
+ return {
884
+ key: `${String(product.id)}:${start}:${bookingEnd}`,
885
+ productId: product.id,
886
+ source: 'duration_window',
887
+ startAt: formatDateTime(start, projection.meta.timezone, fixedOffsetMinutes),
888
+ endAt: formatDateTime(bookingEnd, projection.meta.timezone, fixedOffsetMinutes),
889
+ bookingStartAt: formatDateTime(start, projection.meta.timezone, fixedOffsetMinutes),
890
+ bookingEndAt: formatDateTime(bookingEnd, projection.meta.timezone, fixedOffsetMinutes),
891
+ date: formatDate(start, projection.meta.timezone),
892
+ startTime: formatTime(start, projection.meta.timezone),
893
+ endTime: formatTime(bookingEnd, projection.meta.timezone),
894
+ timezone: projection.meta.timezone,
895
+ scheduleRefs: []
896
+ };
897
+ }
868
898
  function getProductTimeRanges(projection, request = {}) {
869
899
  const normalizedPartySize = normalizePartySize(request.partySize);
870
900
  const dateRange = resolveProjectionDateRange(projection, request.dateRange);
901
+ const slotStepMinutes = projection.meta.defaults.slotStepMinutes;
871
902
  const fixedOffsetMinutes = (0, _localClock.extractFixedOffsetMinutes)(projection.meta.now) ?? (0, _localClock.captureRuntimeOffsetMinutes)();
872
903
  const resourceWindowIndex = buildResourceWindowIndex(projection);
873
904
  const filteredProductIdSet = request.productIds?.length ? new Set(request.productIds.map(String)) : null;
@@ -877,6 +908,7 @@ function getProductTimeRanges(projection, request = {}) {
877
908
  productId: product.id,
878
909
  title: product.title,
879
910
  kind: product.kind,
911
+ slotStepMinutes,
880
912
  ranges: []
881
913
  };
882
914
  }
@@ -885,6 +917,7 @@ function getProductTimeRanges(projection, request = {}) {
885
917
  productId: product.id,
886
918
  title: product.title,
887
919
  kind: product.kind,
920
+ slotStepMinutes,
888
921
  ranges: getSessionRangesForProduct(projection, product, dateRange)
889
922
  };
890
923
  }
@@ -900,9 +933,9 @@ function getProductTimeRanges(projection, request = {}) {
900
933
  resourceWindowIndex
901
934
  })).reduce((current, ranges) => current === null ? ranges : intersectRangeLists(current, ranges), null) || [] : null;
902
935
  const baseRanges = resourceRanges === null ? operatingRanges : intersectRangeLists(resourceRanges, operatingRanges);
903
- const durationMinutes = Math.max(1, Number(product.durationMinutes || 30) || 30);
904
- const timeSliceMinutes = projection.meta.defaults.slotStepMinutes;
936
+ const durationMinutes = resolveRequestedDurationMinutes(product, request);
905
937
  const durationAnchor = ceilToTenMinutes(toDateTime(projection.meta.durationCandidateAnchorAt, projection.meta.timezone), projection.meta.timezone);
938
+ const requestedStartTimes = resolveRequestedDurationStartTimes(product, request);
906
939
  const ranges = [];
907
940
  baseRanges.forEach(range => {
908
941
  if (range.end <= durationAnchor) return;
@@ -915,28 +948,26 @@ function getProductTimeRanges(projection, request = {}) {
915
948
  if (bookingEnd > range.end) break;
916
949
  const bookingDate = formatDate(cursor);
917
950
  if (bookingDate >= dateRange.startDate && bookingDate <= dateRange.endDate) {
918
- ranges.push({
919
- key: `${String(product.id)}:${cursor}:${bookingEnd}`,
920
- productId: product.id,
921
- source: 'duration_window',
922
- startAt: formatDateTime(cursor, projection.meta.timezone, fixedOffsetMinutes),
923
- endAt: formatDateTime(bookingEnd, projection.meta.timezone, fixedOffsetMinutes),
924
- bookingStartAt: formatDateTime(cursor, projection.meta.timezone, fixedOffsetMinutes),
925
- bookingEndAt: formatDateTime(bookingEnd, projection.meta.timezone, fixedOffsetMinutes),
926
- date: formatDate(cursor, projection.meta.timezone),
927
- startTime: formatTime(cursor, projection.meta.timezone),
928
- endTime: formatTime(bookingEnd, projection.meta.timezone),
929
- timezone: projection.meta.timezone,
930
- scheduleRefs: []
931
- });
951
+ ranges.push(createDurationTimeRange(product, cursor, durationMinutes, projection, fixedOffsetMinutes));
932
952
  }
933
- cursor = addMinutesZoned(cursor, timeSliceMinutes, projection.meta.timezone);
953
+ cursor = addMinutesZoned(cursor, slotStepMinutes, projection.meta.timezone);
934
954
  }
935
955
  });
956
+ if (dateRange.startDate === dateRange.endDate && requestedStartTimes.length > 0) {
957
+ requestedStartTimes.forEach(startTime => {
958
+ const start = toDateTimeInDate(dateRange.startDate, startTime, projection.meta.timezone);
959
+ if (!Number.isFinite(start)) return;
960
+ const end = addMinutesZoned(start, durationMinutes, projection.meta.timezone);
961
+ const startsInOperatingRange = operatingRanges.some(range => range.start <= start && start < range.end);
962
+ if (!startsInOperatingRange) return;
963
+ ranges.push(createDurationTimeRange(product, start, durationMinutes, projection, fixedOffsetMinutes));
964
+ });
965
+ }
936
966
  return {
937
967
  productId: product.id,
938
968
  title: product.title,
939
969
  kind: product.kind,
970
+ slotStepMinutes,
940
971
  ranges: dedupeProductRanges(ranges)
941
972
  };
942
973
  });
@@ -211,6 +211,7 @@ export interface ProductTimeRangeGroup {
211
211
  productId: AvailabilityId;
212
212
  title?: string;
213
213
  kind: AvailabilityProductKind;
214
+ slotStepMinutes?: number;
214
215
  ranges: ProductTimeRange[];
215
216
  }
216
217
  export interface AvailabilityAssignment extends AvailabilityAbsoluteRange {
@@ -231,6 +232,8 @@ export interface GetProductTimeRangesRequest {
231
232
  dateRange?: Partial<AvailabilityDateRange>;
232
233
  resourceIds?: AvailabilityId[];
233
234
  partySize?: number;
235
+ durationMinutesByProductId?: Record<string, number>;
236
+ durationStartTimesByProductId?: Record<string, string[]>;
234
237
  }
235
238
  export interface QueryAvailabilityBaseRequest {
236
239
  productIds?: AvailabilityId[];
@@ -1961,7 +1961,7 @@ class RulesModule extends _BaseModule.BaseModule {
1961
1961
  // 套餐适用范围配置
1962
1962
  const packageScope = usageRules?.package_scope;
1963
1963
  const {
1964
- type: scopeType,
1964
+ type: scopeType = 'product_all',
1965
1965
  exclude_bundle_product_ids = [],
1966
1966
  include_bundle_product_ids = [],
1967
1967
  filter = 0
@@ -1969,6 +1969,8 @@ class RulesModule extends _BaseModule.BaseModule {
1969
1969
  const isMainProduct = flatItem.type === 'main'; // 单独购买
1970
1970
  const isBundleItem = flatItem.type === 'bundle'; // 套餐中购买
1971
1971
  const bundleMainProductId = flatItem.product?.product_id;
1972
+ // 主商品id
1973
+ const mainProductId = flatItem?.originProduct?._productOrigin?.id || flatItem?.parentProduct?.id || 0;
1972
1974
 
1973
1975
  // 主商品直接可用
1974
1976
  if (isMainProduct) {
@@ -1985,7 +1987,7 @@ class RulesModule extends _BaseModule.BaseModule {
1985
1987
  const priceType = flatItem.bundleItem?.price_type;
1986
1988
  const priceTypeExt = flatItem.bundleItem?.price_type_ext;
1987
1989
  // 主商品id
1988
- const mainProductId = flatItem?.originProduct?._productOrigin?.id || flatItem?.parentProduct?.id || 0;
1990
+ // const mainProductId = flatItem?.originProduct?._productOrigin?.id || flatItem?.parentProduct?.id || 0;
1989
1991
  // original_price 对应:
1990
1992
  // 1. price_type: "markup" && price_type_ext: "product_price"
1991
1993
  // markup_price 对应:
@@ -2010,13 +2012,13 @@ class RulesModule extends _BaseModule.BaseModule {
2010
2012
  if (!filter) {
2011
2013
  isScopeValid = true;
2012
2014
  } else {
2013
- isScopeValid = !exclude_bundle_product_ids.includes(Number(bundleMainProductId));
2015
+ isScopeValid = !exclude_bundle_product_ids.includes(Number(mainProductId));
2014
2016
  }
2015
2017
  }
2016
2018
 
2017
2019
  // 包含套餐判断, products值兼容旧数据
2018
2020
  if (scopeType === 'specific_packages' || scopeType === 'products') {
2019
- isScopeValid = include_bundle_product_ids.includes(Number(bundleMainProductId));
2021
+ isScopeValid = include_bundle_product_ids.includes(Number(mainProductId));
2020
2022
  }
2021
2023
 
2022
2024
  // 价格和套餐适用范围都符合,则可用
@@ -2078,13 +2080,13 @@ class RulesModule extends _BaseModule.BaseModule {
2078
2080
  if (!filter) {
2079
2081
  isScopeValid = true;
2080
2082
  } else {
2081
- isScopeValid = !exclude_bundle_product_ids.includes(Number(bundleMainProductId));
2083
+ isScopeValid = !exclude_bundle_product_ids.includes(Number(mainProductId));
2082
2084
  }
2083
2085
  }
2084
2086
 
2085
2087
  // 包含套餐判断, products值兼容旧数据
2086
2088
  if (scopeType === 'specific_packages' || scopeType === 'products') {
2087
- isScopeValid = include_bundle_product_ids.includes(Number(bundleMainProductId));
2089
+ isScopeValid = include_bundle_product_ids.includes(Number(mainProductId));
2088
2090
  }
2089
2091
 
2090
2092
  // 价格和套餐适用范围都符合,则可用
@@ -112,6 +112,8 @@ export interface BaseSalesUpdateOrderProductQuantityParams extends BaseSalesOrde
112
112
  export interface BaseSalesOrderProduct extends BaseSalesOrderProductIdentity {
113
113
  order_detail_id: number | null;
114
114
  num: number;
115
+ /** Product 或当前 Variant 的生产编码 */
116
+ production_code?: string;
115
117
  product_sku: BaseSalesProductSku;
116
118
  /**
117
119
  * 券后 **行 composite 单价** = `metadata.main_product_selling_price`
@@ -3,6 +3,7 @@ import type { ProductData } from '../../../modules/Product/types';
3
3
  export interface BaseProductDetailOptionItem {
4
4
  option_group_item_id?: number | string;
5
5
  option_group_id?: number | string;
6
+ production_code?: string;
6
7
  num?: number | string;
7
8
  quantity?: number | string;
8
9
  price?: number | string;
@@ -10,6 +11,7 @@ export interface BaseProductDetailOptionItem {
10
11
  [key: string]: any;
11
12
  }
12
13
  export interface BaseProductDetailBundleItem {
14
+ production_code?: string;
13
15
  option?: BaseProductDetailOptionItem[];
14
16
  [key: string]: any;
15
17
  }
@@ -18,6 +20,7 @@ export interface BaseProductDetailPayload {
18
20
  product_id?: number | string | null;
19
21
  variant_id?: number | string | null;
20
22
  product_variant_id?: number | string | null;
23
+ production_code?: string;
21
24
  quantity?: number | string;
22
25
  num?: number | string;
23
26
  option?: BaseProductDetailOptionItem[];
@@ -27,6 +27,10 @@ function toPriceString(value, fallback = '0.00') {
27
27
  if (!Number.isFinite(parsedValue)) return fallback;
28
28
  return parsedValue.toFixed(2);
29
29
  }
30
+ function normalizeProductionCode(value) {
31
+ if (value === undefined || value === null) return '';
32
+ return String(value).trim();
33
+ }
30
34
  function isBlankValue(value) {
31
35
  return value === undefined || value === null || typeof value === 'string' && value.trim() === '';
32
36
  }
@@ -108,6 +112,7 @@ function transformBaseProductToOrderProduct(params) {
108
112
  ...(callbackOrigin || {})
109
113
  };
110
114
  const matchedVariant = findVariantById(callbackOrigin, productVariantId) ?? findVariantById(sourceProduct, productVariantId) ?? findVariantById(origin, productVariantId);
115
+ const productionCode = normalizeProductionCode(Object.prototype.hasOwnProperty.call(payload, 'production_code') ? payload.production_code : productVariantId > 0 ? matchedVariant?.production_code : origin?.production_code ?? sourceProduct?.production_code);
111
116
  const hasPriceOverride = payload.price_override !== undefined && payload.price_override !== null && payload.price_override !== '';
112
117
  // 手动改价后 payload.price 是分摊后的主商品售价,不能再作为券前 source。
113
118
  // 此时优先从商品/variant 快照读取目录价;售价仍由 line_total - bundle 推导。
@@ -193,6 +198,7 @@ function transformBaseProductToOrderProduct(params) {
193
198
  return {
194
199
  product_id: productId,
195
200
  product_variant_id: productVariantId,
201
+ production_code: productionCode,
196
202
  unique_identification_number: uniqueIdentificationNumber ? String(uniqueIdentificationNumber) : undefined,
197
203
  num: resolvedQuantity,
198
204
  product_sku: {
@@ -257,6 +257,9 @@ function normalizeOrderProduct(product) {
257
257
  product_id: product.product_id,
258
258
  num: getSafeProductNum(product.num),
259
259
  product_variant_id: product.product_variant_id,
260
+ ...(product.production_code !== undefined && product.production_code !== null ? {
261
+ production_code: String(product.production_code).trim()
262
+ } : {}),
260
263
  product_sku: productSku,
261
264
  selling_price: composedSellingPrice,
262
265
  original_price: finalOriginalPrice,
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
326
326
  date: string;
327
327
  status: string;
328
328
  week: string;
329
- weekNum: 0 | 1 | 2 | 5 | 3 | 4 | 6;
329
+ weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
@@ -345,7 +345,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
345
345
  count: number;
346
346
  left: number;
347
347
  summaryCount: number;
348
- status: "sold_out" | "lots_of_space" | "filling_up_fast";
348
+ status: "lots_of_space" | "filling_up_fast" | "sold_out";
349
349
  }[];
350
350
  /**
351
351
  * 找到多个资源的公共可用时间段
@@ -336,6 +336,8 @@ function buildBasePayloadFromCacheItem(cacheItem, ctx) {
336
336
  id: cacheItem?.id ?? cacheItem?.product_id,
337
337
  product_id: resolvedPid,
338
338
  variant_id: other?.product_variant_id ?? other?.variant_id ?? 0,
339
+ // SKUOptionsSelection 已按 Product / Variant 解析好主商品编码;显式空串也需保留。
340
+ production_code: other?.production_code ?? cacheItem?.production_code,
339
341
  quantity,
340
342
  // 规格弹窗本次选择是 option 权威源,避免目录/旧订单里的空 option 覆盖它。
341
343
  product_sku: productSku ? {
@@ -44,6 +44,8 @@ export interface ScanOrderProductSku {
44
44
  export interface ScanOrderOrderProduct extends ScanOrderOrderProductIdentity {
45
45
  order_detail_id: number | null;
46
46
  num: number;
47
+ /** Product 或当前 Variant 的生产编码 */
48
+ production_code?: string;
47
49
  product_sku: ScanOrderProductSku;
48
50
  /**
49
51
  * 券后 **行 composite 单价** = `metadata.main_product_selling_price`
@@ -633,6 +633,9 @@ function normalizeOrderProduct(product) {
633
633
  product_id: product.product_id,
634
634
  num: getSafeProductNum(product.num),
635
635
  product_variant_id: product.product_variant_id,
636
+ ...(product.production_code !== undefined && product.production_code !== null ? {
637
+ production_code: String(product.production_code).trim()
638
+ } : {}),
636
639
  product_sku: productSku,
637
640
  selling_price: composedSellingPrice,
638
641
  original_price: manualOriginalPrice,
@@ -58,6 +58,30 @@ function normalizePositiveInteger(value) {
58
58
  if (!Number.isInteger(normalized) || normalized <= 0) return undefined;
59
59
  return normalized;
60
60
  }
61
+ function getCandidateDurationMinutes(candidate) {
62
+ const startAt = candidate.bookingStartAt || candidate.startAt;
63
+ const endAt = candidate.bookingEndAt || candidate.endAt;
64
+ try {
65
+ const start = (0, _localClock.localDateTimeToScalar)((0, _localClock.parseLocalDateTime)(startAt));
66
+ const end = (0, _localClock.localDateTimeToScalar)((0, _localClock.parseLocalDateTime)(endAt));
67
+ const minutes = Math.round((end - start) / 60000);
68
+ return Number.isInteger(minutes) && minutes > 0 ? minutes : undefined;
69
+ } catch (_error) {
70
+ return undefined;
71
+ }
72
+ }
73
+ function getCandidateStartTime(candidate) {
74
+ if (/^([01]\d|2[0-3]):[0-5]\d$/.test(candidate.startTime || '')) {
75
+ return candidate.startTime;
76
+ }
77
+ const startAt = candidate.bookingStartAt || candidate.startAt;
78
+ try {
79
+ const start = (0, _localClock.parseLocalDateTime)(startAt);
80
+ return `${String(start.hour).padStart(2, '0')}:${String(start.minute).padStart(2, '0')}`;
81
+ } catch (_error) {
82
+ return undefined;
83
+ }
84
+ }
61
85
  function isRecord(value) {
62
86
  return !!value && typeof value === 'object' && !Array.isArray(value);
63
87
  }
@@ -3027,12 +3051,24 @@ class UnifiedBookingSalesImpl extends _BookingTicket.BookingTicket {
3027
3051
  });
3028
3052
  }
3029
3053
  this.assertAvailabilityCommitWriteCAS(commitWriteGuard);
3054
+ const candidateDurationMinutes = getCandidateDurationMinutes(params.candidate);
3055
+ const candidateStartTime = getCandidateStartTime(params.candidate);
3030
3056
  const refreshedRanges = (0, _ResourcePlanner.getProductTimeRanges)(refreshedProjection, {
3031
3057
  productIds: [params.candidate.productId],
3032
3058
  dateRange: {
3033
3059
  startDate: params.candidate.startAt.slice(0, 10),
3034
3060
  endDate: params.candidate.startAt.slice(0, 10)
3035
- }
3061
+ },
3062
+ ...(candidateDurationMinutes ? {
3063
+ durationMinutesByProductId: {
3064
+ [String(params.candidate.productId)]: candidateDurationMinutes
3065
+ },
3066
+ ...(candidateStartTime ? {
3067
+ durationStartTimesByProductId: {
3068
+ [String(params.candidate.productId)]: [candidateStartTime]
3069
+ }
3070
+ } : {})
3071
+ } : {})
3036
3072
  }).flatMap(group => group.ranges);
3037
3073
  const refreshedCandidateBase = refreshedRanges.find(candidate => candidate.startAt === params.candidate.startAt && candidate.endAt === params.candidate.endAt && candidate.bookingStartAt === params.candidate.bookingStartAt && candidate.bookingEndAt === params.candidate.bookingEndAt);
3038
3074
  if (!refreshedCandidateBase) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.3.87",
4
+ "version": "2.3.89",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",