@pisell/pisellos 2.2.261 → 2.2.262
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/model/strategy/adapter/dataVariant/adapter.d.ts +50 -0
- package/dist/model/strategy/adapter/dataVariant/adapter.js +167 -0
- package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +89 -0
- package/dist/model/strategy/adapter/dataVariant/evaluator.js +780 -0
- package/dist/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
- package/dist/model/strategy/adapter/dataVariant/examples.js +277 -0
- package/dist/model/strategy/adapter/dataVariant/index.d.ts +4 -0
- package/dist/model/strategy/adapter/dataVariant/index.js +4 -0
- package/dist/model/strategy/adapter/dataVariant/type.d.ts +148 -0
- package/dist/model/strategy/adapter/dataVariant/type.js +54 -0
- package/dist/model/strategy/adapter/index.d.ts +4 -0
- package/dist/model/strategy/adapter/index.js +5 -1
- package/dist/model/strategy/adapter/promotion/adapter.d.ts +0 -4
- package/dist/model/strategy/adapter/promotion/adapter.js +0 -23
- package/dist/model/strategy/adapter/promotion/evaluator.d.ts +0 -17
- package/dist/model/strategy/adapter/promotion/evaluator.js +6 -279
- package/dist/model/strategy/adapter/promotion/examples.d.ts +0 -86
- package/dist/model/strategy/adapter/promotion/examples.js +0 -99
- package/dist/model/strategy/adapter/promotion/index.d.ts +1 -1
- package/dist/model/strategy/adapter/promotion/index.js +0 -9
- package/dist/model/strategy/adapter/promotion/type.d.ts +2 -90
- package/dist/model/strategy/adapter/promotion/type.js +0 -45
- package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +16 -10
- package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +2 -1
- package/dist/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +1 -1
- package/dist/modules/BookingContext/utils/cacheItemToBookingInput.js +32 -1
- package/dist/modules/Discount/index.d.ts +5 -2
- package/dist/modules/Discount/index.js +30 -7
- package/dist/modules/Discount/types.d.ts +4 -0
- package/dist/modules/Order/index.d.ts +14 -2
- package/dist/modules/Order/index.js +1035 -736
- package/dist/modules/Order/types.d.ts +16 -0
- package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
- package/dist/modules/Order/utils/orderCollectionIdentity.js +405 -0
- package/dist/modules/Order/utils.d.ts +4 -3
- package/dist/modules/Order/utils.js +54 -61
- package/dist/modules/Product/types.d.ts +22 -0
- package/dist/modules/ProductList/index.d.ts +1 -1
- package/dist/modules/ProductList/index.js +4 -2
- package/dist/modules/ProductList/types.d.ts +2 -0
- package/dist/modules/Rules/index.d.ts +2 -9
- package/dist/modules/Rules/index.js +69 -43
- package/dist/modules/Rules/types.d.ts +10 -1
- package/dist/server/index.d.ts +55 -0
- package/dist/server/index.js +1161 -742
- package/dist/server/modules/order/index.d.ts +10 -4
- package/dist/server/modules/order/index.js +404 -399
- package/dist/server/modules/order/types.d.ts +4 -0
- package/dist/server/modules/products/index.d.ts +31 -8
- package/dist/server/modules/products/index.js +549 -390
- package/dist/server/modules/products/types.d.ts +18 -0
- package/dist/solution/BaseSales/index.d.ts +21 -1
- package/dist/solution/BaseSales/index.js +1136 -789
- package/dist/solution/BaseSales/types.d.ts +6 -1
- package/dist/solution/BaseSales/types.js +1 -1
- package/dist/solution/BaseSales/utils/cartPromotion.d.ts +1 -3
- package/dist/solution/BaseSales/utils/cartPromotion.js +48 -81
- package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +3 -3
- package/dist/solution/BaseSales/utils/parseSalesResponse.js +6 -8
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +14 -1
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.js +59 -25
- package/dist/solution/BookingTicket/types.d.ts +2 -0
- package/dist/solution/ScanOrder/index.js +20 -31
- package/dist/solution/ShopDiscount/index.js +15 -14
- package/dist/solution/VenueBooking/index.js +19 -30
- package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +50 -0
- package/lib/model/strategy/adapter/dataVariant/adapter.js +149 -0
- package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +89 -0
- package/lib/model/strategy/adapter/dataVariant/evaluator.js +583 -0
- package/lib/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
- package/lib/model/strategy/adapter/dataVariant/examples.js +293 -0
- package/lib/model/strategy/adapter/dataVariant/index.d.ts +4 -0
- package/lib/model/strategy/adapter/dataVariant/index.js +38 -0
- package/lib/model/strategy/adapter/dataVariant/type.d.ts +148 -0
- package/lib/model/strategy/adapter/dataVariant/type.js +31 -0
- package/lib/model/strategy/adapter/index.d.ts +4 -0
- package/lib/model/strategy/adapter/index.js +13 -2
- package/lib/model/strategy/adapter/promotion/adapter.d.ts +0 -4
- package/lib/model/strategy/adapter/promotion/adapter.js +0 -20
- package/lib/model/strategy/adapter/promotion/evaluator.d.ts +0 -17
- package/lib/model/strategy/adapter/promotion/evaluator.js +0 -235
- package/lib/model/strategy/adapter/promotion/examples.d.ts +0 -86
- package/lib/model/strategy/adapter/promotion/examples.js +0 -91
- package/lib/model/strategy/adapter/promotion/index.d.ts +1 -1
- package/lib/model/strategy/adapter/promotion/index.js +0 -51
- package/lib/model/strategy/adapter/promotion/type.d.ts +2 -90
- package/lib/model/strategy/adapter/promotion/type.js +0 -2
- package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +5 -0
- package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +1 -0
- package/lib/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +1 -1
- package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +23 -2
- package/lib/modules/Discount/index.d.ts +5 -2
- package/lib/modules/Discount/index.js +23 -3
- package/lib/modules/Discount/types.d.ts +4 -0
- package/lib/modules/Order/index.d.ts +14 -2
- package/lib/modules/Order/index.js +326 -60
- package/lib/modules/Order/types.d.ts +16 -0
- package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
- package/lib/modules/Order/utils/orderCollectionIdentity.js +415 -0
- package/lib/modules/Order/utils.d.ts +4 -3
- package/lib/modules/Order/utils.js +22 -23
- package/lib/modules/Product/types.d.ts +22 -0
- package/lib/modules/ProductList/index.d.ts +1 -1
- package/lib/modules/ProductList/index.js +4 -2
- package/lib/modules/ProductList/types.d.ts +2 -0
- package/lib/modules/Rules/index.d.ts +2 -9
- package/lib/modules/Rules/index.js +61 -29
- package/lib/modules/Rules/types.d.ts +10 -1
- package/lib/server/index.d.ts +55 -0
- package/lib/server/index.js +327 -31
- package/lib/server/modules/order/index.d.ts +10 -4
- package/lib/server/modules/order/index.js +198 -139
- package/lib/server/modules/order/types.d.ts +4 -0
- package/lib/server/modules/products/index.d.ts +31 -8
- package/lib/server/modules/products/index.js +134 -35
- package/lib/server/modules/products/types.d.ts +18 -0
- package/lib/solution/BaseSales/index.d.ts +21 -1
- package/lib/solution/BaseSales/index.js +313 -72
- package/lib/solution/BaseSales/types.d.ts +6 -1
- package/lib/solution/BaseSales/utils/cartPromotion.d.ts +1 -3
- package/lib/solution/BaseSales/utils/cartPromotion.js +29 -60
- package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +3 -3
- package/lib/solution/BaseSales/utils/parseSalesResponse.js +4 -5
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +8 -0
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.js +33 -8
- package/lib/solution/BookingTicket/types.d.ts +2 -0
- package/lib/solution/ScanOrder/index.js +0 -8
- package/lib/solution/ShopDiscount/index.js +2 -1
- package/lib/solution/VenueBooking/index.js +0 -8
- package/package.json +1 -1
package/lib/server/index.js
CHANGED
|
@@ -76,6 +76,8 @@ var Server = class {
|
|
|
76
76
|
};
|
|
77
77
|
// ---- 商品查询订阅者 ----
|
|
78
78
|
this.productQuerySubscribers = /* @__PURE__ */ new Map();
|
|
79
|
+
/** subscriberId → 智能定价变价时间点定时器句柄(与 subscriber 分离存储,便于 clear) */
|
|
80
|
+
this.productQueryScheduleTimers = /* @__PURE__ */ new Map();
|
|
79
81
|
// ---- 订单 / 预约列表查询订阅者 ----
|
|
80
82
|
this.orderQuerySubscribers = /* @__PURE__ */ new Map();
|
|
81
83
|
this.bookingQuerySubscribers = /* @__PURE__ */ new Map();
|
|
@@ -208,7 +210,7 @@ var Server = class {
|
|
|
208
210
|
*/
|
|
209
211
|
this.handleProductQuery = async ({ url, method, data, config }) => {
|
|
210
212
|
console.log("[Server] handleProductQuery:", url, method, data, config);
|
|
211
|
-
const { menu_list_ids, schedule_datetime, schedule_date, customer_id, ids, extension_type } = data;
|
|
213
|
+
const { menu_list_ids, schedule_datetime, schedule_date, customer_id, ids, extension_type, strategy_context } = data;
|
|
212
214
|
const { callback, subscriberId } = config || {};
|
|
213
215
|
this.logInfo("handleProductQuery: 开始处理商品查询请求", {
|
|
214
216
|
menu_list_ids,
|
|
@@ -216,19 +218,32 @@ var Server = class {
|
|
|
216
218
|
schedule_datetime,
|
|
217
219
|
schedule_date,
|
|
218
220
|
customer_id,
|
|
219
|
-
extension_type
|
|
221
|
+
extension_type,
|
|
222
|
+
strategyContextKeys: strategy_context ? Object.keys(strategy_context) : []
|
|
220
223
|
});
|
|
221
224
|
if (subscriberId && typeof callback === "function") {
|
|
222
225
|
this.productQuerySubscribers.set(subscriberId, {
|
|
223
226
|
callback,
|
|
224
|
-
context: { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type }
|
|
227
|
+
context: { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type, strategy_context }
|
|
225
228
|
});
|
|
226
229
|
this.logInfo("handleProductQuery: 已注册订阅者", {
|
|
227
230
|
subscriberId,
|
|
228
231
|
totalSubscribers: this.productQuerySubscribers.size
|
|
229
232
|
});
|
|
230
233
|
}
|
|
231
|
-
|
|
234
|
+
const result = await this.computeProductQueryResult({
|
|
235
|
+
menu_list_ids,
|
|
236
|
+
ids,
|
|
237
|
+
schedule_date,
|
|
238
|
+
schedule_datetime,
|
|
239
|
+
customer_id,
|
|
240
|
+
extension_type,
|
|
241
|
+
strategy_context
|
|
242
|
+
});
|
|
243
|
+
if (subscriberId && typeof callback === "function") {
|
|
244
|
+
this.syncProductQueryScheduleTimers(subscriberId, strategy_context);
|
|
245
|
+
}
|
|
246
|
+
return result;
|
|
232
247
|
};
|
|
233
248
|
/**
|
|
234
249
|
* 按商品 id 查询单条(GET /shop/product/query/:productId)
|
|
@@ -769,12 +784,13 @@ var Server = class {
|
|
|
769
784
|
if (!this.shouldForceRemoteSalesDetail(data)) {
|
|
770
785
|
const localOrder = await this.order.getLocalOrderByLookup(lookup);
|
|
771
786
|
if (localOrder) {
|
|
787
|
+
const enrichedOrder = await this.withSalesDetailProductSnapshots(localOrder);
|
|
772
788
|
this.logInfo("handleOrderSalesDetail: 命中本地订单", { lookup });
|
|
773
789
|
return {
|
|
774
790
|
code: 200,
|
|
775
791
|
status: true,
|
|
776
792
|
message: "",
|
|
777
|
-
data:
|
|
793
|
+
data: enrichedOrder
|
|
778
794
|
};
|
|
779
795
|
}
|
|
780
796
|
}
|
|
@@ -821,11 +837,12 @@ var Server = class {
|
|
|
821
837
|
};
|
|
822
838
|
}
|
|
823
839
|
this.logInfo("handleOrderSalesDetail: 远端订单已同步到本地", { lookup });
|
|
840
|
+
const enrichedOrder = await this.withSalesDetailProductSnapshots(savedOrder);
|
|
824
841
|
return {
|
|
825
842
|
code: 200,
|
|
826
843
|
status: true,
|
|
827
844
|
message: "",
|
|
828
|
-
data:
|
|
845
|
+
data: enrichedOrder
|
|
829
846
|
};
|
|
830
847
|
} catch (error) {
|
|
831
848
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -1909,6 +1926,7 @@ var Server = class {
|
|
|
1909
1926
|
*/
|
|
1910
1927
|
removeProductQuerySubscriber(subscriberId) {
|
|
1911
1928
|
if (subscriberId) {
|
|
1929
|
+
this.clearSubscriberScheduleTimers(subscriberId);
|
|
1912
1930
|
this.productQuerySubscribers.delete(subscriberId);
|
|
1913
1931
|
this.logInfo("removeProductQuerySubscriber: 已移除订阅者", {
|
|
1914
1932
|
subscriberId,
|
|
@@ -1916,6 +1934,156 @@ var Server = class {
|
|
|
1916
1934
|
});
|
|
1917
1935
|
}
|
|
1918
1936
|
}
|
|
1937
|
+
/**
|
|
1938
|
+
* 构建商品 query 响应 data 段,附带智能定价 schedule_time_points 元数据。
|
|
1939
|
+
*/
|
|
1940
|
+
buildProductQueryResultPayload(list, count) {
|
|
1941
|
+
var _a, _b;
|
|
1942
|
+
return {
|
|
1943
|
+
list,
|
|
1944
|
+
count: count ?? list.length,
|
|
1945
|
+
schedule_time_points: ((_b = (_a = this.products) == null ? void 0 : _a.getLastScheduleTimePoints) == null ? void 0 : _b.call(_a)) ?? []
|
|
1946
|
+
};
|
|
1947
|
+
}
|
|
1948
|
+
/**
|
|
1949
|
+
* 是否启用商品 query 订阅的 schedule 时间点定时重算。
|
|
1950
|
+
* strategy_context.enable_schedule_reload === false 时关闭。
|
|
1951
|
+
*/
|
|
1952
|
+
shouldScheduleProductQueryReload(strategy_context) {
|
|
1953
|
+
return (strategy_context == null ? void 0 : strategy_context.enable_schedule_reload) !== false;
|
|
1954
|
+
}
|
|
1955
|
+
/**
|
|
1956
|
+
* 清除指定 subscriber 的全部 schedule 定时器,防止重复 query 或 unsubscribe 后泄漏。
|
|
1957
|
+
*/
|
|
1958
|
+
clearSubscriberScheduleTimers(subscriberId) {
|
|
1959
|
+
const timers = this.productQueryScheduleTimers.get(subscriberId);
|
|
1960
|
+
if (timers == null ? void 0 : timers.length) {
|
|
1961
|
+
timers.forEach((timerId) => clearTimeout(timerId));
|
|
1962
|
+
}
|
|
1963
|
+
this.productQueryScheduleTimers.delete(subscriberId);
|
|
1964
|
+
const subscriber = this.productQuerySubscribers.get(subscriberId);
|
|
1965
|
+
if (subscriber) {
|
|
1966
|
+
subscriber.scheduleTimerIds = [];
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
/**
|
|
1970
|
+
* 从 productQueryScheduleTimers 移除已触发的 timer 引用。
|
|
1971
|
+
*/
|
|
1972
|
+
removeScheduleTimerRef(subscriberId, timerId) {
|
|
1973
|
+
const timers = this.productQueryScheduleTimers.get(subscriberId);
|
|
1974
|
+
if (!(timers == null ? void 0 : timers.length))
|
|
1975
|
+
return;
|
|
1976
|
+
const next = timers.filter((id) => id !== timerId);
|
|
1977
|
+
if (next.length === 0) {
|
|
1978
|
+
this.productQueryScheduleTimers.delete(subscriberId);
|
|
1979
|
+
} else {
|
|
1980
|
+
this.productQueryScheduleTimers.set(subscriberId, next);
|
|
1981
|
+
}
|
|
1982
|
+
const subscriber = this.productQuerySubscribers.get(subscriberId);
|
|
1983
|
+
if (subscriber) {
|
|
1984
|
+
subscriber.scheduleTimerIds = next;
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
/**
|
|
1988
|
+
* 计算 schedule 变价时间点到当前时刻的延迟(ms)。已过期返回 -1。
|
|
1989
|
+
*/
|
|
1990
|
+
computeScheduleTimePointDelayMs(scheduleDate, timePoint) {
|
|
1991
|
+
const parts = timePoint.split(":");
|
|
1992
|
+
if (parts.length < 2)
|
|
1993
|
+
return -1;
|
|
1994
|
+
const hours = parseInt(parts[0], 10);
|
|
1995
|
+
const minutes = parseInt(parts[1], 10);
|
|
1996
|
+
if (!Number.isFinite(hours) || !Number.isFinite(minutes))
|
|
1997
|
+
return -1;
|
|
1998
|
+
const target = (0, import_dayjs.default)(scheduleDate).hour(hours).minute(minutes).second(4).millisecond(0);
|
|
1999
|
+
const delayMs = target.diff((0, import_dayjs.default)());
|
|
2000
|
+
return delayMs >= 0 ? delayMs : -1;
|
|
2001
|
+
}
|
|
2002
|
+
/**
|
|
2003
|
+
* 定时重算前刷新 subscriber schedule 上下文:使用执行瞬间时间,禁止沿用首次 query 的 schedule_datetime。
|
|
2004
|
+
*/
|
|
2005
|
+
refreshSubscriberScheduleAtExecution(subscriber) {
|
|
2006
|
+
const executedAt = (0, import_dayjs.default)();
|
|
2007
|
+
const bookingDate = subscriber.context.schedule_date || executedAt.format("YYYY-MM-DD");
|
|
2008
|
+
subscriber.context.schedule_date = bookingDate;
|
|
2009
|
+
subscriber.context.schedule_datetime = `${bookingDate} ${executedAt.format("HH:mm:ss")}`;
|
|
2010
|
+
}
|
|
2011
|
+
/**
|
|
2012
|
+
* 为 subscriber 注册智能定价 scheduleTimePoints 定时重算。
|
|
2013
|
+
* 必须先 clearSubscriberScheduleTimers,再调用本方法。
|
|
2014
|
+
*/
|
|
2015
|
+
scheduleSubscriberTimePointReloads(subscriberId, timePoints) {
|
|
2016
|
+
const subscriber = this.productQuerySubscribers.get(subscriberId);
|
|
2017
|
+
if (!subscriber || !timePoints.length)
|
|
2018
|
+
return;
|
|
2019
|
+
const scheduleDate = subscriber.context.schedule_date || (0, import_dayjs.default)().format("YYYY-MM-DD");
|
|
2020
|
+
const timerIds = [];
|
|
2021
|
+
for (const timePoint of timePoints) {
|
|
2022
|
+
const delayMs = this.computeScheduleTimePointDelayMs(scheduleDate, timePoint);
|
|
2023
|
+
if (delayMs < 0)
|
|
2024
|
+
continue;
|
|
2025
|
+
const timerId = setTimeout(() => {
|
|
2026
|
+
void this.onScheduleTimePointTimerFire(subscriberId, timerId);
|
|
2027
|
+
}, delayMs);
|
|
2028
|
+
timerIds.push(timerId);
|
|
2029
|
+
}
|
|
2030
|
+
if (timerIds.length > 0) {
|
|
2031
|
+
this.productQueryScheduleTimers.set(subscriberId, timerIds);
|
|
2032
|
+
subscriber.scheduleTimerIds = timerIds;
|
|
2033
|
+
this.logInfo("scheduleSubscriberTimePointReloads: 已注册定时器", {
|
|
2034
|
+
subscriberId,
|
|
2035
|
+
timerCount: timerIds.length,
|
|
2036
|
+
timePoints
|
|
2037
|
+
});
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
/**
|
|
2041
|
+
* schedule 变价时间点定时器触发:刷新 schedule_datetime 后重算并 callback。
|
|
2042
|
+
*/
|
|
2043
|
+
async onScheduleTimePointTimerFire(subscriberId, timerId) {
|
|
2044
|
+
this.removeScheduleTimerRef(subscriberId, timerId);
|
|
2045
|
+
if (!this.productQuerySubscribers.has(subscriberId))
|
|
2046
|
+
return;
|
|
2047
|
+
const subscriber = this.productQuerySubscribers.get(subscriberId);
|
|
2048
|
+
this.refreshSubscriberScheduleAtExecution(subscriber);
|
|
2049
|
+
await this.recomputeAndNotifySubscriber(subscriberId);
|
|
2050
|
+
}
|
|
2051
|
+
/**
|
|
2052
|
+
* 对单个商品 query 订阅者重算并推送(定时路径;不新建 schedule timer)。
|
|
2053
|
+
*/
|
|
2054
|
+
async recomputeAndNotifySubscriber(subscriberId) {
|
|
2055
|
+
const subscriber = this.productQuerySubscribers.get(subscriberId);
|
|
2056
|
+
if (!subscriber)
|
|
2057
|
+
return;
|
|
2058
|
+
try {
|
|
2059
|
+
const result = await this.computeProductQueryResult(subscriber.context);
|
|
2060
|
+
subscriber.callback(result);
|
|
2061
|
+
this.logInfo("recomputeAndNotifySubscriber: 已推送", {
|
|
2062
|
+
subscriberId,
|
|
2063
|
+
schedule_datetime: subscriber.context.schedule_datetime
|
|
2064
|
+
});
|
|
2065
|
+
} catch (error) {
|
|
2066
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2067
|
+
this.logError("recomputeAndNotifySubscriber: 推送失败", {
|
|
2068
|
+
subscriberId,
|
|
2069
|
+
error: errorMessage
|
|
2070
|
+
});
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
/**
|
|
2074
|
+
* query 完成后为 subscriber 同步 schedule 定时器(先 clear 再 schedule)。
|
|
2075
|
+
*/
|
|
2076
|
+
syncProductQueryScheduleTimers(subscriberId, strategy_context) {
|
|
2077
|
+
var _a, _b;
|
|
2078
|
+
this.clearSubscriberScheduleTimers(subscriberId);
|
|
2079
|
+
if (!this.shouldScheduleProductQueryReload(strategy_context)) {
|
|
2080
|
+
return;
|
|
2081
|
+
}
|
|
2082
|
+
const timePoints = ((_b = (_a = this.products) == null ? void 0 : _a.getLastScheduleTimePoints) == null ? void 0 : _b.call(_a)) ?? [];
|
|
2083
|
+
if (timePoints.length > 0) {
|
|
2084
|
+
this.scheduleSubscriberTimePointReloads(subscriberId, timePoints);
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
1919
2087
|
/**
|
|
1920
2088
|
* 执行 sales 搜索并登记可见订单号。
|
|
1921
2089
|
* 搜索参数完全透传后端,OS 不做过滤、筛选、排序。
|
|
@@ -3231,6 +3399,123 @@ var Server = class {
|
|
|
3231
3399
|
return map;
|
|
3232
3400
|
}, {});
|
|
3233
3401
|
}
|
|
3402
|
+
collectSalesDetailProductIds(order) {
|
|
3403
|
+
const products = Array.isArray(order == null ? void 0 : order.products) ? order.products : [];
|
|
3404
|
+
const productIds = /* @__PURE__ */ new Set();
|
|
3405
|
+
const addProductId = (rawProductId) => {
|
|
3406
|
+
if (rawProductId === void 0 || rawProductId === null || rawProductId === "")
|
|
3407
|
+
return;
|
|
3408
|
+
const productId = Number(rawProductId);
|
|
3409
|
+
if (Number.isFinite(productId))
|
|
3410
|
+
productIds.add(productId);
|
|
3411
|
+
};
|
|
3412
|
+
products.forEach((product) => {
|
|
3413
|
+
addProductId((product == null ? void 0 : product.product_id) ?? (product == null ? void 0 : product.id));
|
|
3414
|
+
if (Array.isArray(product == null ? void 0 : product.product_bundle)) {
|
|
3415
|
+
product.product_bundle.forEach((bundle) => {
|
|
3416
|
+
addProductId((bundle == null ? void 0 : bundle.bundle_product_id) ?? (bundle == null ? void 0 : bundle._bundle_product_id) ?? (bundle == null ? void 0 : bundle.product_id));
|
|
3417
|
+
});
|
|
3418
|
+
}
|
|
3419
|
+
});
|
|
3420
|
+
return Array.from(productIds);
|
|
3421
|
+
}
|
|
3422
|
+
async buildSalesDetailProductSnapshotMap(order) {
|
|
3423
|
+
var _a;
|
|
3424
|
+
const productIds = this.collectSalesDetailProductIds(order);
|
|
3425
|
+
const getSnapshots = (_a = this.products) == null ? void 0 : _a.getProductSnapshotsByIds;
|
|
3426
|
+
if (!productIds.length || typeof getSnapshots !== "function")
|
|
3427
|
+
return {};
|
|
3428
|
+
try {
|
|
3429
|
+
return await getSnapshots.call(this.products, productIds);
|
|
3430
|
+
} catch (error) {
|
|
3431
|
+
this.logWarning("buildSalesDetailProductSnapshotMap: 查询本地商品快照失败", {
|
|
3432
|
+
product_ids: productIds,
|
|
3433
|
+
error: error instanceof Error ? error.message : String(error)
|
|
3434
|
+
});
|
|
3435
|
+
return {};
|
|
3436
|
+
}
|
|
3437
|
+
}
|
|
3438
|
+
withProductCatalogSnapshots(product, snapshotMap) {
|
|
3439
|
+
if (!product || typeof product !== "object")
|
|
3440
|
+
return product;
|
|
3441
|
+
const rawProductId = (product == null ? void 0 : product.product_id) ?? (product == null ? void 0 : product.id);
|
|
3442
|
+
if (rawProductId === void 0 || rawProductId === null || rawProductId === "")
|
|
3443
|
+
return product;
|
|
3444
|
+
const productId = Number(rawProductId);
|
|
3445
|
+
if (!Number.isFinite(productId))
|
|
3446
|
+
return product;
|
|
3447
|
+
const snapshot = snapshotMap[String(productId)];
|
|
3448
|
+
if (!snapshot)
|
|
3449
|
+
return product;
|
|
3450
|
+
const shouldFillCover = (product.product_cover === void 0 || product.product_cover === null || product.product_cover === "") && snapshot.cover !== void 0 && snapshot.cover !== null && snapshot.cover !== "";
|
|
3451
|
+
const metadata = product.metadata && typeof product.metadata === "object" ? product.metadata : {};
|
|
3452
|
+
const shouldFillHolderConfig = (metadata.holder_config === void 0 || metadata.holder_config === null) && snapshot.holder_config !== void 0 && snapshot.holder_config !== null;
|
|
3453
|
+
if (!shouldFillCover && !shouldFillHolderConfig)
|
|
3454
|
+
return product;
|
|
3455
|
+
return {
|
|
3456
|
+
...product,
|
|
3457
|
+
...shouldFillCover ? { product_cover: snapshot.cover } : {},
|
|
3458
|
+
...shouldFillHolderConfig ? {
|
|
3459
|
+
metadata: {
|
|
3460
|
+
...metadata,
|
|
3461
|
+
holder_config: snapshot.holder_config
|
|
3462
|
+
}
|
|
3463
|
+
} : {}
|
|
3464
|
+
};
|
|
3465
|
+
}
|
|
3466
|
+
withBundleCatalogSnapshots(product, snapshotMap) {
|
|
3467
|
+
if (!Array.isArray(product == null ? void 0 : product.product_bundle))
|
|
3468
|
+
return product;
|
|
3469
|
+
let hasChanged = false;
|
|
3470
|
+
const productBundle = product.product_bundle.map((bundle) => {
|
|
3471
|
+
if (!bundle || typeof bundle !== "object")
|
|
3472
|
+
return bundle;
|
|
3473
|
+
const rawProductId = (bundle == null ? void 0 : bundle.bundle_product_id) ?? (bundle == null ? void 0 : bundle._bundle_product_id) ?? (bundle == null ? void 0 : bundle.product_id);
|
|
3474
|
+
if (rawProductId === void 0 || rawProductId === null || rawProductId === "")
|
|
3475
|
+
return bundle;
|
|
3476
|
+
const productId = Number(rawProductId);
|
|
3477
|
+
if (!Number.isFinite(productId))
|
|
3478
|
+
return bundle;
|
|
3479
|
+
const snapshot = snapshotMap[String(productId)];
|
|
3480
|
+
const shouldFillCover = (bundle.cover === void 0 || bundle.cover === null || bundle.cover === "") && (snapshot == null ? void 0 : snapshot.cover) !== void 0 && snapshot.cover !== null && snapshot.cover !== "";
|
|
3481
|
+
if (!shouldFillCover)
|
|
3482
|
+
return bundle;
|
|
3483
|
+
hasChanged = true;
|
|
3484
|
+
return {
|
|
3485
|
+
...bundle,
|
|
3486
|
+
cover: snapshot.cover
|
|
3487
|
+
};
|
|
3488
|
+
});
|
|
3489
|
+
if (!hasChanged)
|
|
3490
|
+
return product;
|
|
3491
|
+
return {
|
|
3492
|
+
...product,
|
|
3493
|
+
product_bundle: productBundle
|
|
3494
|
+
};
|
|
3495
|
+
}
|
|
3496
|
+
async withSalesDetailProductSnapshots(order) {
|
|
3497
|
+
const products = Array.isArray(order == null ? void 0 : order.products) ? order.products : null;
|
|
3498
|
+
if (!(products == null ? void 0 : products.length))
|
|
3499
|
+
return order;
|
|
3500
|
+
const snapshotMap = await this.buildSalesDetailProductSnapshotMap(order);
|
|
3501
|
+
if (!Object.keys(snapshotMap).length)
|
|
3502
|
+
return order;
|
|
3503
|
+
let hasChanged = false;
|
|
3504
|
+
const enrichedProducts = products.map((product) => {
|
|
3505
|
+
const productWithBundleSnapshots = this.withBundleCatalogSnapshots(product, snapshotMap);
|
|
3506
|
+
const nextProduct = this.withProductCatalogSnapshots(productWithBundleSnapshots, snapshotMap);
|
|
3507
|
+
if (nextProduct !== product)
|
|
3508
|
+
hasChanged = true;
|
|
3509
|
+
return nextProduct;
|
|
3510
|
+
});
|
|
3511
|
+
if (!hasChanged)
|
|
3512
|
+
return order;
|
|
3513
|
+
const enrichedOrder = {
|
|
3514
|
+
...order,
|
|
3515
|
+
products: enrichedProducts
|
|
3516
|
+
};
|
|
3517
|
+
return enrichedOrder;
|
|
3518
|
+
}
|
|
3234
3519
|
withPendingSyncProductTitles(order, productMap) {
|
|
3235
3520
|
const products = Array.isArray(order.products) ? order.products : null;
|
|
3236
3521
|
if (!(products == null ? void 0 : products.length))
|
|
@@ -3992,8 +4277,14 @@ var Server = class {
|
|
|
3992
4277
|
*/
|
|
3993
4278
|
async computeProductQueryResult(context, options) {
|
|
3994
4279
|
const tTotal = performance.now();
|
|
3995
|
-
const { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type, product_id } = context;
|
|
4280
|
+
const { menu_list_ids, ids, schedule_date, schedule_datetime, customer_id, extension_type, product_id, strategy_context } = context;
|
|
3996
4281
|
const queryIds = Array.isArray(ids) ? ids.map((id) => Number(id)).filter((id) => Number.isFinite(id)) : [];
|
|
4282
|
+
const formatterContext = this.buildProductFormatterContext({
|
|
4283
|
+
schedule_date,
|
|
4284
|
+
schedule_datetime,
|
|
4285
|
+
customer_id,
|
|
4286
|
+
strategy_context
|
|
4287
|
+
});
|
|
3997
4288
|
this.logInfo("computeProductQueryResult 开始", {
|
|
3998
4289
|
menuListIdsCount: (menu_list_ids == null ? void 0 : menu_list_ids.length) ?? 0,
|
|
3999
4290
|
ids: queryIds,
|
|
@@ -4002,20 +4293,17 @@ var Server = class {
|
|
|
4002
4293
|
customer_id,
|
|
4003
4294
|
extension_type,
|
|
4004
4295
|
product_id,
|
|
4296
|
+
strategyContextKeys: strategy_context ? Object.keys(strategy_context) : [],
|
|
4005
4297
|
changedIds: options == null ? void 0 : options.changedIds
|
|
4006
4298
|
});
|
|
4007
4299
|
if (!this.products) {
|
|
4008
4300
|
this.logError("computeProductQueryResult: Products 模块未注册");
|
|
4009
|
-
return { message: "Products 模块未注册", data:
|
|
4301
|
+
return { message: "Products 模块未注册", data: this.buildProductQueryResultPayload([], 0) };
|
|
4010
4302
|
}
|
|
4011
4303
|
if (queryIds.length > 0) {
|
|
4012
4304
|
const uniqueIds = Array.from(new Set(queryIds));
|
|
4013
4305
|
const tPrice2 = performance.now();
|
|
4014
|
-
const productsWithPrice = await this.products.getProductsWithPrice(schedule_date, {
|
|
4015
|
-
scheduleModule: this.getSchedule(),
|
|
4016
|
-
schedule_datetime,
|
|
4017
|
-
customer_id
|
|
4018
|
-
}, {
|
|
4306
|
+
const productsWithPrice = await this.products.getProductsWithPrice(schedule_date, formatterContext, {
|
|
4019
4307
|
changedIds: options == null ? void 0 : options.changedIds,
|
|
4020
4308
|
productIds: uniqueIds
|
|
4021
4309
|
});
|
|
@@ -4036,7 +4324,7 @@ var Server = class {
|
|
|
4036
4324
|
});
|
|
4037
4325
|
return {
|
|
4038
4326
|
code: 200,
|
|
4039
|
-
data:
|
|
4327
|
+
data: this.buildProductQueryResultPayload(extensionFilteredProducts),
|
|
4040
4328
|
message: "",
|
|
4041
4329
|
status: true
|
|
4042
4330
|
};
|
|
@@ -4044,9 +4332,7 @@ var Server = class {
|
|
|
4044
4332
|
if (product_id != null && Number.isFinite(Number(product_id))) {
|
|
4045
4333
|
const pid = Number(product_id);
|
|
4046
4334
|
const tPrice2 = performance.now();
|
|
4047
|
-
const allProductsWithPrice = await this.products.getProductsWithPrice(schedule_date, {
|
|
4048
|
-
scheduleModule: this.getSchedule()
|
|
4049
|
-
}, {
|
|
4335
|
+
const allProductsWithPrice = await this.products.getProductsWithPrice(schedule_date, formatterContext, {
|
|
4050
4336
|
changedIds: options == null ? void 0 : options.changedIds
|
|
4051
4337
|
});
|
|
4052
4338
|
(0, import_product.perfMark)("computeQuery.getProductsWithPrice(single)", performance.now() - tPrice2, {
|
|
@@ -4076,11 +4362,7 @@ var Server = class {
|
|
|
4076
4362
|
}
|
|
4077
4363
|
if (this.shouldQueryProductsByExtensionTypes(extension_type)) {
|
|
4078
4364
|
const tPrice2 = performance.now();
|
|
4079
|
-
let filteredProducts2 = await this.products.getProductsWithPrice(schedule_date, {
|
|
4080
|
-
scheduleModule: this.getSchedule(),
|
|
4081
|
-
schedule_datetime,
|
|
4082
|
-
customer_id
|
|
4083
|
-
}, {
|
|
4365
|
+
let filteredProducts2 = await this.products.getProductsWithPrice(schedule_date, formatterContext, {
|
|
4084
4366
|
changedIds: options == null ? void 0 : options.changedIds
|
|
4085
4367
|
});
|
|
4086
4368
|
(0, import_product.perfMark)("computeQuery.getProductsWithPrice(extensionType)", performance.now() - tPrice2, {
|
|
@@ -4120,18 +4402,18 @@ var Server = class {
|
|
|
4120
4402
|
});
|
|
4121
4403
|
return {
|
|
4122
4404
|
code: 200,
|
|
4123
|
-
data:
|
|
4405
|
+
data: this.buildProductQueryResultPayload(filteredProducts2),
|
|
4124
4406
|
message: "",
|
|
4125
4407
|
status: true
|
|
4126
4408
|
};
|
|
4127
4409
|
}
|
|
4128
4410
|
if (!this.menu) {
|
|
4129
4411
|
this.logError("computeProductQueryResult: Menu 模块未注册");
|
|
4130
|
-
return { message: "Menu 模块未注册", data:
|
|
4412
|
+
return { message: "Menu 模块未注册", data: this.buildProductQueryResultPayload([], 0) };
|
|
4131
4413
|
}
|
|
4132
4414
|
if (!this.schedule) {
|
|
4133
4415
|
this.logError("computeProductQueryResult: Schedule 模块未注册");
|
|
4134
|
-
return { message: "Schedule 模块未注册", data:
|
|
4416
|
+
return { message: "Schedule 模块未注册", data: this.buildProductQueryResultPayload([], 0) };
|
|
4135
4417
|
}
|
|
4136
4418
|
let activeMenuList = [];
|
|
4137
4419
|
if (menu_list_ids && Array.isArray(menu_list_ids) && menu_list_ids.length > 0) {
|
|
@@ -4155,11 +4437,7 @@ var Server = class {
|
|
|
4155
4437
|
isAllProducts: !!productScope.isAllProducts
|
|
4156
4438
|
});
|
|
4157
4439
|
const tPrice = performance.now();
|
|
4158
|
-
let filteredProducts = scopedProductIds.length > 0 ? await this.products.getProductsWithPrice(schedule_date, {
|
|
4159
|
-
scheduleModule: this.getSchedule(),
|
|
4160
|
-
schedule_datetime,
|
|
4161
|
-
customer_id
|
|
4162
|
-
}, {
|
|
4440
|
+
let filteredProducts = scopedProductIds.length > 0 ? await this.products.getProductsWithPrice(schedule_date, formatterContext, {
|
|
4163
4441
|
changedIds: options == null ? void 0 : options.changedIds,
|
|
4164
4442
|
productIds: productScope.isAllProducts ? void 0 : scopedProductIds
|
|
4165
4443
|
}) : [];
|
|
@@ -4202,11 +4480,29 @@ var Server = class {
|
|
|
4202
4480
|
});
|
|
4203
4481
|
return {
|
|
4204
4482
|
code: 200,
|
|
4205
|
-
data:
|
|
4483
|
+
data: this.buildProductQueryResultPayload(filteredProducts),
|
|
4206
4484
|
message: "",
|
|
4207
4485
|
status: true
|
|
4208
4486
|
};
|
|
4209
4487
|
}
|
|
4488
|
+
/**
|
|
4489
|
+
* 构建商品格式化上下文。
|
|
4490
|
+
*
|
|
4491
|
+
* 智能定价条件使用全量 menuList/scheduleList;Product Query 顶层参数只保留筛选商品集合所需字段。
|
|
4492
|
+
*/
|
|
4493
|
+
buildProductFormatterContext(context) {
|
|
4494
|
+
var _a, _b, _c, _d;
|
|
4495
|
+
const scheduleModule = this.getSchedule();
|
|
4496
|
+
return {
|
|
4497
|
+
scheduleModule,
|
|
4498
|
+
schedule_datetime: context.schedule_datetime,
|
|
4499
|
+
customer_id: context.customer_id,
|
|
4500
|
+
strategy_context: context.strategy_context,
|
|
4501
|
+
menuList: ((_b = (_a = this.menu) == null ? void 0 : _a.getMenuList) == null ? void 0 : _b.call(_a)) || [],
|
|
4502
|
+
scheduleList: ((_c = scheduleModule == null ? void 0 : scheduleModule.getScheduleList) == null ? void 0 : _c.call(scheduleModule)) || [],
|
|
4503
|
+
dataVariantEvaluator: (_d = this.core.context) == null ? void 0 : _d.dataVariantEvaluator
|
|
4504
|
+
};
|
|
4505
|
+
}
|
|
4210
4506
|
/**
|
|
4211
4507
|
* 数据变更后,遍历所有订阅者重新计算查询结果并通过 callback 推送
|
|
4212
4508
|
* 由 ProductsModule 的 onProductsSyncCompleted 事件触发
|
|
@@ -43,6 +43,16 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
43
43
|
*/
|
|
44
44
|
private logError;
|
|
45
45
|
private logWarning;
|
|
46
|
+
/**
|
|
47
|
+
* 在订单进入内存或 SQLite 前统一压缩子项强身份重复并补齐协议 UID。
|
|
48
|
+
* 仅记录计数与订单标识,不输出商品、预约、支付或客户明细。
|
|
49
|
+
*/
|
|
50
|
+
private normalizeOrderCollectionsForIngress;
|
|
51
|
+
/**
|
|
52
|
+
* incoming 决定权威成员集合;同一持久化行仍从 existing 补齐 incoming 省略的本地展示字段。
|
|
53
|
+
*/
|
|
54
|
+
private mergeAuthoritativeOrderCollection;
|
|
55
|
+
private reconcileOverwriteOrderCollections;
|
|
46
56
|
/**
|
|
47
57
|
* 记录订单最近一次 SQLite 写入,供 pubsub 回声去重使用。
|
|
48
58
|
*
|
|
@@ -212,10 +222,6 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
212
222
|
private findOrderIndexByIdentity;
|
|
213
223
|
private getOrderCompletenessScore;
|
|
214
224
|
private pickPreferredOrder;
|
|
215
|
-
private getProductIdentityKeys;
|
|
216
|
-
private mergeOrderProductLists;
|
|
217
|
-
private getPaymentMergeKey;
|
|
218
|
-
private mergeOrderPaymentLists;
|
|
219
225
|
private mergeOrderRecords;
|
|
220
226
|
private summarizeDuplicateOrders;
|
|
221
227
|
private logDuplicateOrders;
|