@pisell/pisellos 2.2.247 → 2.2.249

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.
@@ -1183,6 +1183,55 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1183
1183
  }
1184
1184
  return result;
1185
1185
  }
1186
+ getPaymentMergeKey(payment) {
1187
+ var _a;
1188
+ const record = payment;
1189
+ if (!record)
1190
+ return "";
1191
+ const uniquePaymentNumber = (_a = record.metadata) == null ? void 0 : _a.unique_payment_number;
1192
+ if (!this.isBlankIdentityValue(uniquePaymentNumber)) {
1193
+ return `unique:${String(uniquePaymentNumber)}`;
1194
+ }
1195
+ const orderPaymentId = record.order_payment_id;
1196
+ if (!this.isBlankIdentityValue(orderPaymentId))
1197
+ return `order_payment:${String(orderPaymentId)}`;
1198
+ const code = record.code;
1199
+ const customPaymentId = record.custom_payment_id;
1200
+ if (!this.isBlankIdentityValue(code) && !this.isBlankIdentityValue(customPaymentId)) {
1201
+ return `custom:${String(code)}#${String(customPaymentId)}`;
1202
+ }
1203
+ return "";
1204
+ }
1205
+ mergeOrderPaymentLists(existing, incoming) {
1206
+ const existingList = Array.isArray(existing) ? existing : [];
1207
+ const incomingList = Array.isArray(incoming) ? incoming : [];
1208
+ if (incomingList.length === 0)
1209
+ return (0, import_lodash_es.cloneDeep)(existingList);
1210
+ if (existingList.length === 0)
1211
+ return (0, import_lodash_es.cloneDeep)(incomingList);
1212
+ const existingByKey = /* @__PURE__ */ new Map();
1213
+ for (const payment of existingList) {
1214
+ const key = this.getPaymentMergeKey(payment);
1215
+ if (!key)
1216
+ continue;
1217
+ existingByKey.set(key, payment);
1218
+ }
1219
+ return incomingList.map((payment) => {
1220
+ const incomingPayment = payment;
1221
+ const key = this.getPaymentMergeKey(incomingPayment);
1222
+ const existingPayment = key ? existingByKey.get(key) : void 0;
1223
+ if (!existingPayment)
1224
+ return (0, import_lodash_es.cloneDeep)(incomingPayment);
1225
+ return {
1226
+ ...(0, import_lodash_es.cloneDeep)(existingPayment),
1227
+ ...(0, import_lodash_es.cloneDeep)(incomingPayment),
1228
+ metadata: {
1229
+ ...(0, import_lodash_es.cloneDeep)(existingPayment.metadata || {}),
1230
+ ...(0, import_lodash_es.cloneDeep)(incomingPayment.metadata || {})
1231
+ }
1232
+ };
1233
+ });
1234
+ }
1186
1235
  mergeOrderRecords(existing, incoming, options) {
1187
1236
  const preferred = this.pickPreferredOrder(existing, incoming);
1188
1237
  const secondary = preferred === existing ? incoming : existing;
@@ -1204,7 +1253,6 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1204
1253
  "updated_at",
1205
1254
  "shop_discount",
1206
1255
  "summary",
1207
- "payments",
1208
1256
  "products",
1209
1257
  "bookings"
1210
1258
  ];
@@ -1212,6 +1260,7 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1212
1260
  const preferredRecord = preferred;
1213
1261
  const secondaryRecord = secondary;
1214
1262
  const incomingRecord = incoming;
