@pisell/pisellos 0.10.66 → 0.10.68

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.
@@ -2152,7 +2152,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
2152
2152
  (_this$store$customer = this.store.customer) === null || _this$store$customer === void 0 || (_this$store$customer$ = _this$store$customer.setSelectedCustomer) === null || _this$store$customer$ === void 0 || _this$store$customer$.call(_this$store$customer, authenticatedCustomer);
2153
2153
  this.setOrderCustomer(authenticatedCustomer);
2154
2154
  _context8.next = 15;
2155
- return Promise.all([this.refreshDiscountConfigAfterOrderCustomerChange(authenticatedCustomerId), this.waitForOrderCustomerPromotionRefresh()]);
2155
+ return Promise.all([this.refreshDiscountConfigAfterOrderCustomerChange(authenticatedCustomerId), this.waitForOrderCustomerPromotionRefresh(), this.waitForOrderCustomerContactInfo()]);
2156
2156
  case 15:
2157
2157
  return _context8.abrupt("return", true);
2158
2158
  case 16:
@@ -1918,8 +1918,10 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
1918
1918
  }
1919
1919
  async validateContactInfo() {
1920
1920
  const order = this.getTempOrder();
1921
- const identity = order?._extend?.localId || order?.external_sale_number || order?.order_id || order;
1922
1921
  const customerId = order?.customer_id;
1922
+ // Missing customer IDs and the reserved Walk-In IDs do not require contact info.
1923
+ if (!Number.isFinite(Number(customerId)) || Number(customerId) <= 1) return;
1924
+ const identity = order?._extend?.localId || order?.external_sale_number || order?.order_id || order;
1923
1925
  const config = await this.getContactInfoConfig();
1924
1926
  const current = this.getTempOrder();
1925
1927
  if (identity !== (current?._extend?.localId || current?.external_sale_number || current?.order_id || current) || customerId !== current?.customer_id) {
@@ -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 | 2 | 1 | 6 | 4 | 5 | 3;
329
+ weekNum: 0 | 6 | 5 | 1 | 2 | 3 | 4;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
@@ -32,6 +32,7 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
32
32
  private orderCustomerDiscountRefreshCustomerId;
33
33
  private orderCustomerDiscountRefreshTarget;
34
34
  private orderCustomerPromotionRefreshInFlight;
35
+ private orderCustomerContactRequest;
35
36
  private readonly customerResolveRequests;
36
37
  protected loadOpenDataInFlight: Promise<OpenDataConfig> | null;
37
38
  protected loadOpenDataInFlightTarget: string | null;
@@ -276,6 +277,16 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
276
277
  setOrderCustomer(customer: ICustomer | null, options?: {
277
278
  source?: OrderCustomerChangePayload['source'];
278
279
  }): void;
280
+ private resetOrderCustomerContactInfo;
281
+ /** Explicit edits, including clearing the contact, must win over a pending default. */
282
+ updateTempOrderContactsInfo(contact: Record<string, any> | null): Record<string, any> | null;
283
+ private getCustomerContactScope;
284
+ private getCustomerContactOrderKey;
285
+ replaceTempOrder(...args: Parameters<BaseSalesImpl['replaceTempOrder']>): Promise<import("../../modules/Order/types").OrderTempOrder>;
286
+ private applyDefaultOrderCustomerContactInfo;
287
+ private prefillOrderCustomerContactInfo;
288
+ protected waitForOrderCustomerContactInfo(): Promise<void>;
289
+ validateContactInfo(): Promise<void>;
279
290
  /**
280
291
  * 读取 tempOrder 上的下单客户协议字段;customer_id 缺失时返回 null。
281
292
  */
@@ -468,7 +479,19 @@ export declare class BookingTicketImpl extends BaseSalesImpl implements Module {
468
479
  * 加车两阶段主决策(规格弹窗 / 资源编辑 / 直接加车)。
469
480
  * 与 ticketBooking `handleSelectProduct` + `handleBooking4Service` 等价。
470
481
  */
471
- decideAddProduct(item: any, options?: Partial<AddProductDecideContext>): import("./utils/addProductDecision").AddProductDecision;
482
+ decideAddProduct(item: any, options?: Partial<AddProductDecideContext>): {
483
+ action: "reloadCatalog";
484
+ } | {
485
+ action: "add";
486
+ cacheItem: any;
487
+ } | {
488
+ action: "requiresDetail";
489
+ payload: AddProductRequiresDetailPayload;
490
+ } | {
491
+ action: "requiresBookingEdit";
492
+ cacheItem: any;
493
+ payload: import("./utils/addProductDecision").AddProductRequiresBookingEditPayload;
494
+ };
472
495
  /** 规格弹窗 callback 后的第二段决策。 */
473
496
  decideAfterDetail(cacheItem: any, options?: Partial<AddProductDecideContext>): import("./utils/addProductDecision").AddProductDecision;
474
497
  /**
@@ -40,6 +40,7 @@ var _bookingStatus = require("./utils/bookingStatus");
40
40
  var _resolveBestAddTimePlan = require("./utils/resolveBestAddTimePlan");
41
41
  var _utils = require("../../modules/Order/utils");
42
42
  var _contactInfo = require("../../modules/OpenData/contactInfo");
43
+ var _platform = require("../../utils/platform");
43
44
  var _lodashEs = require("lodash-es");
44
45
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
45
46
  const OPEN_DATA_SECTION_CODES = ['sale', 'reservation', 'fulfillment', 'menu', 'workflow', 'documents'];
@@ -164,6 +165,7 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
164
165
  orderCustomerDiscountRefreshCustomerId = null;
165
166
  orderCustomerDiscountRefreshTarget = null;
166
167
  orderCustomerPromotionRefreshInFlight = null;
168
+ orderCustomerContactRequest = null;
167
169
  customerResolveRequests = new Map();
168
170
  loadOpenDataInFlight = null;
169
171
  loadOpenDataInFlightTarget = null;
@@ -1028,9 +1030,15 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
1028
1030
  this.hasManualDiscountSelection = false;
1029
1031
  }
1030
1032
  if (!customerUnchanged && options?.source !== 'detailHydrate') {
1033
+ this.resetOrderCustomerContactInfo();
1031
1034
  this.store.order.updateTempOrderContactsInfo((0, _lodashEs.cloneDeep)((0, _contactInfo.extractCustomerContactInfo)(customer)));
1032
1035
  }
1033
1036
  this.store.order.setOrderCustomer(patch, customer);
1037
+ if (options?.source === 'detailHydrate') {
1038
+ this.orderCustomerContactRequest = null;
1039
+ } else {
1040
+ this.prefillOrderCustomerContactInfo(customer, !customerUnchanged);
1041
+ }
1034
1042
  const snapshotAfterOrderSet = this.store.order.getOrderCustomerSnapshot();
1035
1043
  if (customerUnchanged) {
1036
1044
  // hydrate 后 customer_id 已存在但 _extend.customerSnapshot 仍为空时,
@@ -1063,6 +1071,105 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
1063
1071
  this.orderCustomerPromotionRefreshInFlight = null;
1064
1072
  });
1065
1073
  }
1074
+ resetOrderCustomerContactInfo() {
1075
+ this.orderCustomerContactRequest = null;
1076
+ const order = this.getTempOrder();
1077
+ if (order?._extend) delete order._extend.contactInfoEdited;
1078
+ }
1079
+
1080
+ /** Explicit edits, including clearing the contact, must win over a pending default. */
1081
+ updateTempOrderContactsInfo(contact) {
1082
+ const order = this.store.order.ensureTempOrder();
1083
+ order._extend || (order._extend = {});
1084
+ order._extend.contactInfoEdited = true;
1085
+ this.orderCustomerContactRequest = null;
1086
+ return super.updateTempOrderContactsInfo(contact);
1087
+ }
1088
+ getCustomerContactScope() {
1089
+ return JSON.stringify([this.getPickupTimingScope(), this.otherParams?.channel, this.otherParams?.shop_id, this.otherParams?.tenantId]);
1090
+ }
1091
+ getCustomerContactOrderKey() {
1092
+ const order = this.getTempOrder();
1093
+ // Cart mutations can replace the object without changing the order.
1094
+ const identity = order?.external_sale_number || order?.request_unique_idempotency_token || order?._extend?.localId || order?.order_id;
1095
+ return identity ? JSON.stringify([identity, order?.order_id]) : order;
1096
+ }
1097
+ async replaceTempOrder(...args) {
1098
+ this.orderCustomerContactRequest = null;
1099
+ return super.replaceTempOrder(...args);
1100
+ }
1101
+ async applyDefaultOrderCustomerContactInfo(contact) {
1102
+ this.store.order.updateTempOrderContactsInfo((0, _lodashEs.cloneDeep)(contact));
1103
+ // Metadata may finish after promotion/discount refresh; publish the updated cart explicitly.
1104
+ await this.effectsEmit('onTempOrderReplaced', {
1105
+ tempOrder: this.getTempOrder()
1106
+ });
1107
+ }
1108
+ prefillOrderCustomerContactInfo(customer, customerChanged) {
1109
+ const order = this.getTempOrder();
1110
+ const customerId = Number(order?.customer_id);
1111
+ if (!order || !Number.isInteger(customerId) || customerId <= 1 || order.contacts_info != null || order._extend?.contactInfoEdited) return;
1112
+ // A restored new cart may already have its customer ID. Existing sales keep their snapshot,
1113
+ // even when it is empty; only an explicit customer switch replaces it.
1114
+ if (!customerChanged && order.order_id && !String(order.order_id).startsWith('local_order')) return;
1115
+ const contact = (0, _contactInfo.extractCustomerContactInfo)(customer);
1116
+ if (contact) {
1117
+ this.orderCustomerContactRequest = null;
1118
+ void this.applyDefaultOrderCustomerContactInfo(contact);
1119
+ return;
1120
+ }
1121
+ // A relation explicitly returned as null is authoritative. Only a missing relation needs fetching.
1122
+ if (customer.contacts_info !== undefined) return;
1123
+ const userPlatform = (0, _platform.isCustomerUserPlatform)(this.otherParams?.platform);
1124
+ const getAuthenticatedCustomerId = () => Number(this.core?.getPlugin?.('user')?.get?.()?.id);
1125
+ if (userPlatform && getAuthenticatedCustomerId() !== customerId) return;
1126
+ const scope = this.getCustomerContactScope();
1127
+ const orderKey = this.getCustomerContactOrderKey();
1128
+ const previous = this.orderCustomerContactRequest;
1129
+ if (previous?.orderKey === orderKey && previous.customerId === customerId && previous.scope === scope) return;
1130
+ const pending = {
1131
+ orderKey,
1132
+ customerId,
1133
+ scope,
1134
+ promise: Promise.resolve()
1135
+ };
1136
+ this.orderCustomerContactRequest = pending;
1137
+ const loadContact = async () => {
1138
+ if (userPlatform) {
1139
+ // Same endpoint as BookingByStep.getContactInfo; the PC/H5 host adds /h5 and login headers.
1140
+ const result = await this.request.get('/customer/metadata', {
1141
+ key: 'contacts_info'
1142
+ });
1143
+ if (result?.code !== 200 || result?.status === false) throw new Error('Customer contact lookup failed');
1144
+ return (0, _contactInfo.isContactRecord)(result.data) ? result.data : null;
1145
+ }
1146
+ // POS and physical Kiosk share the /shop request plugin and current-shop customer resolver.
1147
+ const resolved = await this.resolveCustomerById(customerId);
1148
+ return Number(resolved?.id) === customerId ? (0, _contactInfo.extractCustomerContactInfo)(resolved) : null;
1149
+ };
1150
+ pending.promise = loadContact().then(async value => {
1151
+ const current = this.getTempOrder();
1152
+ if (this.orderCustomerContactRequest !== pending || this.getCustomerContactOrderKey() !== orderKey || Number(current?.customer_id) !== customerId || scope !== this.getCustomerContactScope() || current?._extend?.contactInfoEdited || current?.contacts_info != null || userPlatform && getAuthenticatedCustomerId() !== customerId) return;
1153
+ if (value) await this.applyDefaultOrderCustomerContactInfo(value);
1154
+ }).catch(() => {
1155
+ // A failed default does not prevent manual entry; a subsequent sync can retry.
1156
+ if (this.orderCustomerContactRequest === pending) this.orderCustomerContactRequest = null;
1157
+ console.warn('[BookingTicket] Failed to load saved customer contact information');
1158
+ });
1159
+ }
1160
+ waitForOrderCustomerContactInfo() {
1161
+ return this.orderCustomerContactRequest?.promise ?? Promise.resolve();
1162
+ }
1163
+ async validateContactInfo() {
1164
+ const orderKey = this.getCustomerContactOrderKey();
1165
+ const customerId = this.getTempOrder()?.customer_id;
1166
+ const scope = this.getCustomerContactScope();
1167
+ await this.waitForOrderCustomerContactInfo();
1168
+ if (this.getCustomerContactOrderKey() !== orderKey || this.getTempOrder()?.customer_id !== customerId || this.getCustomerContactScope() !== scope) {
1169
+ throw new Error('The order changed. Please try again.');
1170
+ }
1171
+ await super.validateContactInfo();
1172
+ }
1066
1173
 
1067
1174
  /**
1068
1175
  * 读取 tempOrder 上的下单客户协议字段;customer_id 缺失时返回 null。
@@ -1082,6 +1189,8 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
1082
1189
  * 清空下单客户(协议字段 + snapshot)。
1083
1190
  */
1084
1191
  clearOrderCustomer(options) {
1192
+ this.orderCustomerContactRequest = null;
1193
+ if (!options?.preserveContactInfo) this.resetOrderCustomerContactInfo();
1085
1194
  if (!options?.preserveContactInfo) this.store.order.updateTempOrderContactsInfo(null);
1086
1195
  this.store.order.clearOrderCustomer();
1087
1196
  this.discountConfigCacheKey = null;
@@ -1902,6 +2011,11 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
1902
2011
  async setOtherParams(params, {
1903
2012
  cover = false
1904
2013
  } = {}) {
2014
+ const nextParams = cover ? params : {
2015
+ ...this.otherParams,
2016
+ ...params
2017
+ };
2018
+ if (['businessCode', 'business_code', 'channel', 'platform', 'shop_id', 'tenantId', 'cacheId'].some(key => nextParams?.[key] !== this.otherParams?.[key])) this.orderCustomerContactRequest = null;
1905
2019
  await super.setOtherParams(params, {
1906
2020
  cover
1907
2021
  });
@@ -2017,6 +2131,7 @@ class BookingTicketImpl extends _BaseSales.BaseSalesImpl {
2017
2131
  * 再清理 BookingTicket 自有资源(scan 监听 + scan 内存缓存)。
2018
2132
  */
2019
2133
  async destroy() {
2134
+ this.orderCustomerContactRequest = null;
2020
2135
  await super.destroy();
2021
2136
  try {
2022
2137
  this.scan?.removeAllListeners();
@@ -1718,7 +1718,7 @@ class UnifiedBookingSalesImpl extends _BookingTicket.BookingTicket {
1718
1718
  }
1719
1719
  this.store.customer?.setSelectedCustomer?.(authenticatedCustomer);
1720
1720
  this.setOrderCustomer(authenticatedCustomer);
1721
- await Promise.all([this.refreshDiscountConfigAfterOrderCustomerChange(authenticatedCustomerId), this.waitForOrderCustomerPromotionRefresh()]);
1721
+ await Promise.all([this.refreshDiscountConfigAfterOrderCustomerChange(authenticatedCustomerId), this.waitForOrderCustomerPromotionRefresh(), this.waitForOrderCustomerContactInfo()]);
1722
1722
  return true;
1723
1723
  }
1724
1724
  isAuthenticatedCustomerUserPlatform() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "0.10.66",
4
+ "version": "0.10.68",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",