@pisell/pisellos 2.2.191 → 2.2.193
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/walletPass/utils.js +7 -4
- package/dist/modules/Order/index.d.ts +12 -10
- package/dist/modules/Order/index.js +462 -571
- package/dist/modules/Order/types.d.ts +5 -5
- package/dist/modules/Order/utils.js +3 -3
- package/dist/modules/Payment/utils.js +2 -1
- package/dist/modules/SalesSummary/utils.js +1 -1
- package/dist/server/index.d.ts +8 -1
- package/dist/server/index.js +651 -464
- package/dist/server/modules/order/index.d.ts +4 -70
- package/dist/server/modules/order/index.js +336 -747
- package/dist/server/modules/products/index.d.ts +0 -57
- package/dist/server/modules/products/index.js +347 -706
- package/dist/solution/BaseSales/index.d.ts +2 -1
- package/dist/solution/BaseSales/index.js +116 -122
- package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +0 -1
- package/dist/solution/BookingByStep/index.d.ts +1 -1
- package/dist/solution/BookingTicket/index.d.ts +1 -1
- package/dist/solution/ScanOrder/index.js +3 -1
- package/lib/model/strategy/adapter/promotion/index.js +49 -0
- package/lib/model/strategy/adapter/walletPass/utils.js +3 -2
- package/lib/modules/Order/index.d.ts +12 -10
- package/lib/modules/Order/index.js +94 -118
- package/lib/modules/Order/types.d.ts +5 -5
- package/lib/modules/Order/utils.js +4 -4
- package/lib/modules/Payment/utils.js +2 -1
- package/lib/modules/SalesSummary/utils.js +1 -3
- package/lib/server/index.d.ts +8 -1
- package/lib/server/index.js +143 -24
- package/lib/server/modules/order/index.d.ts +4 -70
- package/lib/server/modules/order/index.js +31 -391
- package/lib/server/modules/products/index.d.ts +0 -57
- package/lib/server/modules/products/index.js +0 -333
- package/lib/solution/BaseSales/index.d.ts +2 -1
- package/lib/solution/BaseSales/index.js +53 -16
- package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +0 -1
- package/lib/solution/BookingByStep/index.d.ts +1 -1
- package/lib/solution/BookingTicket/index.d.ts +1 -1
- package/lib/solution/ScanOrder/index.js +3 -1
- package/package.json +1 -1
package/lib/server/index.js
CHANGED
|
@@ -452,34 +452,55 @@ var Server = class {
|
|
|
452
452
|
};
|
|
453
453
|
}
|
|
454
454
|
};
|
|
455
|
+
this.handleOrderSalesCheckout = async ({ data }) => {
|
|
456
|
+
return this.handleOrderCheckoutSubmit({
|
|
457
|
+
backendPath: "/shop/order/sales/checkout",
|
|
458
|
+
data,
|
|
459
|
+
title: "handleOrderSalesCheckout"
|
|
460
|
+
});
|
|
461
|
+
};
|
|
462
|
+
this.handleOrderCheckout = async ({ data }) => {
|
|
463
|
+
return this.handleOrderCheckoutSubmit({
|
|
464
|
+
backendPath: "/order/checkout",
|
|
465
|
+
data,
|
|
466
|
+
title: "handleOrderCheckout"
|
|
467
|
+
});
|
|
468
|
+
};
|
|
455
469
|
this.handleOrderSalesDetail = async ({ url, data, path }) => {
|
|
456
470
|
var _a;
|
|
457
471
|
const requestPath = this.parseRequestPath(url, path);
|
|
458
|
-
const
|
|
459
|
-
this.logInfo("handleOrderSalesDetail: 开始处理", { url, path: requestPath,
|
|
460
|
-
if (!
|
|
461
|
-
this.logWarning("handleOrderSalesDetail:
|
|
462
|
-
return { code: 400, status: false, message: "
|
|
472
|
+
const lookup = this.extractOrderSalesDetailLookup(requestPath);
|
|
473
|
+
this.logInfo("handleOrderSalesDetail: 开始处理", { url, path: requestPath, lookup });
|
|
474
|
+
if (!lookup) {
|
|
475
|
+
this.logWarning("handleOrderSalesDetail: lookup 缺失", { url, path: requestPath });
|
|
476
|
+
return { code: 400, status: false, message: "订单 lookup 缺失", data: null };
|
|
463
477
|
}
|
|
464
478
|
if (!this.order) {
|
|
465
479
|
this.logError("handleOrderSalesDetail: Order 模块未注册");
|
|
466
480
|
return { code: 500, status: false, message: "Order 模块未注册", data: null };
|
|
467
481
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
482
|
+
if (!this.shouldForceRemoteSalesDetail(data)) {
|
|
483
|
+
const localOrder = await this.order.getLocalOrderByLookup(lookup);
|
|
484
|
+
if (localOrder) {
|
|
485
|
+
this.logInfo("handleOrderSalesDetail: 命中本地订单", { lookup });
|
|
486
|
+
return {
|
|
487
|
+
code: 200,
|
|
488
|
+
status: true,
|
|
489
|
+
message: "",
|
|
490
|
+
data: localOrder
|
|
491
|
+
};
|
|
492
|
+
}
|
|
477
493
|
}
|
|
478
494
|
if (!((_a = this.app) == null ? void 0 : _a.request)) {
|
|
479
495
|
this.logError("handleOrderSalesDetail: app.request 不可用");
|
|
480
|
-
return {
|
|
496
|
+
return {
|
|
497
|
+
code: 500,
|
|
498
|
+
status: false,
|
|
499
|
+
message: "app.request 不可用",
|
|
500
|
+
data: null
|
|
501
|
+
};
|
|
481
502
|
}
|
|
482
|
-
const backendPath = this.buildOrderSalesDetailBackendPath(
|
|
503
|
+
const backendPath = this.buildOrderSalesDetailBackendPath(lookup, data);
|
|
483
504
|
try {
|
|
484
505
|
const response = await this.app.request.get(backendPath, {
|
|
485
506
|
lookup_mode: "multi"
|
|
@@ -491,7 +512,7 @@ var Server = class {
|
|
|
491
512
|
const fresh = (response == null ? void 0 : response.data) ?? response;
|
|
492
513
|
if (!fresh || typeof fresh !== "object" || fresh.order_id == null) {
|
|
493
514
|
this.logError("handleOrderSalesDetail: 后端返回订单为空", {
|
|
494
|
-
|
|
515
|
+
lookup,
|
|
495
516
|
backendPath
|
|
496
517
|
});
|
|
497
518
|
return {
|
|
@@ -502,9 +523,9 @@ var Server = class {
|
|
|
502
523
|
};
|
|
503
524
|
}
|
|
504
525
|
await this.order.upsertOrdersFromRemote([fresh]);
|
|
505
|
-
const savedOrder = await this.order.
|
|
526
|
+
const savedOrder = await this.order.getLocalOrderByLookup(lookup);
|
|
506
527
|
if (!savedOrder) {
|
|
507
|
-
this.logError("handleOrderSalesDetail: 订单写入后回读失败", {
|
|
528
|
+
this.logError("handleOrderSalesDetail: 订单写入后回读失败", { lookup });
|
|
508
529
|
return {
|
|
509
530
|
code: 500,
|
|
510
531
|
status: false,
|
|
@@ -512,7 +533,7 @@ var Server = class {
|
|
|
512
533
|
data: null
|
|
513
534
|
};
|
|
514
535
|
}
|
|
515
|
-
this.logInfo("handleOrderSalesDetail: 远端订单已同步到本地", {
|
|
536
|
+
this.logInfo("handleOrderSalesDetail: 远端订单已同步到本地", { lookup });
|
|
516
537
|
return {
|
|
517
538
|
code: 200,
|
|
518
539
|
status: true,
|
|
@@ -522,7 +543,7 @@ var Server = class {
|
|
|
522
543
|
} catch (error) {
|
|
523
544
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
524
545
|
this.logError("handleOrderSalesDetail: 请求失败", {
|
|
525
|
-
|
|
546
|
+
lookup,
|
|
526
547
|
backendPath,
|
|
527
548
|
error: errorMessage
|
|
528
549
|
});
|
|
@@ -1240,6 +1261,16 @@ var Server = class {
|
|
|
1240
1261
|
method: "get",
|
|
1241
1262
|
path: "/update/localOrder",
|
|
1242
1263
|
handler: this.handleUpdateLocalOrder.bind(this)
|
|
1264
|
+
},
|
|
1265
|
+
{
|
|
1266
|
+
method: "post",
|
|
1267
|
+
path: "/shop/order/sales/checkout",
|
|
1268
|
+
handler: this.handleOrderSalesCheckout.bind(this)
|
|
1269
|
+
},
|
|
1270
|
+
{
|
|
1271
|
+
method: "post",
|
|
1272
|
+
path: "/shop/order/checkout",
|
|
1273
|
+
handler: this.handleOrderCheckout.bind(this)
|
|
1243
1274
|
}
|
|
1244
1275
|
]);
|
|
1245
1276
|
this.registerPrefixRoutes([
|
|
@@ -1707,6 +1738,49 @@ var Server = class {
|
|
|
1707
1738
|
};
|
|
1708
1739
|
}
|
|
1709
1740
|
}
|
|
1741
|
+
async handleOrderCheckoutSubmit(params) {
|
|
1742
|
+
var _a;
|
|
1743
|
+
const { backendPath, data, title } = params;
|
|
1744
|
+
this.logInfo(`${title}: 开始处理`, {
|
|
1745
|
+
backendPath,
|
|
1746
|
+
order_id: data == null ? void 0 : data.order_id,
|
|
1747
|
+
external_sale_number: data == null ? void 0 : data.external_sale_number,
|
|
1748
|
+
order_number: data == null ? void 0 : data.order_number
|
|
1749
|
+
});
|
|
1750
|
+
if (!((_a = this.app) == null ? void 0 : _a.request)) {
|
|
1751
|
+
this.logError(`${title}: app.request 不可用`);
|
|
1752
|
+
return { code: 500, status: false, message: "app.request 不可用", data: null };
|
|
1753
|
+
}
|
|
1754
|
+
try {
|
|
1755
|
+
const response = await this.app.request.post(backendPath, data, {
|
|
1756
|
+
isShopApi: true,
|
|
1757
|
+
customToast: () => {
|
|
1758
|
+
}
|
|
1759
|
+
});
|
|
1760
|
+
const fresh = this.extractOrderDataFromCheckoutResponse(response);
|
|
1761
|
+
if (fresh && this.order) {
|
|
1762
|
+
await this.order.upsertOrdersFromRemote([fresh]);
|
|
1763
|
+
this.logInfo(`${title}: 订单已同步到本地`, {
|
|
1764
|
+
order_id: fresh.order_id,
|
|
1765
|
+
external_sale_number: fresh.external_sale_number,
|
|
1766
|
+
order_number: fresh.order_number
|
|
1767
|
+
});
|
|
1768
|
+
} else {
|
|
1769
|
+
this.logWarning(`${title}: checkout 返回未包含可同步订单`, {
|
|
1770
|
+
hasOrderModule: !!this.order,
|
|
1771
|
+
backendPath
|
|
1772
|
+
});
|
|
1773
|
+
}
|
|
1774
|
+
return this.normalizeCheckoutResponse(response);
|
|
1775
|
+
} catch (error) {
|
|
1776
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1777
|
+
this.logError(`${title}: 请求失败`, { backendPath, error: errorMessage });
|
|
1778
|
+
const backendError = this.extractBackendErrorResponse(error);
|
|
1779
|
+
if (backendError)
|
|
1780
|
+
return backendError;
|
|
1781
|
+
return { code: 500, status: false, message: errorMessage, data: null };
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1710
1784
|
/**
|
|
1711
1785
|
* 解析 order_ids 入参,兼容 url query / data 字段、字符串(csv) / 数组两种形态。
|
|
1712
1786
|
* 自动 trim、去空、按字符串去重,输出归一化后的字符串数组。
|
|
@@ -1859,12 +1933,15 @@ var Server = class {
|
|
|
1859
1933
|
return null;
|
|
1860
1934
|
}
|
|
1861
1935
|
}
|
|
1862
|
-
|
|
1936
|
+
extractOrderSalesDetailLookup(url) {
|
|
1863
1937
|
const path = this.parseRequestPath(url);
|
|
1864
1938
|
const match = path.match(/^\/shop\/order\/sales\/([^/?#]+)$/);
|
|
1865
1939
|
return (match == null ? void 0 : match[1]) ? decodeURIComponent(match[1]) : null;
|
|
1866
1940
|
}
|
|
1867
|
-
|
|
1941
|
+
shouldForceRemoteSalesDetail(data) {
|
|
1942
|
+
return (data == null ? void 0 : data.forceRemote) === true || (data == null ? void 0 : data.force_remote) === true;
|
|
1943
|
+
}
|
|
1944
|
+
buildOrderSalesDetailBackendPath(lookup, data) {
|
|
1868
1945
|
const rawWith = data && typeof data === "object" ? data.with : void 0;
|
|
1869
1946
|
const withFields = Array.isArray(rawWith) && rawWith.length > 0 ? rawWith : ["products", "scheduleEvents"];
|
|
1870
1947
|
const searchParams = new URLSearchParams();
|
|
@@ -1875,7 +1952,49 @@ var Server = class {
|
|
|
1875
1952
|
});
|
|
1876
1953
|
searchParams.append("lookup_mode", "multi");
|
|
1877
1954
|
const query = searchParams.toString();
|
|
1878
|
-
return `/shop/order/sales/${encodeURIComponent(
|
|
1955
|
+
return `/shop/order/sales/${encodeURIComponent(lookup)}${query ? `?${query}` : ""}`;
|
|
1956
|
+
}
|
|
1957
|
+
extractOrderDataFromCheckoutResponse(response) {
|
|
1958
|
+
var _a, _b;
|
|
1959
|
+
const candidates = [
|
|
1960
|
+
(_a = response == null ? void 0 : response.data) == null ? void 0 : _a.order,
|
|
1961
|
+
(_b = response == null ? void 0 : response.data) == null ? void 0 : _b.sales,
|
|
1962
|
+
response == null ? void 0 : response.data,
|
|
1963
|
+
response == null ? void 0 : response.order,
|
|
1964
|
+
response == null ? void 0 : response.sales,
|
|
1965
|
+
response
|
|
1966
|
+
];
|
|
1967
|
+
for (const candidate of candidates) {
|
|
1968
|
+
if (!candidate || typeof candidate !== "object")
|
|
1969
|
+
continue;
|
|
1970
|
+
if (candidate.order_id !== void 0 && candidate.order_id !== null) {
|
|
1971
|
+
return candidate;
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
return null;
|
|
1975
|
+
}
|
|
1976
|
+
normalizeCheckoutResponse(response) {
|
|
1977
|
+
if (response && typeof response === "object" && (response.code !== void 0 || response.status !== void 0)) {
|
|
1978
|
+
return response;
|
|
1979
|
+
}
|
|
1980
|
+
return {
|
|
1981
|
+
code: 200,
|
|
1982
|
+
status: true,
|
|
1983
|
+
message: "",
|
|
1984
|
+
data: response
|
|
1985
|
+
};
|
|
1986
|
+
}
|
|
1987
|
+
extractBackendErrorResponse(error) {
|
|
1988
|
+
var _a, _b;
|
|
1989
|
+
const candidates = [
|
|
1990
|
+
(_a = error == null ? void 0 : error.response) == null ? void 0 : _a.data,
|
|
1991
|
+
error == null ? void 0 : error.data,
|
|
1992
|
+
(_b = error == null ? void 0 : error.response) == null ? void 0 : _b.body,
|
|
1993
|
+
error == null ? void 0 : error.body
|
|
1994
|
+
];
|
|
1995
|
+
return candidates.find(
|
|
1996
|
+
(candidate) => candidate && typeof candidate === "object"
|
|
1997
|
+
) || null;
|
|
1879
1998
|
}
|
|
1880
1999
|
/**
|
|
1881
2000
|
* 从 url 或路由 path 解析 pathname(不含 query,去掉末尾 /)
|
|
@@ -2,44 +2,6 @@ import { Module, ModuleOptions, PisellCore } from '../../../types';
|
|
|
2
2
|
import { BaseModule } from '../../../modules/BaseModule';
|
|
3
3
|
import type { RouteDefinition } from '../../types';
|
|
4
4
|
import { OrderData, OrderId } from './types';
|
|
5
|
-
/** 订单模块流程调试日志条目 */
|
|
6
|
-
interface OrderFlowLogEntry {
|
|
7
|
-
ts: string;
|
|
8
|
-
step: string;
|
|
9
|
-
metadata?: Record<string, unknown>;
|
|
10
|
-
}
|
|
11
|
-
/** 单笔订单 SQLite 写入记录 */
|
|
12
|
-
interface OrderWriteStatEntry {
|
|
13
|
-
ts: string;
|
|
14
|
-
writeSeq: number;
|
|
15
|
-
source: string;
|
|
16
|
-
writeMethod: string;
|
|
17
|
-
orderId: OrderId | null;
|
|
18
|
-
storageKey: string;
|
|
19
|
-
mergeAction?: 'insert' | 'update' | 'snapshot' | 'singleUpdate';
|
|
20
|
-
}
|
|
21
|
-
declare global {
|
|
22
|
-
interface Window {
|
|
23
|
-
/** 订单模块流程调试日志,可在 DevTools 直接查看 */
|
|
24
|
-
__orderModuleFlowLogs?: OrderFlowLogEntry[];
|
|
25
|
-
/** 按 storageKey 聚合的 SQLite 写入次数,便于排查重复写 */
|
|
26
|
-
__orderModuleWriteStats?: Record<string, OrderWriteStatEntry[]>;
|
|
27
|
-
/** 清空订单流程调试日志 */
|
|
28
|
-
clearOrderModuleFlowLogs?: () => void;
|
|
29
|
-
/** 导出订单流程调试日志 JSON 字符串 */
|
|
30
|
-
exportOrderModuleFlowLogs?: () => string;
|
|
31
|
-
/** 导出按订单聚合的写入统计 */
|
|
32
|
-
exportOrderModuleWriteStats?: () => string;
|
|
33
|
-
/** 汇总写入次数 Top N(默认 20) */
|
|
34
|
-
summarizeOrderModuleWrites?: (topN?: number) => Array<{
|
|
35
|
-
storageKey: string;
|
|
36
|
-
orderId: OrderId | null;
|
|
37
|
-
writeCount: number;
|
|
38
|
-
sources: string[];
|
|
39
|
-
lastWriteAt: string;
|
|
40
|
-
}>;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
5
|
/**
|
|
44
6
|
* Order 模块 - 基础框架
|
|
45
7
|
*/
|
|
@@ -56,10 +18,7 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
56
18
|
private resourceIdIndex;
|
|
57
19
|
private logger;
|
|
58
20
|
private storage;
|
|
59
|
-
private orderSQLiteSaveQueue;
|
|
60
|
-
/** 全局递增的 SQLite 写入序号,便于日志关联同一次操作 */
|
|
61
|
-
private orderFlowWriteSeq;
|
|
62
|
-
/** 按 storageKey 记录最近一次 SQLite 写入来源与时间,用于去重 */
|
|
21
|
+
private orderSQLiteSaveQueue; /** 按 storageKey 记录最近一次 SQLite 写入来源与时间,用于去重 */
|
|
63
22
|
private recentSqliteWriteByStorageKey;
|
|
64
23
|
/** 最近一次 SSE 全量拉取完成时间 */
|
|
65
24
|
private lastServerFullFetchAtMs;
|
|
@@ -77,31 +36,6 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
77
36
|
* @param metadata 日志元数据
|
|
78
37
|
*/
|
|
79
38
|
private logError;
|
|
80
|
-
/**
|
|
81
|
-
* 初始化 window 上的订单流程调试日志数组及辅助方法。
|
|
82
|
-
*
|
|
83
|
-
* @example
|
|
84
|
-
* window.clearOrderModuleFlowLogs()
|
|
85
|
-
* // 操作完成后:
|
|
86
|
-
* copy(window.exportOrderModuleFlowLogs?.() || '[]')
|
|
87
|
-
*/
|
|
88
|
-
private initOrderFlowLogs;
|
|
89
|
-
/**
|
|
90
|
-
* 写入 window 订单流程调试日志。
|
|
91
|
-
*
|
|
92
|
-
* @example
|
|
93
|
-
* this.pushOrderFlowLog('mergeOrdersToStore.start', { count: 3 })
|
|
94
|
-
*/
|
|
95
|
-
private pushOrderFlowLog;
|
|
96
|
-
/** 当前内存 store 快照信息,供流程日志使用 */
|
|
97
|
-
private getOrderStoreSnapshot;
|
|
98
|
-
/**
|
|
99
|
-
* 记录一次 SQLite 写入到 window 统计,用于排查同一订单被多次写入的原因。
|
|
100
|
-
*
|
|
101
|
-
* @example
|
|
102
|
-
* this.trackOrderWrite('upsertOrdersFromRemote', 'bulkUpdate', orders, 'insert')
|
|
103
|
-
*/
|
|
104
|
-
private trackOrderWrite;
|
|
105
39
|
/**
|
|
106
40
|
* 记录订单最近一次 SQLite 写入,供 pubsub 回声去重使用。
|
|
107
41
|
*
|
|
@@ -135,9 +69,9 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
135
69
|
preload(): Promise<void>;
|
|
136
70
|
getOrders(): OrderData[];
|
|
137
71
|
getOrderById(id: OrderId): OrderData | undefined;
|
|
138
|
-
/** 按 order_id
|
|
72
|
+
/** 按 order_id 查询内存订单。 */
|
|
139
73
|
getOrderByOrderId(orderId: OrderId): OrderData | undefined;
|
|
140
|
-
|
|
74
|
+
getLocalOrderByLookup(lookup: OrderId): Promise<OrderData | null>;
|
|
141
75
|
loadOrdersByServer(): Promise<OrderData[]>;
|
|
142
76
|
/**
|
|
143
77
|
* 静默全量刷新:后台重新拉取全量 SSE 订单数据并更新本地
|
|
@@ -218,6 +152,7 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
218
152
|
private normalizeOrderSyncPayload;
|
|
219
153
|
private uniqueOrderIds;
|
|
220
154
|
private getIdKey;
|
|
155
|
+
private isOrderLookupMatch;
|
|
221
156
|
/**
|
|
222
157
|
* 解析订单 SQLite 主键,规则与宿主 OrderDataSource.getOrderStorageKey 一致。
|
|
223
158
|
*
|
|
@@ -275,4 +210,3 @@ export declare class OrderModule extends BaseModule implements Module {
|
|
|
275
210
|
*/
|
|
276
211
|
clear(): Promise<void>;
|
|
277
212
|
}
|
|
278
|
-
export {};
|