ts-glitter 21.3.8 → 21.3.9
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/lowcode/Entry.js +1 -1
- package/lowcode/Entry.ts +1 -1
- package/lowcode/backend-manager/bg-line.js +12 -1
- package/lowcode/backend-manager/bg-line.ts +16 -1
- package/lowcode/backend-manager/bg-notify.js +13 -2
- package/lowcode/backend-manager/bg-notify.ts +17 -2
- package/lowcode/backend-manager/bg-product.js +81 -30
- package/lowcode/backend-manager/bg-product.ts +95 -34
- package/lowcode/backend-manager/bg-recommend.js +109 -141
- package/lowcode/backend-manager/bg-recommend.ts +122 -144
- package/lowcode/backend-manager/bg-sns.js +14 -4
- package/lowcode/backend-manager/bg-sns.ts +18 -4
- package/lowcode/backend-manager/bg-widget.js +176 -12
- package/lowcode/backend-manager/bg-widget.ts +198 -13
- package/lowcode/cms-plugin/auto-fcm-advertise.js +13 -2
- package/lowcode/cms-plugin/auto-fcm-advertise.ts +16 -2
- package/lowcode/cms-plugin/auto-fcm-history.js +13 -2
- package/lowcode/cms-plugin/auto-fcm-history.ts +16 -2
- package/lowcode/cms-plugin/model/order.d.ts +1 -0
- package/lowcode/cms-plugin/module/order-excel.js +18 -2
- package/lowcode/cms-plugin/module/order-excel.ts +20 -9
- package/lowcode/cms-plugin/module/product-setting.js +2 -1
- package/lowcode/cms-plugin/module/product-setting.ts +2 -1
- package/lowcode/cms-plugin/module/user-excel.js +1 -1
- package/lowcode/cms-plugin/module/user-excel.ts +2 -2
- package/lowcode/cms-plugin/pos-pages/payment-page.js +3 -2
- package/lowcode/cms-plugin/pos-pages/payment-page.ts +11 -5
- package/lowcode/cms-plugin/pos-pages/products-page.ts +0 -1
- package/lowcode/cms-plugin/shopping-allowance-manager.js +3 -2
- package/lowcode/cms-plugin/shopping-allowance-manager.ts +3 -2
- package/lowcode/cms-plugin/shopping-discount-setting.js +2 -0
- package/lowcode/cms-plugin/shopping-discount-setting.ts +2 -0
- package/lowcode/cms-plugin/shopping-invoice-manager.js +7 -4
- package/lowcode/cms-plugin/shopping-invoice-manager.ts +12 -11
- package/lowcode/cms-plugin/shopping-order-manager.js +21 -4
- package/lowcode/cms-plugin/shopping-order-manager.ts +30 -11
- package/lowcode/cms-plugin/shopping-product-setting.js +45 -41
- package/lowcode/cms-plugin/shopping-product-setting.ts +55 -48
- package/lowcode/cms-plugin/shopping-rebate.js +52 -46
- package/lowcode/cms-plugin/shopping-rebate.ts +402 -396
- package/lowcode/cms-plugin/shopping-setting-advance.js +6 -6
- package/lowcode/cms-plugin/shopping-setting-advance.ts +7 -7
- package/lowcode/cms-plugin/shopping-setting-basic.js +44 -0
- package/lowcode/cms-plugin/shopping-setting-basic.ts +63 -1
- package/lowcode/cms-plugin/shopping-setting-stock-log.js +57 -0
- package/lowcode/cms-plugin/shopping-setting-stock-log.ts +101 -0
- package/lowcode/cms-plugin/user-list.js +10 -9
- package/lowcode/cms-plugin/user-list.ts +11 -8
- package/lowcode/css/editor.css +1 -1
- package/lowcode/form-view/editor/image-selector.js +83 -82
- package/lowcode/form-view/editor/image-selector.ts +115 -107
- package/lowcode/glitter-base/route/user.js +27 -34
- package/lowcode/glitter-base/route/user.ts +31 -40
- package/lowcode/glitterBundle/dialog/ShareDialog.js +1 -0
- package/lowcode/glitterBundle/dialog/ShareDialog.ts +2 -0
- package/lowcode/glitterBundle/dialog/dialog.js +2 -2
- package/lowcode/glitterBundle/dialog/dialog.ts +2 -2
- package/lowcode/glitterBundle/plugins/editor-elem.js +5 -11
- package/lowcode/glitterBundle/plugins/editor-elem.ts +11 -11
- package/lowcode/modules/image-library.js +836 -486
- package/lowcode/modules/image-library.ts +1760 -1418
- package/lowcode/modules/tool.js +10 -9
- package/lowcode/modules/tool.ts +11 -10
- package/lowcode/public-models/product.ts +13 -0
- package/nxv0ptv53w.json +1 -0
- package/package.json +1 -1
- package/src/api-public/controllers/shop.js +2 -2
- package/src/api-public/controllers/shop.js.map +1 -1
- package/src/api-public/controllers/shop.ts +5 -2
- package/src/api-public/controllers/stock.js +1 -1
- package/src/api-public/controllers/stock.js.map +1 -1
- package/src/api-public/controllers/stock.ts +93 -81
- package/src/api-public/models/glitter-finance.js +2 -1
- package/src/api-public/models/glitter-finance.js.map +1 -1
- package/src/api-public/services/checkout-event.js +1 -0
- package/src/api-public/services/checkout-event.js.map +1 -1
- package/src/api-public/services/checkout-event.ts +2 -2
- package/src/api-public/services/data-analyze.d.ts +1 -1
- package/src/api-public/services/diff-record.d.ts +25 -0
- package/src/api-public/services/diff-record.js +158 -0
- package/src/api-public/services/diff-record.js.map +1 -0
- package/src/api-public/services/diff-record.ts +217 -0
- package/src/api-public/services/ezpay/tool.d.ts +1 -0
- package/src/api-public/services/financial-serviceV2.js +7 -17
- package/src/api-public/services/financial-serviceV2.js.map +1 -1
- package/src/api-public/services/public-table-check.js +25 -7
- package/src/api-public/services/public-table-check.js.map +1 -1
- package/src/api-public/services/public-table-check.ts +53 -31
- package/src/api-public/services/shopping.d.ts +2 -12
- package/src/api-public/services/shopping.js +16 -7
- package/src/api-public/services/shopping.js.map +1 -1
- package/src/api-public/services/shopping.ts +33 -7
- package/src/api-public/services/stock.d.ts +1 -1
- package/src/api-public/services/stock.js +19 -17
- package/src/api-public/services/stock.js.map +1 -1
- package/src/api-public/services/stock.ts +711 -696
- package/src/api-public/services/user.d.ts +1 -1
- package/src/api-public/services/user.js +18 -8
- package/src/api-public/services/user.js.map +1 -1
- package/src/api-public/services/user.ts +34 -27
- package/src/app-project/serverless/src/index.js +7 -17
- package/src/app-project/serverless/src/index.js.map +1 -1
- package/src/app-project/serverless/src/modules/CryptoJS.js +7 -17
- package/src/app-project/serverless/src/modules/CryptoJS.js.map +1 -1
- package/src/app-project/serverless/src/modules/database.d.ts +1 -1
- package/src/app-project/serverless/src/modules/redis.d.ts +1 -1
- package/src/app-project/serverless/src/modules/ssh.js +7 -17
- package/src/app-project/serverless/src/modules/ssh.js.map +1 -1
- package/src/firebase/message.js +2 -1
- package/src/firebase/message.js.map +1 -1
- package/src/helper/app_creater.js +2 -1
- package/src/helper/app_creater.js.map +1 -1
- package/src/helper/glitter-util.d.ts +1 -0
- package/src/index.js +17 -7
- package/src/index.js.map +5 -1
- package/src/lambda/interface.js +2 -2
- package/src/lambda/interface.js.map +1 -1
- package/src/modules/CryptoJS.js +7 -17
- package/src/modules/CryptoJS.js.map +1 -1
- package/src/modules/database.d.ts +1 -1
- package/src/modules/ssh.js +7 -17
- package/src/modules/ssh.js.map +1 -1
- package/src/modules/tool.d.ts +5 -0
- package/src/modules/tool.js +19 -0
- package/src/modules/tool.js.map +1 -1
- package/src/modules/tool.ts +27 -0
- package/src/run.js +2 -1
- package/src/run.js.map +1 -1
- package/src/services/saas-table-check.js +2 -2
- package/src/services/saas-table-check.js.map +1 -1
- package/src/services/ses.js +2 -1
- package/src/services/ses.js.map +1 -1
|
@@ -6,200 +6,200 @@ import { Shopping } from './shopping';
|
|
|
6
6
|
import { SharePermission } from './share-permission';
|
|
7
7
|
|
|
8
8
|
type StockList = {
|
|
9
|
-
|
|
9
|
+
[key: string]: { count: number };
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
export type StockHistoryType = 'restocking' | 'transfer' | 'checking';
|
|
13
13
|
|
|
14
14
|
type ContentProduct = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
variant_id: number;
|
|
16
|
+
cost: number;
|
|
17
|
+
note: string;
|
|
18
|
+
transfer_count: number; // 預計進貨數, 預計調入數
|
|
19
|
+
recent_count?: number; // 實際進貨數, 實際調入數
|
|
20
|
+
check_count: number; // 盤點數
|
|
21
|
+
replenishment_count?: number; // 此次補貨數
|
|
22
|
+
title?: string;
|
|
23
|
+
spec?: string;
|
|
24
|
+
sku?: '';
|
|
25
|
+
barcode?: '';
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
type StockHistoryData = {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
29
|
+
id: string;
|
|
30
|
+
type: StockHistoryType;
|
|
31
|
+
status: number;
|
|
32
|
+
order_id: string;
|
|
33
|
+
created_time: string;
|
|
34
|
+
content: {
|
|
35
|
+
vendor: string;
|
|
36
|
+
store_in: string; // 調入庫存點
|
|
37
|
+
store_out: string; // 調出庫存點、盤點庫存點
|
|
38
|
+
check_member: string; // 盤點人
|
|
39
|
+
check_according: '' | 'all' | 'collection' | 'product'; // 商品盤點類型
|
|
40
|
+
note: string;
|
|
41
|
+
total_price?: number;
|
|
42
|
+
product_list: ContentProduct[];
|
|
43
|
+
changeLogs: {
|
|
44
|
+
time: string;
|
|
45
|
+
text: string;
|
|
46
|
+
user: number;
|
|
47
|
+
status: number;
|
|
48
|
+
user_name?: string;
|
|
49
|
+
product_list?: ContentProduct[];
|
|
50
|
+
}[];
|
|
51
|
+
};
|
|
52
52
|
};
|
|
53
53
|
|
|
54
54
|
const typeConfig: {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
};
|
|
55
|
+
[key in StockHistoryType]: {
|
|
56
|
+
name: string;
|
|
57
|
+
prefixId: string;
|
|
58
|
+
status: {
|
|
59
|
+
[key in number]: {
|
|
60
|
+
title: string;
|
|
61
|
+
badge: string;
|
|
62
|
+
};
|
|
64
63
|
};
|
|
64
|
+
};
|
|
65
65
|
} = {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
},
|
|
66
|
+
restocking: {
|
|
67
|
+
name: '進貨',
|
|
68
|
+
prefixId: 'IC',
|
|
69
|
+
status: {
|
|
70
|
+
0: {
|
|
71
|
+
title: '已完成',
|
|
72
|
+
badge: 'info',
|
|
73
|
+
},
|
|
74
|
+
1: {
|
|
75
|
+
title: '已補貨',
|
|
76
|
+
badge: 'info',
|
|
77
|
+
},
|
|
78
|
+
2: {
|
|
79
|
+
title: '待進貨',
|
|
80
|
+
badge: 'warning',
|
|
81
|
+
},
|
|
82
|
+
3: {
|
|
83
|
+
title: '核對中',
|
|
84
|
+
badge: 'warning',
|
|
85
|
+
},
|
|
86
|
+
4: {
|
|
87
|
+
title: '已暫停',
|
|
88
|
+
badge: 'normal',
|
|
89
|
+
},
|
|
90
|
+
5: {
|
|
91
|
+
title: '待補貨',
|
|
92
|
+
badge: 'notify',
|
|
93
|
+
},
|
|
94
|
+
6: {
|
|
95
|
+
title: '已取消',
|
|
96
|
+
badge: 'notify',
|
|
97
|
+
},
|
|
99
98
|
},
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
99
|
+
},
|
|
100
|
+
transfer: {
|
|
101
|
+
name: '調撥',
|
|
102
|
+
prefixId: 'TB',
|
|
103
|
+
status: {
|
|
104
|
+
0: {
|
|
105
|
+
title: '已完成',
|
|
106
|
+
badge: 'info',
|
|
107
|
+
},
|
|
108
|
+
1: {
|
|
109
|
+
title: '已補貨',
|
|
110
|
+
badge: 'info',
|
|
111
|
+
},
|
|
112
|
+
2: {
|
|
113
|
+
title: '待調撥',
|
|
114
|
+
badge: 'warning',
|
|
115
|
+
},
|
|
116
|
+
3: {
|
|
117
|
+
title: '核對中',
|
|
118
|
+
badge: 'warning',
|
|
119
|
+
},
|
|
120
|
+
4: {
|
|
121
|
+
title: '已暫停',
|
|
122
|
+
badge: 'normal',
|
|
123
|
+
},
|
|
124
|
+
5: {
|
|
125
|
+
title: '待補貨',
|
|
126
|
+
badge: 'notify',
|
|
127
|
+
},
|
|
128
|
+
6: {
|
|
129
|
+
title: '已取消',
|
|
130
|
+
badge: 'notify',
|
|
131
|
+
},
|
|
133
132
|
},
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
133
|
+
},
|
|
134
|
+
checking: {
|
|
135
|
+
name: '盤點',
|
|
136
|
+
prefixId: 'PD',
|
|
137
|
+
status: {
|
|
138
|
+
0: {
|
|
139
|
+
title: '已完成',
|
|
140
|
+
badge: 'info',
|
|
141
|
+
},
|
|
142
|
+
1: {
|
|
143
|
+
title: '已修正',
|
|
144
|
+
badge: 'info',
|
|
145
|
+
},
|
|
146
|
+
2: {
|
|
147
|
+
title: '待盤點',
|
|
148
|
+
badge: 'warning',
|
|
149
|
+
},
|
|
150
|
+
3: {
|
|
151
|
+
title: '盤點中',
|
|
152
|
+
badge: 'warning',
|
|
153
|
+
},
|
|
154
|
+
4: {
|
|
155
|
+
title: '已暫停',
|
|
156
|
+
badge: 'normal',
|
|
157
|
+
},
|
|
158
|
+
5: {
|
|
159
|
+
title: '異常',
|
|
160
|
+
badge: 'notify',
|
|
161
|
+
},
|
|
162
|
+
6: {
|
|
163
|
+
title: '已取消',
|
|
164
|
+
badge: 'notify',
|
|
165
|
+
},
|
|
167
166
|
},
|
|
167
|
+
},
|
|
168
168
|
};
|
|
169
169
|
|
|
170
170
|
export class Stock {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
171
|
+
public app;
|
|
172
|
+
public token;
|
|
173
|
+
|
|
174
|
+
constructor(app: string, token?: IToken) {
|
|
175
|
+
this.app = app;
|
|
176
|
+
this.token = token;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async productList(json: { page: string; limit: string; search: string; variant_id_list?: string }) {
|
|
180
|
+
const page = json.page ? parseInt(`${json.page}`, 10) : 0;
|
|
181
|
+
const limit = json.limit ? parseInt(`${json.limit}`, 10) : 20;
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
const sqlArr = ['1=1'];
|
|
185
|
+
if (json.variant_id_list) {
|
|
186
|
+
sqlArr.push(`(v.id in (${json.variant_id_list}))`);
|
|
187
|
+
}
|
|
188
|
+
const sqlText = sqlArr.join(' AND ');
|
|
189
|
+
|
|
190
|
+
const getStockTotal = await db.query(
|
|
191
|
+
`SELECT count(v.id) as c
|
|
192
192
|
FROM \`${this.app}\`.t_variants as v,
|
|
193
193
|
\`${this.app}\`.t_manager_post as p
|
|
194
194
|
WHERE v.content ->>'$.stockList.${json.search || 'store'}.count' > 0
|
|
195
195
|
AND v.product_id = p.id
|
|
196
196
|
AND ${sqlText}
|
|
197
197
|
`,
|
|
198
|
-
|
|
199
|
-
|
|
198
|
+
[]
|
|
199
|
+
);
|
|
200
200
|
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
let data = await db.query(
|
|
202
|
+
`SELECT v.*, p.content as product_content
|
|
203
203
|
FROM \`${this.app}\`.t_variants as v,
|
|
204
204
|
\`${this.app}\`.t_manager_post as p
|
|
205
205
|
WHERE v.content ->>'$.stockList.${json.search || 'store'}.count' > 0
|
|
@@ -208,57 +208,57 @@ export class Stock {
|
|
|
208
208
|
LIMIT ${page * limit}
|
|
209
209
|
, ${limit};
|
|
210
210
|
`,
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
211
|
+
[]
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
data.map((item: any) => {
|
|
215
|
+
item.count = item.content.stockList[json.search].count;
|
|
216
|
+
item.title = (() => {
|
|
217
|
+
try {
|
|
218
|
+
return item.product_content.language_data['zh-TW'].title;
|
|
219
|
+
} catch (error) {
|
|
220
|
+
console.error(`product id ${item.product_id} 沒有 zh-TW 的標題,使用原標題`);
|
|
221
|
+
return item.product_content.title;
|
|
222
|
+
}
|
|
223
|
+
})();
|
|
224
|
+
return item;
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
total: getStockTotal[0].c,
|
|
229
|
+
data,
|
|
230
|
+
};
|
|
231
|
+
} catch (error) {
|
|
232
|
+
console.error(error);
|
|
233
|
+
if (error instanceof Error) {
|
|
234
|
+
throw exception.BadRequestError('stock productList Error: ', error.message, null);
|
|
235
|
+
}
|
|
237
236
|
}
|
|
237
|
+
}
|
|
238
238
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
239
|
+
async productStock(json: { page: string; limit: string; variant_id_list: string }) {
|
|
240
|
+
const page = json.page ? parseInt(`${json.page}`, 10) : 0;
|
|
241
|
+
const limit = json.limit ? parseInt(`${json.limit}`, 10) : 20;
|
|
242
242
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
243
|
+
try {
|
|
244
|
+
const sqlArr = ['1=1'];
|
|
245
|
+
if (json.variant_id_list) {
|
|
246
|
+
sqlArr.push(`(v.id in (${json.variant_id_list}))`);
|
|
247
|
+
}
|
|
248
|
+
const sqlText = sqlArr.join(' AND ');
|
|
249
249
|
|
|
250
|
-
|
|
251
|
-
|
|
250
|
+
const getStockTotal = await db.query(
|
|
251
|
+
`SELECT count(v.id) as c
|
|
252
252
|
FROM \`${this.app}\`.t_variants as v,
|
|
253
253
|
\`${this.app}\`.t_manager_post as p
|
|
254
254
|
WHERE v.product_id = p.id
|
|
255
255
|
AND ${sqlText}
|
|
256
256
|
`,
|
|
257
|
-
|
|
258
|
-
|
|
257
|
+
[]
|
|
258
|
+
);
|
|
259
259
|
|
|
260
|
-
|
|
261
|
-
|
|
260
|
+
let data = await db.query(
|
|
261
|
+
`SELECT v.*, p.content as product_content
|
|
262
262
|
FROM \`${this.app}\`.t_variants as v,
|
|
263
263
|
\`${this.app}\`.t_manager_post as p
|
|
264
264
|
WHERE v.product_id = p.id
|
|
@@ -266,561 +266,576 @@ export class Stock {
|
|
|
266
266
|
LIMIT ${page * limit}
|
|
267
267
|
, ${limit};
|
|
268
268
|
`,
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
269
|
+
[]
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
data.map((item: any) => {
|
|
273
|
+
item.count = Object.values(item.content.stockList).reduce((sum: number, stock: any) => sum + stock.count, 0);
|
|
274
|
+
item.title = (() => {
|
|
275
|
+
try {
|
|
276
|
+
return item.product_content.language_data['zh-TW'].title;
|
|
277
|
+
} catch (error) {
|
|
278
|
+
console.error(`product id ${item.product_id} 沒有 zh-TW 的標題,使用原標題`);
|
|
279
|
+
return item.product_content.title;
|
|
280
|
+
}
|
|
281
|
+
})();
|
|
282
|
+
return item;
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
return {
|
|
286
|
+
total: getStockTotal[0].c,
|
|
287
|
+
data,
|
|
288
|
+
};
|
|
289
|
+
} catch (error) {
|
|
290
|
+
console.error(error);
|
|
291
|
+
if (error instanceof Error) {
|
|
292
|
+
throw exception.BadRequestError('stock productList Error: ', error.message, null);
|
|
293
|
+
}
|
|
295
294
|
}
|
|
295
|
+
}
|
|
296
296
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
297
|
+
async deleteStoreProduct(store_id: string) {
|
|
298
|
+
try {
|
|
299
|
+
const productList: { [k: string]: any } = {};
|
|
300
|
+
const variants = await db.query(
|
|
301
|
+
`SELECT *
|
|
302
302
|
FROM \`${this.app}\`.t_variants
|
|
303
303
|
WHERE content ->>'$.stockList.${store_id}.count' is not null;
|
|
304
304
|
`,
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
305
|
+
[]
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
if (variants.length == 0) {
|
|
309
|
+
return { data: true, process: '' };
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const promise = await new Promise<void>(resolve => {
|
|
313
|
+
let n = 0;
|
|
314
|
+
for (const variant of variants) {
|
|
315
|
+
delete variant.content.stockList[store_id];
|
|
316
|
+
db.query(
|
|
317
|
+
`UPDATE \`${this.app}\`.t_variants
|
|
318
318
|
SET ?
|
|
319
319
|
WHERE id = ?
|
|
320
320
|
`,
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
321
|
+
[{ content: JSON.stringify(variant.content) }, variant.id]
|
|
322
|
+
).then(() => {
|
|
323
|
+
const p = productList[`${variant.product_id}`];
|
|
324
|
+
if (p) {
|
|
325
|
+
p.push(variant.content);
|
|
326
|
+
} else {
|
|
327
|
+
productList[`${variant.product_id}`] = [variant.content];
|
|
328
|
+
}
|
|
329
|
+
n++;
|
|
330
|
+
if (n === variants.length) {
|
|
331
|
+
resolve();
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
}).then(async () => {
|
|
336
|
+
const idString = Object.keys(productList)
|
|
337
|
+
.map(item => `"${item}"`)
|
|
338
|
+
.join(',');
|
|
339
|
+
|
|
340
|
+
if (idString.length > 0) {
|
|
341
|
+
const products = await db.query(
|
|
342
|
+
`SELECT *
|
|
343
343
|
FROM \`${this.app}\`.t_manager_post
|
|
344
344
|
WHERE id in (${idString});
|
|
345
345
|
`,
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
346
|
+
[]
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
return await new Promise<void>(resolve => {
|
|
350
|
+
let n = 0;
|
|
351
|
+
for (const product of products) {
|
|
352
|
+
product.content.variants = productList[`${product.id}`];
|
|
353
|
+
db.query(
|
|
354
|
+
`UPDATE \`${this.app}\`.t_manager_post
|
|
355
355
|
SET ?
|
|
356
356
|
WHERE id = ?`,
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
}).then(() => {
|
|
366
|
-
return { data: true, process: 't_variants, t_manager_post' };
|
|
367
|
-
});
|
|
357
|
+
[{ content: JSON.stringify(product.content) }, product.id]
|
|
358
|
+
).then(() => {
|
|
359
|
+
n++;
|
|
360
|
+
if (n === products.length) {
|
|
361
|
+
resolve();
|
|
368
362
|
}
|
|
369
|
-
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
return promise;
|
|
373
|
-
} catch (error) {
|
|
374
|
-
console.error(error);
|
|
375
|
-
if (error instanceof Error) {
|
|
376
|
-
throw exception.BadRequestError('stock deleteStore Error: ', error.message, null);
|
|
363
|
+
});
|
|
377
364
|
}
|
|
365
|
+
}).then(() => {
|
|
366
|
+
return { data: true, process: 't_variants, t_manager_post' };
|
|
367
|
+
});
|
|
378
368
|
}
|
|
369
|
+
return { data: true, process: 't_variants' };
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
return promise;
|
|
373
|
+
} catch (error) {
|
|
374
|
+
console.error(error);
|
|
375
|
+
if (error instanceof Error) {
|
|
376
|
+
throw exception.BadRequestError('stock deleteStore Error: ', error.message, null);
|
|
377
|
+
}
|
|
379
378
|
}
|
|
379
|
+
}
|
|
380
380
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
381
|
+
public allocateStock(stockList: StockList, requiredCount: number) {
|
|
382
|
+
let remainingCount = requiredCount;
|
|
383
|
+
let totalDeduction = 0; // 紀錄所有扣除的總數
|
|
384
|
+
const deductionLog: { [key: string]: number } = {}; // 記錄每個倉庫的扣除值
|
|
385
385
|
|
|
386
|
-
|
|
387
|
-
|
|
386
|
+
// 按照 `count` 從大到小排序倉庫
|
|
387
|
+
const sortedStock = Object.entries(stockList).sort(([, a], [, b]) => b.count - a.count);
|
|
388
388
|
|
|
389
|
-
|
|
390
|
-
|
|
389
|
+
for (let [key, stock] of sortedStock) {
|
|
390
|
+
if (remainingCount === 0) break; // 如果需求已經滿足,停止迴圈
|
|
391
391
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
392
|
+
const deduction = Math.min((stock as any).count, remainingCount); // 扣除的數量為倉庫數量或剩餘需求中的較小值
|
|
393
|
+
remainingCount -= deduction; // 更新剩餘需求
|
|
394
|
+
totalDeduction += deduction; // 累加扣除值
|
|
395
|
+
(stock as any).count -= deduction; // 更新倉庫數量
|
|
396
396
|
|
|
397
|
-
|
|
398
|
-
|
|
397
|
+
deductionLog[key] = deduction; // 記錄本次扣除
|
|
398
|
+
}
|
|
399
399
|
|
|
400
|
-
|
|
401
|
-
|
|
400
|
+
// 紀錄最大扣除值
|
|
401
|
+
const maxDeduction = Math.max(...Object.values(deductionLog), 0);
|
|
402
402
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
403
|
+
return {
|
|
404
|
+
stockList,
|
|
405
|
+
deductionLog,
|
|
406
|
+
totalDeduction,
|
|
407
|
+
remainingCount, // 如果需求無法完全滿足,這裡會大於 0
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
public async recoverStock(variant: any) {
|
|
412
|
+
const sql =
|
|
413
|
+
variant.spec.length > 0
|
|
414
|
+
? `AND JSON_CONTAINS(content->'$.spec', JSON_ARRAY(${variant.spec
|
|
415
|
+
.map((data: string) => {
|
|
416
|
+
return `\"${data}\"`;
|
|
417
|
+
})
|
|
418
|
+
.join(',')}));`
|
|
419
|
+
: '';
|
|
410
420
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
variant.spec.length > 0
|
|
414
|
-
? `AND JSON_CONTAINS(content->'$.spec', JSON_ARRAY(${variant.spec
|
|
415
|
-
.map((data: string) => {
|
|
416
|
-
return `\"${data}\"`;
|
|
417
|
-
})
|
|
418
|
-
.join(',')}));`
|
|
419
|
-
: '';
|
|
420
|
-
|
|
421
|
-
let variantData = await db.query(
|
|
422
|
-
`
|
|
421
|
+
let variantData = await db.query(
|
|
422
|
+
`
|
|
423
423
|
SELECT *
|
|
424
424
|
FROM \`${this.app}\`.t_variants
|
|
425
425
|
WHERE \`product_id\` = "${variant.id}" ${sql}
|
|
426
426
|
`,
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
427
|
+
[]
|
|
428
|
+
);
|
|
429
|
+
const pdDqlData = (
|
|
430
|
+
await new Shopping(this.app, this.token).getProduct({
|
|
431
|
+
page: 0,
|
|
432
|
+
limit: 50,
|
|
433
|
+
id: variant.id,
|
|
434
|
+
status: 'inRange',
|
|
435
|
+
})
|
|
436
|
+
).data;
|
|
437
|
+
const pd = pdDqlData.content;
|
|
438
|
+
const pbVariant = pd.variants.find((dd: any) => {
|
|
439
|
+
return dd.spec.join('-') === variant.spec.join('-');
|
|
440
|
+
});
|
|
441
|
+
variantData = variantData[0];
|
|
442
|
+
Object.entries(variant.deduction_log).forEach(([key, value]) => {
|
|
443
|
+
pbVariant.stockList[key].count = parseInt(pbVariant.stockList[key].count as string) + parseInt(value as string);
|
|
444
|
+
pbVariant.stock = parseInt(pbVariant.stock as string) + parseInt(value as string);
|
|
445
|
+
variantData.content.stockList[key].count =
|
|
446
|
+
parseInt(variantData.content.stockList[key].count) + parseInt(value as string);
|
|
447
|
+
variantData.content.stock = parseInt(variantData.content.stock) + parseInt(value as string);
|
|
448
|
+
});
|
|
449
|
+
await new Shopping(this.app, this.token).updateVariantsWithSpec(variantData.content, variant.id, variant.spec);
|
|
450
|
+
await db.query(
|
|
451
|
+
`UPDATE \`${this.app}\`.\`t_manager_post\`
|
|
451
452
|
SET ?
|
|
452
453
|
WHERE 1 = 1
|
|
453
454
|
and id = ${pdDqlData.id}`,
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
455
|
+
[{ content: JSON.stringify(pd) }]
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
public async shippingStock(variant: any) {
|
|
460
|
+
const sql =
|
|
461
|
+
variant.spec.length > 0
|
|
462
|
+
? `AND JSON_CONTAINS(content->'$.spec', JSON_ARRAY(${variant.spec
|
|
463
|
+
.map((data: string) => {
|
|
464
|
+
return `\"${data}\"`;
|
|
465
|
+
})
|
|
466
|
+
.join(',')}));`
|
|
467
|
+
: '';
|
|
457
468
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
variant.spec.length > 0
|
|
461
|
-
? `AND JSON_CONTAINS(content->'$.spec', JSON_ARRAY(${variant.spec
|
|
462
|
-
.map((data: string) => {
|
|
463
|
-
return `\"${data}\"`;
|
|
464
|
-
})
|
|
465
|
-
.join(',')}));`
|
|
466
|
-
: '';
|
|
467
|
-
|
|
468
|
-
let variantData = await db.query(
|
|
469
|
-
`
|
|
469
|
+
let variantData = await db.query(
|
|
470
|
+
`
|
|
470
471
|
SELECT *
|
|
471
472
|
FROM \`${this.app}\`.t_variants
|
|
472
473
|
WHERE \`product_id\` = "${variant.id}" ${sql}
|
|
473
474
|
`,
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
475
|
+
[]
|
|
476
|
+
);
|
|
477
|
+
const pdDqlData = (
|
|
478
|
+
await new Shopping(this.app, this.token).getProduct({
|
|
479
|
+
page: 0,
|
|
480
|
+
limit: 50,
|
|
481
|
+
id: variant.id,
|
|
482
|
+
status: 'inRange',
|
|
483
|
+
})
|
|
484
|
+
).data;
|
|
485
|
+
const pd = pdDqlData.content;
|
|
486
|
+
const pbVariant = pd.variants.find((dd: any) => {
|
|
487
|
+
return dd.spec.join('-') === variant.spec.join('-');
|
|
488
|
+
});
|
|
489
|
+
variantData = variantData[0];
|
|
490
|
+
Object.entries(variant.deduction_log).forEach(([key, value]) => {
|
|
491
|
+
pbVariant.stockList[key].count = parseInt(pbVariant.stockList[key].count as string) - parseInt(value as string);
|
|
492
|
+
pbVariant.stock = parseInt(pbVariant.stock as string) - parseInt(value as string);
|
|
493
|
+
variantData.content.stockList[key].count =
|
|
494
|
+
parseInt(variantData.content.stockList[key].count) - parseInt(value as string);
|
|
495
|
+
variantData.content.stock = parseInt(variantData.content.stock) - parseInt(value as string);
|
|
496
|
+
});
|
|
497
|
+
await new Shopping(this.app, this.token).updateVariantsWithSpec(variantData.content, variant.id, variant.spec);
|
|
498
|
+
await db.query(
|
|
499
|
+
`UPDATE \`${this.app}\`.\`t_manager_post\`
|
|
498
500
|
SET ?
|
|
499
501
|
WHERE 1 = 1
|
|
500
502
|
and id = ${pdDqlData.id}`,
|
|
501
|
-
|
|
502
|
-
|
|
503
|
+
[{ content: JSON.stringify(pd) }]
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
async getHistory(json: {
|
|
508
|
+
page: string;
|
|
509
|
+
limit: string;
|
|
510
|
+
search: string;
|
|
511
|
+
type: StockHistoryType;
|
|
512
|
+
order_id: string;
|
|
513
|
+
queryType: string;
|
|
514
|
+
}) {
|
|
515
|
+
const page = json.page ? parseInt(`${json.page}`, 10) : 0;
|
|
516
|
+
const limit = json.limit ? parseInt(`${json.limit}`, 10) : 20;
|
|
517
|
+
|
|
518
|
+
function formatDate(sqlDatetime: string): string {
|
|
519
|
+
// 將 datetime 字串轉換為 JavaScript Date 物件
|
|
520
|
+
const date = new Date(sqlDatetime);
|
|
521
|
+
|
|
522
|
+
// 取得年、月、日
|
|
523
|
+
const year = date.getFullYear();
|
|
524
|
+
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份是從 0 開始的,需要加 1
|
|
525
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
526
|
+
|
|
527
|
+
// 組合成 'yyyy-mm-dd' 格式
|
|
528
|
+
const formattedDate = `${year}-${month}-${day}`;
|
|
529
|
+
return formattedDate;
|
|
503
530
|
}
|
|
504
531
|
|
|
505
|
-
|
|
506
|
-
const page = json.page ? parseInt(`${json.page}`, 10) : 0;
|
|
507
|
-
const limit = json.limit ? parseInt(`${json.limit}`, 10) : 20;
|
|
508
|
-
|
|
509
|
-
function formatDate(sqlDatetime: string): string {
|
|
510
|
-
// 將 datetime 字串轉換為 JavaScript Date 物件
|
|
511
|
-
const date = new Date(sqlDatetime);
|
|
512
|
-
|
|
513
|
-
// 取得年、月、日
|
|
514
|
-
const year = date.getFullYear();
|
|
515
|
-
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份是從 0 開始的,需要加 1
|
|
516
|
-
const day = String(date.getDate()).padStart(2, '0');
|
|
517
|
-
|
|
518
|
-
// 組合成 'yyyy-mm-dd' 格式
|
|
519
|
-
const formattedDate = `${year}-${month}-${day}`;
|
|
520
|
-
return formattedDate;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
const sqlArr: string[] = ['(status <> -1)', `(type = '${json.type}')`];
|
|
532
|
+
const sqlArr: string[] = ['(status <> -1)', `(type = '${json.type}')`];
|
|
524
533
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
534
|
+
if (json.order_id) {
|
|
535
|
+
sqlArr.push(`(order_id = '${json.order_id}')`);
|
|
536
|
+
}
|
|
528
537
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
538
|
+
if (json.queryType && json.search) {
|
|
539
|
+
switch (json.queryType) {
|
|
540
|
+
case 'order_id':
|
|
541
|
+
sqlArr.push(`(order_id like '%${json.search}%')`);
|
|
542
|
+
break;
|
|
543
|
+
case 'note':
|
|
544
|
+
sqlArr.push(`(JSON_EXTRACT(content, '$.note') like '%${json.search}%')`);
|
|
545
|
+
break;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
539
548
|
|
|
540
|
-
|
|
549
|
+
const sqlString = sqlArr.join(' AND ');
|
|
541
550
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
551
|
+
try {
|
|
552
|
+
if (!this.token) {
|
|
553
|
+
return {
|
|
554
|
+
total: 0,
|
|
555
|
+
data: [],
|
|
556
|
+
};
|
|
557
|
+
}
|
|
549
558
|
|
|
550
|
-
|
|
551
|
-
|
|
559
|
+
const getHistoryTotal = await db.query(
|
|
560
|
+
`SELECT count(id) as c FROM \`${this.app}\`.t_stock_history
|
|
552
561
|
WHERE 1=1 AND ${sqlString}
|
|
553
562
|
`,
|
|
554
|
-
|
|
555
|
-
|
|
563
|
+
[]
|
|
564
|
+
);
|
|
556
565
|
|
|
557
|
-
|
|
558
|
-
|
|
566
|
+
const data = await db.query(
|
|
567
|
+
`SELECT * FROM \`${this.app}\`.t_stock_history
|
|
559
568
|
WHERE 1=1 AND ${sqlString}
|
|
560
569
|
ORDER BY order_id DESC
|
|
561
570
|
LIMIT ${page * limit}, ${limit};
|
|
562
571
|
`,
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
}
|
|
572
|
+
[]
|
|
573
|
+
);
|
|
574
|
+
|
|
575
|
+
const getPermission = (await new SharePermission(this.app, this.token).getPermission({
|
|
576
|
+
page: 0,
|
|
577
|
+
limit: 9999,
|
|
578
|
+
})) as any;
|
|
579
|
+
|
|
580
|
+
data.map((rowData: StockHistoryData) => {
|
|
581
|
+
rowData.created_time = formatDate(rowData.created_time);
|
|
582
|
+
rowData.content.changeLogs.map(log => {
|
|
583
|
+
const findManager = getPermission.data.find((m: any) => `${m.user}` === `${log.user}`);
|
|
584
|
+
log.user_name = findManager ? findManager.config.name : '';
|
|
585
|
+
return log;
|
|
586
|
+
});
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
return {
|
|
590
|
+
total: getHistoryTotal[0].c,
|
|
591
|
+
data,
|
|
592
|
+
};
|
|
593
|
+
} catch (error) {
|
|
594
|
+
console.error(error);
|
|
595
|
+
if (error instanceof Error) {
|
|
596
|
+
throw exception.BadRequestError('stock getHistory Error: ', error.message, null);
|
|
597
|
+
}
|
|
590
598
|
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
async postHistory(json: StockHistoryData) {
|
|
602
|
+
try {
|
|
603
|
+
const typeData = typeConfig[json.type];
|
|
604
|
+
|
|
605
|
+
json.content.product_list.map(item => {
|
|
606
|
+
// delete item.title;
|
|
607
|
+
// delete item.spec;
|
|
608
|
+
// delete item.sku;
|
|
609
|
+
return item;
|
|
610
|
+
});
|
|
611
|
+
json.content.changeLogs = [
|
|
612
|
+
{
|
|
613
|
+
time: Tool.getCurrentDateTime(),
|
|
614
|
+
status: json.status,
|
|
615
|
+
text: `${typeData.name}單建立`,
|
|
616
|
+
user: this.token ? this.token.userID : 0,
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
time: Tool.getCurrentDateTime({ addSeconds: 1 }),
|
|
620
|
+
status: json.status,
|
|
621
|
+
text: `${typeData.name}單狀態改為「${typeData.status[json.status].title}」`,
|
|
622
|
+
user: this.token ? this.token.userID : 0,
|
|
623
|
+
},
|
|
624
|
+
];
|
|
591
625
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
626
|
+
const formatJson = JSON.parse(JSON.stringify(json));
|
|
627
|
+
formatJson.order_id = `${typeData.prefixId}${new Date().getTime()}`;
|
|
628
|
+
formatJson.content = JSON.stringify(json.content);
|
|
629
|
+
formatJson.created_time = `${json.created_time} 00:00:00`;
|
|
630
|
+
delete formatJson.id;
|
|
595
631
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
// delete item.spec;
|
|
599
|
-
// delete item.sku;
|
|
600
|
-
return item;
|
|
601
|
-
});
|
|
602
|
-
json.content.changeLogs = [
|
|
603
|
-
{
|
|
604
|
-
time: Tool.getCurrentDateTime(),
|
|
605
|
-
status: json.status,
|
|
606
|
-
text: `${typeData.name}單建立`,
|
|
607
|
-
user: this.token ? this.token.userID : 0,
|
|
608
|
-
},
|
|
609
|
-
{
|
|
610
|
-
time: Tool.getCurrentDateTime({ addSeconds: 1 }),
|
|
611
|
-
status: json.status,
|
|
612
|
-
text: `${typeData.name}單狀態改為「${typeData.status[json.status].title}」`,
|
|
613
|
-
user: this.token ? this.token.userID : 0,
|
|
614
|
-
},
|
|
615
|
-
];
|
|
616
|
-
|
|
617
|
-
const formatJson = JSON.parse(JSON.stringify(json));
|
|
618
|
-
formatJson.order_id = `${typeData.prefixId}${new Date().getTime()}`;
|
|
619
|
-
formatJson.content = JSON.stringify(json.content);
|
|
620
|
-
formatJson.created_time = `${json.created_time} 00:00:00`;
|
|
621
|
-
delete formatJson.id;
|
|
622
|
-
|
|
623
|
-
await db.query(
|
|
624
|
-
`INSERT INTO \`${this.app}\`.\`t_stock_history\` SET ?;
|
|
632
|
+
await db.query(
|
|
633
|
+
`INSERT INTO \`${this.app}\`.\`t_stock_history\` SET ?;
|
|
625
634
|
`,
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
}
|
|
635
|
+
[formatJson]
|
|
636
|
+
);
|
|
637
|
+
|
|
638
|
+
return { data: formatJson };
|
|
639
|
+
} catch (error) {
|
|
640
|
+
console.error(error);
|
|
641
|
+
if (error instanceof Error) {
|
|
642
|
+
throw exception.BadRequestError('stock postHistory Error: ', error.message, null);
|
|
643
|
+
}
|
|
636
644
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
async putHistory(token: any, json: StockHistoryData) {
|
|
648
|
+
try {
|
|
649
|
+
if (!this.token) {
|
|
650
|
+
return { data: false };
|
|
651
|
+
}
|
|
652
|
+
const typeData = typeConfig[json.type];
|
|
653
|
+
|
|
654
|
+
// 取得原始資料
|
|
655
|
+
const getHistory = await db.query(
|
|
656
|
+
`SELECT * FROM \`${this.app}\`.t_stock_history WHERE order_id = ?;
|
|
648
657
|
`,
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
return undefined;
|
|
687
|
-
})(),
|
|
688
|
-
});
|
|
689
|
-
|
|
690
|
-
const formatJson = JSON.parse(JSON.stringify(json));
|
|
691
|
-
formatJson.content = JSON.stringify(json.content);
|
|
692
|
-
delete formatJson.id;
|
|
693
|
-
|
|
694
|
-
// 改變商品與規格庫存
|
|
695
|
-
const _shop = new Shopping(this.app, this.token);
|
|
696
|
-
const variants = await _shop.getVariants({
|
|
697
|
-
page: 0,
|
|
698
|
-
limit: 9999,
|
|
699
|
-
id_list: json.content.product_list.map((item) => item.variant_id).join(','),
|
|
700
|
-
});
|
|
701
|
-
const dataList: {
|
|
702
|
-
id: number;
|
|
703
|
-
product_id: number;
|
|
704
|
-
product_content: any;
|
|
705
|
-
variant_content: any;
|
|
706
|
-
}[] = [];
|
|
707
|
-
|
|
708
|
-
const createStockEntry = (type: 'plus' | 'minus' | 'equal', store: string, count: number, variant: any) => ({
|
|
709
|
-
id: variant.id,
|
|
710
|
-
product_id: variant.product_id,
|
|
711
|
-
...Stock.formatStockContent({
|
|
712
|
-
type,
|
|
713
|
-
store,
|
|
714
|
-
count,
|
|
715
|
-
product_content: variant.product_content,
|
|
716
|
-
variant_content: variant.variant_content,
|
|
717
|
-
}),
|
|
658
|
+
[json.order_id]
|
|
659
|
+
);
|
|
660
|
+
if (!getHistory || getHistory.length !== 1) {
|
|
661
|
+
return { data: false };
|
|
662
|
+
}
|
|
663
|
+
const originHistory = getHistory[0] as StockHistoryData;
|
|
664
|
+
const originList = originHistory.content.product_list;
|
|
665
|
+
|
|
666
|
+
// 格式化更新資料
|
|
667
|
+
json.content.product_list.map(item => {
|
|
668
|
+
delete item.title;
|
|
669
|
+
delete item.spec;
|
|
670
|
+
delete item.sku;
|
|
671
|
+
delete item.barcode;
|
|
672
|
+
return item;
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
json.content.changeLogs.push({
|
|
676
|
+
time: Tool.getCurrentDateTime(),
|
|
677
|
+
status: json.status,
|
|
678
|
+
text: `進貨單狀態改為「${typeData.status[json.status].title}」`,
|
|
679
|
+
user: this.token.userID,
|
|
680
|
+
product_list: (() => {
|
|
681
|
+
if (json.status === 1 || json.status === 5) {
|
|
682
|
+
const updateList = JSON.parse(JSON.stringify(json.content.product_list)) as ContentProduct[];
|
|
683
|
+
|
|
684
|
+
return updateList.map(item1 => {
|
|
685
|
+
const originVariant = originList.find(item2 => item1.variant_id === item2.variant_id);
|
|
686
|
+
if (originVariant) {
|
|
687
|
+
return {
|
|
688
|
+
replenishment_count: (item1.recent_count ?? 0) - (originVariant.recent_count ?? 0),
|
|
689
|
+
...item1,
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
return item1;
|
|
718
693
|
});
|
|
694
|
+
}
|
|
695
|
+
return undefined;
|
|
696
|
+
})(),
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
const formatJson = JSON.parse(JSON.stringify(json));
|
|
700
|
+
formatJson.content = JSON.stringify(json.content);
|
|
701
|
+
delete formatJson.id;
|
|
702
|
+
|
|
703
|
+
// 改變商品與規格庫存
|
|
704
|
+
const _shop = new Shopping(this.app, this.token);
|
|
705
|
+
const variants = await _shop.getVariants({
|
|
706
|
+
page: 0,
|
|
707
|
+
limit: 9999,
|
|
708
|
+
id_list: json.content.product_list.map(item => item.variant_id).join(','),
|
|
709
|
+
});
|
|
710
|
+
const dataList: {
|
|
711
|
+
id: number;
|
|
712
|
+
product_id: number;
|
|
713
|
+
product_content: any;
|
|
714
|
+
variant_content: any;
|
|
715
|
+
}[] = [];
|
|
716
|
+
|
|
717
|
+
const createStockEntry = (type: 'plus' | 'minus' | 'equal', store: string, count: number, variant: any) => ({
|
|
718
|
+
id: variant.id,
|
|
719
|
+
product_id: variant.product_id,
|
|
720
|
+
...Stock.formatStockContent({
|
|
721
|
+
type,
|
|
722
|
+
store,
|
|
723
|
+
count,
|
|
724
|
+
product_content: variant.product_content,
|
|
725
|
+
variant_content: variant.variant_content,
|
|
726
|
+
}),
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
for (const variant of variants.data) {
|
|
730
|
+
const item = json.content.product_list.find(item => item.variant_id === variant.id);
|
|
731
|
+
|
|
732
|
+
if (item) {
|
|
733
|
+
const originVariant = originList.find(origin => item.variant_id === origin.variant_id);
|
|
734
|
+
const recent_count = item.recent_count ?? 0;
|
|
735
|
+
const count = originVariant ? recent_count - (originVariant.recent_count ?? 0) : recent_count;
|
|
736
|
+
const { type, content } = json;
|
|
737
|
+
const { store_in, store_out } = content;
|
|
738
|
+
|
|
739
|
+
if (type === 'restocking') {
|
|
740
|
+
dataList.push(createStockEntry('plus', store_in, count, variant));
|
|
741
|
+
} else if (type === 'transfer') {
|
|
742
|
+
dataList.push(createStockEntry('plus', store_in, count, variant));
|
|
743
|
+
dataList.push(createStockEntry('minus', store_out, count, variant));
|
|
744
|
+
} else if (type === 'checking' && (json.status === 0 || json.status === 1)) {
|
|
745
|
+
dataList.push(createStockEntry('equal', store_out, recent_count, variant));
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
719
749
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
if (item) {
|
|
724
|
-
const originVariant = originList.find((origin) => item.variant_id === origin.variant_id);
|
|
725
|
-
const recent_count = item.recent_count ?? 0;
|
|
726
|
-
const count = originVariant ? recent_count - (originVariant.recent_count ?? 0) : recent_count;
|
|
727
|
-
const { type, content } = json;
|
|
728
|
-
const { store_in, store_out } = content;
|
|
729
|
-
|
|
730
|
-
if (type === 'restocking') {
|
|
731
|
-
dataList.push(createStockEntry('plus', store_in, count, variant));
|
|
732
|
-
} else if (type === 'transfer') {
|
|
733
|
-
dataList.push(createStockEntry('plus', store_in, count, variant));
|
|
734
|
-
dataList.push(createStockEntry('minus', store_out, count, variant));
|
|
735
|
-
} else if (type === 'checking' && (json.status === 0 || json.status === 1)) {
|
|
736
|
-
dataList.push(createStockEntry('equal', store_out, recent_count, variant));
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
// 更新產品與規格庫存
|
|
742
|
-
await _shop.putVariants(dataList);
|
|
750
|
+
// 更新產品與規格庫存
|
|
751
|
+
await _shop.putVariants(token, dataList);
|
|
743
752
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
}
|
|
753
|
+
// 更新庫存單
|
|
754
|
+
await db.query(
|
|
755
|
+
`UPDATE \`${this.app}\`.t_stock_history SET ? WHERE order_id = ?
|
|
756
|
+
`,
|
|
757
|
+
[formatJson, json.order_id]
|
|
758
|
+
);
|
|
759
|
+
|
|
760
|
+
return { data: true };
|
|
761
|
+
} catch (error) {
|
|
762
|
+
console.error(error);
|
|
763
|
+
if (error instanceof Error) {
|
|
764
|
+
throw exception.BadRequestError('stock postHistory Error: ', error.message, null);
|
|
765
|
+
}
|
|
758
766
|
}
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
} else {
|
|
783
|
-
stockList[store].count = count;
|
|
784
|
-
}
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
static formatStockContent(data: {
|
|
770
|
+
type: 'plus' | 'minus' | 'equal';
|
|
771
|
+
store: string;
|
|
772
|
+
count: number;
|
|
773
|
+
product_content: any;
|
|
774
|
+
variant_content: any;
|
|
775
|
+
}) {
|
|
776
|
+
const type = data.type;
|
|
777
|
+
const store = data.store;
|
|
778
|
+
const count = data.count;
|
|
779
|
+
const product_content = data.product_content;
|
|
780
|
+
const variant_content = data.variant_content;
|
|
781
|
+
const stockList = variant_content.stockList;
|
|
782
|
+
|
|
783
|
+
// 修改 variant stockList
|
|
784
|
+
if (stockList[store]) {
|
|
785
|
+
if (type === 'plus') {
|
|
786
|
+
if (stockList[store].count) {
|
|
787
|
+
stockList[store].count += count;
|
|
788
|
+
} else {
|
|
789
|
+
stockList[store].count = count;
|
|
785
790
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
}
|
|
792
|
-
return sum;
|
|
793
|
-
}, 0);
|
|
794
|
-
|
|
795
|
-
// 修改 product variant 的 stock, stockList
|
|
796
|
-
const productVariant = product_content.variants.find((item: any) => {
|
|
797
|
-
return item.spec.join(',') === variant_content.spec.join(',');
|
|
798
|
-
});
|
|
799
|
-
if (productVariant) {
|
|
800
|
-
productVariant.stockList = variant_content.stockList;
|
|
801
|
-
productVariant.stock = variant_content.stock;
|
|
791
|
+
} else if (type === 'minus') {
|
|
792
|
+
if (stockList[store].count) {
|
|
793
|
+
stockList[store].count -= count;
|
|
794
|
+
} else {
|
|
795
|
+
stockList[store].count = -count;
|
|
802
796
|
}
|
|
797
|
+
} else {
|
|
798
|
+
stockList[store].count = count;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
803
801
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
802
|
+
// 修改 variant stock
|
|
803
|
+
variant_content.stock = Object.keys(stockList).reduce((sum: number, key: string) => {
|
|
804
|
+
if (stockList[key] && stockList[key].count) {
|
|
805
|
+
return sum + stockList[key].count;
|
|
806
|
+
}
|
|
807
|
+
return sum;
|
|
808
|
+
}, 0);
|
|
809
|
+
|
|
810
|
+
// 修改 product variant 的 stock, stockList
|
|
811
|
+
const productVariant = product_content.variants.find((item: any) => {
|
|
812
|
+
return item.spec.join(',') === variant_content.spec.join(',');
|
|
813
|
+
});
|
|
814
|
+
if (productVariant) {
|
|
815
|
+
productVariant.stockList = variant_content.stockList;
|
|
816
|
+
productVariant.stock = variant_content.stock;
|
|
808
817
|
}
|
|
809
818
|
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
819
|
+
return {
|
|
820
|
+
product_content,
|
|
821
|
+
variant_content,
|
|
822
|
+
};
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
async deleteHistory(json: StockHistoryData) {
|
|
826
|
+
try {
|
|
827
|
+
await db.query(
|
|
828
|
+
`UPDATE \`${this.app}\`.t_stock_history SET ? WHERE id = ?
|
|
829
|
+
`,
|
|
830
|
+
[{ status: -1 }, json.id]
|
|
831
|
+
);
|
|
832
|
+
|
|
833
|
+
return { data: false };
|
|
834
|
+
} catch (error) {
|
|
835
|
+
console.error(error);
|
|
836
|
+
if (error instanceof Error) {
|
|
837
|
+
throw exception.BadRequestError('stock postHistory Error: ', error.message, null);
|
|
838
|
+
}
|
|
825
839
|
}
|
|
840
|
+
}
|
|
826
841
|
}
|