1263
+ const previousRecord = preferred === incoming ? secondaryRecord : preferredRecord;
1215
1264
  for (const field of fieldsToPreserve) {
1216
1265
  if (!this.isBlankIdentityValue(preferredRecord[field])) {
1217
1266
  mergedRecord[field] = preferredRecord[field];
@@ -1233,6 +1282,16 @@ var OrderModule = class extends import_BaseModule.BaseModule {
1233
1282
  mergedRecord[field] = (0, import_lodash_es.cloneDeep)(incomingRecord[field]);
1234
1283
  }
1235
1284
  mergedRecord.products = shouldUseIncomingProductsSnapshot ? (0, import_lodash_es.cloneDeep)(incomingRecord.products) : this.mergeOrderProductLists(preferredRecord.products, secondaryRecord.products);
1285
+ if (Object.prototype.hasOwnProperty.call(incomingRecord, "payments")) {
1286
+ if (Array.isArray(incomingRecord.payments)) {
1287
+ mergedRecord.payments = this.mergeOrderPaymentLists(
1288
+ previousRecord.payments,
1289
+ incomingRecord.payments
1290
+ );
1291
+ } else if (incomingRecord.payments !== void 0 && incomingRecord.payments !== null) {
1292
+ mergedRecord.payments = (0, import_lodash_es.cloneDeep)(incomingRecord.payments);
1293
+ }
1294
+ }
1236
1295
  if (!this.isPendingSyncOrder(preferred) || !this.isPendingSyncOrder(secondary)) {
1237
1296
  merged.need_sync = 0;
1238
1297
  }
@@ -59,7 +59,9 @@ var LABELS = {
59
59
  orderDiscount: "Order discount",
60
60
  manualDiscount: "Manual discount",
61
61
  payProcessingFee: "Pay processing fee",
62
- rounding: "Rounding"
62
+ rounding: "Rounding",
63
+ gross: "Gross",
64
+ tare: "Tare"
63
65
  },
64
66
  zh_CN: {
65
67
  contactName: "联系人姓名",
@@ -83,7 +85,9 @@ var LABELS = {
83
85
  orderDiscount: "整单折扣",
84
86
  manualDiscount: "手动折扣",
85
87
  payProcessingFee: "支付手续费",
86
- rounding: "抹零"
88
+ rounding: "抹零",
89
+ gross: "重量",
90
+ tare: "去皮"
87
91
  },
88
92
  zh_HK: {
89
93
  contactName: "聯絡人姓名",
@@ -107,7 +111,9 @@ var LABELS = {
107
111
  orderDiscount: "整單折扣",
108
112
  manualDiscount: "手動折扣",
109
113
  payProcessingFee: "支付手續費",
110
- rounding: "抹零"
114
+ rounding: "抹零",
115
+ gross: "重量",
116
+ tare: "去皮"
111
117
  }
112
118
  };
113
119
  function buildSmallTicketData(params) {
@@ -187,14 +193,21 @@ function buildProducts(order, locale, productMap) {
187
193
  parentProduct
188
194
  });
189
195
  const resolvedVariant = resolveProductVariantText({ product, parentProduct, locale });
190
- const discountList = normalizeProductDiscounts({ product, locale, currencySymbol });
196
+ const extensionList = buildProductExtensionList({
197
+ product,
198
+ locale,
199
+ currencySymbol,
200
+ quantity,
201
+ originalPrice
202
+ });
203
+ const discountList = normalizeProductDiscounts({ product, locale, currencySymbol, quantity });
191
204
  return {
192
205
  product_title: productTitle,
193
206
  product_quantity: quantity,
194
207
  selling_price: formatMoney(sellingPrice, currencySymbol),
195
208
  original_price: formatMoney(originalPrice, currencySymbol),
196
209
  total_original_price: formatMoney(new import_decimal.default(toMoneyNumber(originalPrice)).mul(quantity), currencySymbol),
197
- extension_list: Array.isArray(product.extension_list) ? product.extension_list : [],
210
+ extension_list: extensionList,
198
211
  ...discountList.length ? { discount_list: discountList } : {},
199
212
  ...options.length ? { options } : {},
200
213
  ...resolvedVariant ? { variant: resolvedVariant } : {},
@@ -203,11 +216,11 @@ function buildProducts(order, locale, productMap) {
203
216
  });
204
217
  }
205
218
  function normalizeProductDiscounts(params) {
206
- const { product, locale, currencySymbol } = params;
219
+ const { product, locale, currencySymbol, quantity } = params;
207
220
  return normalizeArray(product.discount_list).map((discount) => {
208
- const title = resolveDiscountTitle(discount, locale);
221
+ const title = resolveDiscountTitleWithPercent(discount, locale);
209
222
  const amount = discount.amount ?? discount.value ?? discount.discount_amount;
210
- const formattedAmount = formatNegativeMoney(amount, currencySymbol);
223
+ const formattedAmount = formatNegativeMoney(new import_decimal.default(toMoneyNumber(amount)).mul(quantity), currencySymbol);
211
224
  return {
212
225
  ...discount,
213
226
  item: title,
@@ -217,6 +230,63 @@ function normalizeProductDiscounts(params) {
217
230
  };
218
231
  });
219
232
  }
233
+ function buildProductExtensionList(params) {
234
+ const { product, locale, currencySymbol, quantity, originalPrice } = params;
235
+ const extensionList = [
236
+ ...buildProductOpenWeightRows({ product, locale, currencySymbol }),
237
+ ...quantity > 1 ? [{
238
+ item: buildProductQuantityPriceText({ quantity, currencySymbol, price: originalPrice }),
239
+ value: ""
240
+ }] : []
241
+ ];
242
+ return extensionList.length ? extensionList : normalizeArray(product.extension_list);
243
+ }
244
+ function buildProductOpenWeightRows(params) {
245
+ const { product, locale, currencySymbol } = params;
246
+ const productSku = product.product_sku || {};
247
+ if (productSku.open_sold_weight != 1)
248
+ return [];
249
+ const unit = productSku.unit ?? "";
250
+ const manualFlag = productSku.weight_source === "manual" ? "(M) " : "";
251
+ const hasTare = toNumber(productSku.tare_weight, 0) > 0;
252
+ const rows = [];
253
+ if (hasTare) {
254
+ rows.push({
255
+ item: `${manualFlag}${label(locale, "gross")}: ${productSku.weight ?? 0}${unit}`,
256
+ value: ""
257
+ });
258
+ rows.push({
259
+ item: `${label(locale, "tare")}: ${productSku.tare_weight}${unit}`,
260
+ value: ""
261
+ });
262
+ }
263
+ const netWeight = productSku.net_weight ?? 0;
264
+ const unitPrice = productSku.unit_price ?? 0;
265
+ const netItem = `${netWeight} ${unit} NET @ ${currencySymbol}${unitPrice}/${unit}`;
266
+ rows.push({
267
+ item: hasTare ? netItem : `${manualFlag}${netItem}`,
268
+ value: ""
269
+ });
270
+ return rows;
271
+ }
272
+ function buildProductQuantityPriceText(params) {
273
+ const { quantity, currencySymbol, price } = params;
274
+ return `${quantity} @ ${currencySymbol}${stringify(price)} EACH`;
275
+ }
276
+ function resolveDiscountTitleWithPercent(discount, locale) {
277
+ var _a, _b;
278
+ const title = resolveDiscountTitle(discount, locale);
279
+ const percentRaw = (_a = discount.discount) == null ? void 0 : _a.percent;
280
+ const cardType = ((_b = discount.discount) == null ? void 0 : _b.discount_card_type) ?? "percent";
281
+ const percent = percentRaw !== void 0 && percentRaw !== null ? Math.trunc(Number(percentRaw)) : NaN;
282
+ if (percentRaw === void 0 || percentRaw === null)
283
+ return title;
284
+ if (cardType !== "percent")
285
+ return title;
286
+ if (Number.isNaN(percent))
287
+ return title;
288
+ return `${title} (${percent}%)`;
289
+ }
220
290
  function resolveDiscountTitle(discount, locale) {
221
291
  var _a, _b, _c;
222
292
  const title = getLocalizedValue(
@@ -540,14 +610,14 @@ function buildFees(params) {
540
610
  value: formatMoney(payProcessingFee, currencySymbol)
541
611
  });
542
612
  }
613
+ const productExpectAmount = summary.product_expect_amount || summary.product_amount || order.product_expect_amount;
614
+ const productOriginalAmount = summary.product_original_amount ?? order.product_original_amount ?? productExpectAmount;
615
+ const totalSavingsAmount = new import_decimal.default(toMoneyNumber(productOriginalAmount)).minus(toMoneyNumber(productExpectAmount)).plus(toMoneyNumber(discountAmount));
543
616
  return {
544
617
  fees,
545
618
  countFee: {
546
619
  total_amount: formatMoney(summary.total_amount || order.total_amount, currencySymbol),
547
- product_expect_amount: formatMoney(
548
- summary.product_expect_amount || summary.product_amount || order.product_expect_amount,
549
- currencySymbol
550
- ),
620
+ product_expect_amount: formatMoney(productExpectAmount, currencySymbol),
551
621
  expect_amount: formatMoney(summary.expect_amount || order.expect_amount || summary.total_amount || order.total_amount, currencySymbol),
552
622
  product_quantity: toNumber(
553
623
  summary.product_quantity || products.reduce((sum, product) => sum + product.product_quantity, 0),
@@ -558,7 +628,7 @@ function buildFees(params) {
558
628
  tax_title: stringify(summary.tax_title || order.tax_title || shopInfo.tax_title),
559
629
  total_refund_amount: formatMoney(summary.total_refund_amount || order.total_refund_amount, currencySymbol),
560
630
  ...isNonZero(roundingAmount) ? { rounding_amount: formatMoney(roundingAmount, currencySymbol) } : {},
561
- ...isNonZero(discountAmount) ? { order_total_discount: formatMoney(discountAmount, currencySymbol) } : {},
631
+ ...isNonZero(totalSavingsAmount) ? { order_total_discount: formatMoney(totalSavingsAmount, currencySymbol) } : {},
562
632
  ...isNonZero(payProcessingFee) ? { pay_processing_fee: formatMoney(payProcessingFee, currencySymbol) } : {},
563
633
  ...isNonZero(taxFee) ? { tax_fee: formatMoney(taxFee, currencySymbol) } : {}
564
634
  }
@@ -70,6 +70,11 @@ function preserveManualProductDiscountProducts(previousProducts, nextProducts) {
70
70
  return previous && isBaseSalesManualProductDiscountProduct(previous) ? previous : product;
71
71
  });
72
72
  }
73
+ function isBaseSalesHistoricalDiscountEntry(discount) {
74
+ return Boolean(
75
+ (discount == null ? void 0 : discount.isEditMode) || (discount == null ? void 0 : discount.isDisabled) || (discount == null ? void 0 : discount.order_discount_id) != null
76
+ );
77
+ }
73
78
  function getBaseSalesUniqueArrayMetadataKey(key) {
74
79
  if (key === "products" || key === "bookings")
75
80
  return "unique_identification_number";
@@ -883,7 +888,11 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
883
888
  const historyIds = new Set(historyDiscountList.map((discount) => discount.id));
884
889
  return [
885
890
  ...historyDiscountList,
886
- ...(discountList || []).filter((discount) => !historyIds.has(discount.id))
891
+ ...(discountList || []).filter((discount) => {
892
+ if (!historyIds.has(discount.id))
893
+ return true;
894
+ return !isBaseSalesHistoricalDiscountEntry(discount);
895
+ })
887
896
  ];
888
897
  }
889
898
  shouldSkipAutoApplyFetchedDiscountsInEditMode(params) {
@@ -906,11 +915,17 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
906
915
  mergeCurrentDiscountSelectionState(discountList, currentDiscountList) {
907
916
  if (!currentDiscountList.length)
908
917
  return discountList;
909
- const currentDiscountMap = new Map(
910
- currentDiscountList.map((discount) => [discount.id, discount])
911
- );
918
+ const currentDiscountMap = /* @__PURE__ */ new Map();
919
+ currentDiscountList.forEach((discount) => {
920
+ currentDiscountMap.set(
921
+ `${discount.id}:${isBaseSalesHistoricalDiscountEntry(discount) ? "historical" : "runtime"}`,
922
+ discount
923
+ );
924
+ });
912
925
  return discountList.map((discount) => {
913
- const currentDiscount = currentDiscountMap.get(discount.id);
926
+ const currentDiscount = currentDiscountMap.get(
927
+ `${discount.id}:${isBaseSalesHistoricalDiscountEntry(discount) ? "historical" : "runtime"}`
928
+ );
914
929
  if (!currentDiscount)
915
930
  return discount;
916
931
  if (currentDiscount.isManualSelect) {
@@ -1145,7 +1160,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1145
1160
  throw new Error("order 模块未初始化");
1146
1161
  const list = this.store.order.getDiscountList();
1147
1162
  const updated = list.map(
1148
- (d) => d.id === params.discountId ? {
1163
+ (d) => d.id === params.discountId && !isBaseSalesHistoricalDiscountEntry(d) ? {
1149
1164
  ...d,
1150
1165
  isSelected: params.isSelected,
1151
1166
  isManualSelect: !params.isSelected
@@ -207,6 +207,10 @@ function transformBaseProductToOrderProduct(params) {
207
207
  if (uniqueIdentificationNumber) {
208
208
  metadata.unique_identification_number = String(uniqueIdentificationNumber);
209
209
  }
210
+ const productTitle = {
211
+ ...(sourceProduct == null ? void 0 : sourceProduct.title_i18n) || {},
212
+ original: (sourceProduct == null ? void 0 : sourceProduct.title) || ""
213
+ };
210
214
  return {
211
215
  product_id: productId,
212
216
  product_variant_id: productVariantId,
@@ -231,6 +235,7 @@ function transformBaseProductToOrderProduct(params) {
231
235
  ),
232
236
  metadata,
233
237
  note: payload.note != null ? String(payload.note) : "",
238
+ product_title: productTitle,
234
239
  _origin: {
235
240
  ...sourceProduct || {},
236
241
  callbackData: payload
@@ -311,7 +311,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
311
311
  date: string;
312
312
  status: string;
313
313
  week: string;
314
- weekNum: 0 | 5 | 1 | 4 | 2 | 3 | 6;
314
+ weekNum: 0 | 2 | 1 | 6 | 3 | 4 | 5;
315
315
  }[]>;
316
316
  submitTimeSlot(timeSlots: TimeSliceItem): void;
317
317
  private getScheduleDataByIds;
@@ -441,19 +441,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
441
441
  * 加车两阶段主决策(规格弹窗 / 资源编辑 / 直接加车)。
442
442
  * 与 ticketBooking `handleSelectProduct` + `handleBooking4Service` 等价。
443
443
  */
444
- decideAddProduct(item: any, options?: Partial<AddProductDecideContext>): {
445
- action: "reloadCatalog";
446
- } | {
447
- action: "add";
448
- cacheItem: any;
449
- } | {
450
- action: "requiresDetail";
451
- payload: AddProductRequiresDetailPayload;
452
- } | {
453
- action: "requiresBookingEdit";
454
- cacheItem: any;
455
- payload: import("./utils/addProductDecision").AddProductRequiresBookingEditPayload;
456
- };
444
+ decideAddProduct(item: any, options?: Partial<AddProductDecideContext>): import("./utils/addProductDecision").AddProductDecision;
457
445
  /** 规格弹窗 callback 后的第二段决策。 */
458
446
  decideAfterDetail(cacheItem: any, options?: Partial<AddProductDecideContext>): import("./utils/addProductDecision").AddProductDecision;
459
447
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.2.247",
4
+ "version": "2.2.249",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",