ts-glitter 20.6.8 → 20.7.0

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.
Files changed (175) hide show
  1. package/lowcode/Entry.js +2 -2
  2. package/lowcode/Entry.ts +2 -2
  3. package/lowcode/backend-manager/bg-blog.js +617 -621
  4. package/lowcode/backend-manager/bg-blog.ts +2323 -2325
  5. package/lowcode/backend-manager/bg-line.js +5 -4
  6. package/lowcode/backend-manager/bg-line.ts +5 -4
  7. package/lowcode/backend-manager/bg-list-component.js +9 -0
  8. package/lowcode/backend-manager/bg-list-component.ts +15 -1
  9. package/lowcode/backend-manager/bg-notify.js +6 -4
  10. package/lowcode/backend-manager/bg-notify.ts +6 -4
  11. package/lowcode/backend-manager/bg-product.js +145 -0
  12. package/lowcode/backend-manager/bg-product.ts +153 -0
  13. package/lowcode/backend-manager/bg-sns.js +5 -3
  14. package/lowcode/backend-manager/bg-sns.ts +5 -3
  15. package/lowcode/backend-manager/bg-widget.js +92 -4
  16. package/lowcode/backend-manager/bg-widget.ts +122 -6
  17. package/lowcode/backend-manager/splitPage.js +0 -39
  18. package/lowcode/backend-manager/splitPage.ts +0 -40
  19. package/lowcode/cms-plugin/auto-fcm-advertise.js +17 -5
  20. package/lowcode/cms-plugin/auto-fcm-advertise.ts +19 -6
  21. package/lowcode/cms-plugin/auto-fcm-history.js +2732 -0
  22. package/lowcode/cms-plugin/auto-fcm-history.ts +2995 -0
  23. package/lowcode/cms-plugin/cms-router.js +5 -0
  24. package/lowcode/cms-plugin/cms-router.ts +6 -0
  25. package/lowcode/cms-plugin/filter-options.js +80 -27
  26. package/lowcode/cms-plugin/filter-options.ts +83 -27
  27. package/lowcode/cms-plugin/language-backend.js +50 -39
  28. package/lowcode/cms-plugin/language-backend.ts +109 -95
  29. package/lowcode/cms-plugin/menus-setting.js +175 -151
  30. package/lowcode/cms-plugin/menus-setting.ts +620 -591
  31. package/lowcode/cms-plugin/model/order.d.ts +1 -0
  32. package/lowcode/cms-plugin/module/data.js +7 -7
  33. package/lowcode/cms-plugin/module/data.ts +262 -233
  34. package/lowcode/cms-plugin/module/delivery-html.js +18 -10
  35. package/lowcode/cms-plugin/module/delivery-html.ts +26 -10
  36. package/lowcode/cms-plugin/module/order-setting.js +458 -328
  37. package/lowcode/cms-plugin/module/order-setting.ts +622 -351
  38. package/lowcode/cms-plugin/module/product-excel.js +1 -1
  39. package/lowcode/cms-plugin/module/product-excel.ts +2 -1
  40. package/lowcode/cms-plugin/order/order-module.js +90 -1
  41. package/lowcode/cms-plugin/order/order-module.ts +106 -1
  42. package/lowcode/cms-plugin/pos-pages/payment-page.js +11 -8
  43. package/lowcode/cms-plugin/pos-pages/payment-page.ts +28 -15
  44. package/lowcode/cms-plugin/pos-pages/products-page.js +0 -39
  45. package/lowcode/cms-plugin/pos-pages/products-page.ts +0 -40
  46. package/lowcode/cms-plugin/shopping-collections.ts +1 -3
  47. package/lowcode/cms-plugin/shopping-finance-setting.js +19 -80
  48. package/lowcode/cms-plugin/shopping-finance-setting.ts +19 -87
  49. package/lowcode/cms-plugin/shopping-order-manager.js +122 -38
  50. package/lowcode/cms-plugin/shopping-order-manager.ts +160 -58
  51. package/lowcode/cms-plugin/shopping-product-setting.js +364 -376
  52. package/lowcode/cms-plugin/shopping-product-setting.ts +406 -415
  53. package/lowcode/cms-plugin/shopping-setting-advance.js +57 -16
  54. package/lowcode/cms-plugin/shopping-setting-advance.ts +69 -18
  55. package/lowcode/cms-plugin/stock-history.js +75 -63
  56. package/lowcode/cms-plugin/stock-history.ts +390 -376
  57. package/lowcode/cms-plugin/user/user-module.js +2 -43
  58. package/lowcode/cms-plugin/user/user-module.ts +2 -46
  59. package/lowcode/cms-plugin/user-list.js +4 -6
  60. package/lowcode/cms-plugin/user-list.ts +35 -38
  61. package/lowcode/css/editor.css +42 -3
  62. package/lowcode/glitter-base/global/language.js +6 -1
  63. package/lowcode/glitter-base/global/language.ts +10 -4
  64. package/lowcode/glitter-base/global/payment-config.js +19 -16
  65. package/lowcode/glitter-base/global/payment-config.ts +22 -16
  66. package/lowcode/glitter-base/global/shipment-config.js +6 -5
  67. package/lowcode/glitter-base/global/shipment-config.ts +12 -10
  68. package/lowcode/glitter-base/route/fcm.js +21 -1
  69. package/lowcode/glitter-base/route/fcm.ts +22 -2
  70. package/lowcode/glitter-base/route/shopping.js +8 -32
  71. package/lowcode/glitter-base/route/shopping.ts +10 -33
  72. package/lowcode/glitter-base/route/stock.ts +1 -0
  73. package/lowcode/glitter-base/route/user.js +11 -2
  74. package/lowcode/glitter-base/route/user.ts +23 -12
  75. package/lowcode/jspage/function-page/setting_editor.js +9 -0
  76. package/lowcode/jspage/function-page/setting_editor.ts +9 -0
  77. package/lowcode/public-components/blogs/list.js +223 -195
  78. package/lowcode/public-components/blogs/list.ts +383 -352
  79. package/lowcode/public-components/product/product-list.js +8 -4
  80. package/lowcode/public-components/product/product-list.ts +9 -4
  81. package/lowcode/public-components/terms-related/index.js +1 -1
  82. package/lowcode/public-components/terms-related/index.ts +1 -1
  83. package/lowcode/public-components/user-manager/um-login.js +1 -1
  84. package/lowcode/public-components/user-manager/um-login.ts +2 -2
  85. package/lowcode/public-components/user-manager/um-order.js +41 -5
  86. package/lowcode/public-components/user-manager/um-order.ts +58 -20
  87. package/lowcode/public-components/user-manager/um-voucher.ts +2 -2
  88. package/nhi4veq3gk.json +1 -0
  89. package/package.json +1 -1
  90. package/src/Language.d.ts +2 -0
  91. package/src/Language.js +66 -65
  92. package/src/Language.js.map +1 -1
  93. package/src/Language.ts +719 -715
  94. package/src/api-public/config/shipment-config.js +3 -2
  95. package/src/api-public/config/shipment-config.js.map +1 -1
  96. package/src/api-public/config/shipment-config.ts +3 -2
  97. package/src/api-public/controllers/ai-chat.js.map +1 -1
  98. package/src/api-public/controllers/ai-chat.ts +1 -2
  99. package/src/api-public/controllers/fcm.js +23 -58
  100. package/src/api-public/controllers/fcm.js.map +1 -1
  101. package/src/api-public/controllers/fcm.ts +28 -56
  102. package/src/api-public/controllers/shop.js +7 -1
  103. package/src/api-public/controllers/shop.js.map +1 -1
  104. package/src/api-public/controllers/shop.ts +17 -10
  105. package/src/api-public/controllers/user.js +1 -0
  106. package/src/api-public/controllers/user.js.map +1 -1
  107. package/src/api-public/controllers/user.ts +2 -0
  108. package/src/api-public/services/auto-send-email.js +247 -187
  109. package/src/api-public/services/auto-send-email.js.map +1 -1
  110. package/src/api-public/services/auto-send-email.ts +568 -505
  111. package/src/api-public/services/delivery.js +1 -1
  112. package/src/api-public/services/delivery.js.map +1 -1
  113. package/src/api-public/services/delivery.ts +6 -5
  114. package/src/api-public/services/financial-service.js +1 -2
  115. package/src/api-public/services/financial-service.js.map +1 -1
  116. package/src/api-public/services/financial-service.ts +4 -6
  117. package/src/api-public/services/manager.d.ts +4 -3
  118. package/src/api-public/services/manager.js +8 -12
  119. package/src/api-public/services/manager.js.map +1 -1
  120. package/src/api-public/services/manager.ts +57 -59
  121. package/src/api-public/services/model/handlePaymentTransaction.d.ts +1 -1
  122. package/src/api-public/services/model/handlePaymentTransaction.js +23 -3
  123. package/src/api-public/services/model/handlePaymentTransaction.js.map +1 -1
  124. package/src/api-public/services/model/handlePaymentTransaction.ts +25 -36
  125. package/src/api-public/services/schedule.d.ts +1 -0
  126. package/src/api-public/services/schedule.js +27 -0
  127. package/src/api-public/services/schedule.js.map +1 -1
  128. package/src/api-public/services/schedule.ts +30 -0
  129. package/src/api-public/services/shopping.d.ts +22 -2
  130. package/src/api-public/services/shopping.js +371 -95
  131. package/src/api-public/services/shopping.js.map +1 -1
  132. package/src/api-public/services/shopping.ts +499 -141
  133. package/src/api-public/services/stock.js +0 -3
  134. package/src/api-public/services/stock.js.map +1 -1
  135. package/src/api-public/services/stock.ts +3 -3
  136. package/src/api-public/services/user.d.ts +1 -0
  137. package/src/api-public/services/user.js +32 -12
  138. package/src/api-public/services/user.js.map +1 -1
  139. package/src/api-public/services/user.ts +38 -19
  140. package/src/api-public/services/workers.js +3 -3
  141. package/src/api-public/services/workers.js.map +1 -1
  142. package/src/api-public/services/workers.ts +103 -103
  143. package/src/app-project/ios/proshake/AppDelegate.swift +51 -7
  144. package/src/app-project/ios/proshake/Info.plist +11 -9
  145. package/src/app-project/ios/proshake/SceneDelegate.swift +18 -0
  146. package/src/app-project/ios/proshake/glitter-interface/BasicUtil.swift +43 -2
  147. package/src/app-project/ios/proshake/glitter-interface/Ecommerce.swift +56 -0
  148. package/src/app-project/ios/proshake.xcodeproj/project.xcworkspace/xcuserdata/jianzhi.wang.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  149. package/src/app-project/serverless/src/modules/database.js +1 -1
  150. package/src/app-project/serverless/src/modules/database.js.map +1 -1
  151. package/src/app-project/serverless/src/modules/database.ts +171 -171
  152. package/src/controllers/template.d.ts +1 -1
  153. package/src/controllers/template.js +16 -16
  154. package/src/controllers/template.js.map +1 -1
  155. package/src/controllers/template.ts +98 -84
  156. package/src/modules/database.js +3 -1
  157. package/src/modules/database.js.map +1 -1
  158. package/src/modules/database.ts +185 -181
  159. package/src/modules/firebase.d.ts +17 -0
  160. package/src/modules/firebase.js +126 -0
  161. package/src/modules/firebase.js.map +1 -1
  162. package/src/modules/firebase.ts +169 -0
  163. package/src/public-config-initial/auto-fcm.js +8 -2
  164. package/src/public-config-initial/auto-fcm.js.map +1 -1
  165. package/src/public-config-initial/auto-fcm.ts +15 -6
  166. package/src/services/app.d.ts +2 -1
  167. package/src/services/app.js.map +1 -1
  168. package/src/services/app.ts +2 -1
  169. package/src/services/ios-project.js +12 -6
  170. package/src/services/ios-project.js.map +1 -1
  171. package/src/services/ios-project.ts +12 -6
  172. package/src/services/template.d.ts +3 -2
  173. package/src/services/template.js +2 -1
  174. package/src/services/template.js.map +1 -1
  175. package/src/services/template.ts +13 -20
@@ -34,6 +34,7 @@ import { ProductInitial } from './product-initial.js';
34
34
  import { UtTimer } from '../utils/ut-timer.js';
35
35
  import { AutoFcm } from '../../public-config-initial/auto-fcm.js';
36
36
  import PaymentTransaction from './model/handlePaymentTransaction.js';
37
+ import { Language, LanguageLocation } from '../../Language.js';
37
38
  import { CartItem, CheckoutEvent } from './checkout-event.js';
38
39
 
39
40
  type BindItem = {
@@ -206,16 +207,17 @@ class OrderDetail {
206
207
  custom_form_delivery?: any;
207
208
  shipment:
208
209
  | 'normal'
209
- | 'FAMIC2C'
210
210
  | 'black_cat_freezing'
211
- | 'UNIMARTC2C'
212
- | 'HILIFEC2C'
213
- | 'OKMARTC2C'
214
211
  | 'now'
215
212
  | 'shop'
216
213
  | 'global_express'
217
214
  | 'black_cat'
218
- | 'UNIMARTFREEZE';
215
+ | 'UNIMARTC2C'
216
+ | 'FAMIC2C'
217
+ | 'HILIFEC2C'
218
+ | 'OKMARTC2C'
219
+ | 'UNIMARTFREEZE'
220
+ | 'FAMIC2CFREEZE';
219
221
  CVSStoreName: string;
220
222
  CVSStoreID: string;
221
223
  CVSTelephone: string;
@@ -307,8 +309,6 @@ type Collection = {
307
309
  hidden?: boolean;
308
310
  };
309
311
 
310
-
311
-
312
312
  type MultiSaleType = 'store' | 'level' | 'tags';
313
313
 
314
314
  export type Cart = {
@@ -396,6 +396,8 @@ export class Shopping {
396
396
  max_price?: string;
397
397
  status?: string;
398
398
  channel?: string;
399
+ general_tag?: string;
400
+ manager_tag?: string;
399
401
  whereStore?: string;
400
402
  order_by?: string;
401
403
  id_list?: string;
@@ -424,6 +426,9 @@ export class Shopping {
424
426
  query.language = query.language ?? store_info.language_setting.def;
425
427
  query.show_hidden = query.show_hidden ?? 'true';
426
428
 
429
+ // 初始化商品與管理員標籤 Config
430
+ // await Promise.all([this.initProductCustomizeTagConifg(), this.initProductGeneralTagConifg()]);
431
+
427
432
  const orderMapping: Record<string, string> = {
428
433
  title: `ORDER BY JSON_EXTRACT(content, '$.title')`,
429
434
  max_price: `ORDER BY CAST(JSON_UNQUOTE(JSON_EXTRACT(content, '$.max_price')) AS SIGNED) DESC , id DESC`,
@@ -521,12 +526,12 @@ export class Shopping {
521
526
  // 當非管理員時,檢查是否顯示隱形商品
522
527
  if (query.filter_visible) {
523
528
  if (query.filter_visible === 'true') {
524
- querySql.push(`(content->>'$.visible' is null || content->>'$.visible' = 'true')`);
529
+ querySql.push(`(content->>'$.visible' IS NULL || content->>'$.visible' = 'true')`);
525
530
  } else {
526
531
  querySql.push(`(content->>'$.visible' = 'false')`);
527
532
  }
528
533
  } else if (!query.is_manger && `${query.show_hidden}` !== 'true') {
529
- querySql.push(`(content->>'$.visible' is null || content->>'$.visible' = 'true')`);
534
+ querySql.push(`(content->>'$.visible' IS NULL || content->>'$.visible' = 'true')`);
530
535
  }
531
536
 
532
537
  // 判斷有帶入商品類型時,顯示商品類型,反之預設折是一班商品
@@ -685,6 +690,29 @@ export class Shopping {
685
690
  }
686
691
  }
687
692
 
693
+ if (query.manager_tag) {
694
+ const tagSplit = query.manager_tag.split(',').map(tag => tag.trim());
695
+ if (tagSplit.length > 0) {
696
+ const tagJoin = tagSplit.map(tag => {
697
+ return `JSON_CONTAINS(content->>'$.product_customize_tag', '"${tag}"')`;
698
+ });
699
+ querySql.push(`(${tagJoin.join(' OR ')})`);
700
+ }
701
+ }
702
+
703
+ if (query.general_tag) {
704
+ const tagSplit = query.general_tag.split(',').map(tag => tag.trim());
705
+ if (tagSplit.length > 0) {
706
+ const tagJoin = tagSplit.map(tag => {
707
+ return `(JSON_CONTAINS(
708
+ JSON_EXTRACT(content, '$.product_tag.language."${query.language ?? 'zh-TW'}"'),
709
+ JSON_QUOTE('${tag}')
710
+ ))`;
711
+ });
712
+ querySql.push(`(${tagJoin.join(' OR ')})`);
713
+ }
714
+ }
715
+
688
716
  if (query.id_list && idStr) {
689
717
  querySql.push(`(id in (${idStr}))`);
690
718
  }
@@ -967,6 +995,7 @@ export class Shopping {
967
995
 
968
996
  products.data = foundProduct || products.data[0];
969
997
  }
998
+
970
999
  if (query.id && products.data.length > 0) {
971
1000
  products.data = products.data[0];
972
1001
  }
@@ -1168,6 +1197,175 @@ export class Shopping {
1168
1197
  }
1169
1198
  }
1170
1199
 
1200
+ async initProductCustomizeTagConifg() {
1201
+ try {
1202
+ const managerTags = await new User(this.app).getConfigV2({ key: 'product_manager_tags', user_id: 'manager' });
1203
+ console.log(`initProductCustomizeTagConifg=>getData=>`, managerTags);
1204
+ if (managerTags && Array.isArray(managerTags.list)) {
1205
+ return managerTags;
1206
+ }
1207
+ console.log(
1208
+ `query_sql=>`,
1209
+ `SELECT GROUP_CONCAT(DISTINCT JSON_UNQUOTE(JSON_EXTRACT(content, '$.product_customize_tag')) SEPARATOR ',') AS unique_tags
1210
+ FROM \`${this.app}\`.t_manager_post
1211
+ WHERE JSON_UNQUOTE(JSON_EXTRACT(content, '$.type')) = 'product'`
1212
+ );
1213
+ const getData = await db.query(
1214
+ `
1215
+ SELECT GROUP_CONCAT(DISTINCT JSON_UNQUOTE(JSON_EXTRACT(content, '$.product_customize_tag')) SEPARATOR ',') AS unique_tags
1216
+ FROM \`${this.app}\`.t_manager_post
1217
+ WHERE JSON_UNQUOTE(JSON_EXTRACT(content, '$.type')) = 'product'
1218
+ `,
1219
+ []
1220
+ );
1221
+
1222
+ const unique_tags_string = getData[0]?.unique_tags ?? '';
1223
+ console.log(`JSON_STRING=>`, `[${unique_tags_string}]`);
1224
+ const unique_tags_array = JSON.parse(`[${unique_tags_string}]`);
1225
+ const unique_tags_flot = Array.isArray(unique_tags_array) ? unique_tags_array.flat() : [];
1226
+ const data = { list: [...new Set(unique_tags_flot)] };
1227
+ console.log(`product_manager_tags=>setData=>`, managerTags);
1228
+ await new User(this.app).setConfig({
1229
+ key: 'product_manager_tags',
1230
+ user_id: 'manager',
1231
+ value: data,
1232
+ });
1233
+
1234
+ return data;
1235
+ } catch (error) {
1236
+ throw exception.BadRequestError('BAD_REQUEST', 'Set product customize tag conifg Error:' + error, null);
1237
+ }
1238
+ }
1239
+
1240
+ async setProductCustomizeTagConifg(add_tags: string[]) {
1241
+ const tagConfig = await new User(this.app).getConfigV2({ key: 'product_manager_tags', user_id: 'manager' });
1242
+ const tagList = tagConfig?.list ?? [];
1243
+ const data = { list: [...new Set([...tagList, ...add_tags])] };
1244
+
1245
+ await new User(this.app).setConfig({
1246
+ key: 'product_manager_tags',
1247
+ user_id: 'manager',
1248
+ value: data,
1249
+ });
1250
+
1251
+ return data;
1252
+ }
1253
+
1254
+ async initProductGeneralTagConifg() {
1255
+ try {
1256
+ const generalTags = await new User(this.app).getConfigV2({ key: 'product_general_tags', user_id: 'manager' });
1257
+
1258
+ if (generalTags && Array.isArray(generalTags.list)) {
1259
+ return generalTags;
1260
+ }
1261
+ console.log(`initProductCustomizeTagConifg=>getData=>`, generalTags);
1262
+ const getData = await db.query(
1263
+ `
1264
+ SELECT GROUP_CONCAT(DISTINCT JSON_UNQUOTE(JSON_EXTRACT(content, '$.product_tag.language')) SEPARATOR ',') AS unique_tags
1265
+ FROM \`${this.app}\`.t_manager_post
1266
+ WHERE JSON_UNQUOTE(JSON_EXTRACT(content, '$.type')) = 'product'
1267
+ `,
1268
+ []
1269
+ );
1270
+ const unique_tags_string = getData[0]?.unique_tags ?? '';
1271
+ console.log(`JSON_STRING=>`, `[${unique_tags_string}]`);
1272
+ const unique_tags_array = JSON.parse(`[${unique_tags_string}]`);
1273
+ console.log(`JSON_DATA=>`, unique_tags_array);
1274
+ const unique_tags_flot = Array.isArray(unique_tags_array) ? unique_tags_array.flat() : [];
1275
+ const list: { [k in LanguageLocation]?: string[] } = {};
1276
+
1277
+ unique_tags_flot.map(item => {
1278
+ Language.locationList.map(lang => {
1279
+ list[lang] = [...(list[lang] ?? []), ...item[lang]];
1280
+ });
1281
+ });
1282
+
1283
+ Language.locationList.map(lang => {
1284
+ list[lang] = [...new Set(list[lang])];
1285
+ });
1286
+
1287
+ const data = { list };
1288
+ await new User(this.app).setConfig({
1289
+ key: 'product_general_tags',
1290
+ user_id: 'manager',
1291
+ value: data,
1292
+ });
1293
+
1294
+ return data;
1295
+ } catch (error) {
1296
+ throw exception.BadRequestError('BAD_REQUEST', 'Set product general tag conifg Error:' + error, null);
1297
+ }
1298
+ }
1299
+
1300
+ async setProductGeneralTagConifg(add_tags: { [k in LanguageLocation]: string[] }) {
1301
+ const tagConfig =
1302
+ (await new User(this.app).getConfigV2({ key: 'product_general_tags', user_id: 'manager' })) ??
1303
+ (await this.initProductGeneralTagConifg());
1304
+
1305
+ tagConfig.list ??= {};
1306
+
1307
+ Language.locationList.map(lang => {
1308
+ const originList = tagConfig.list[lang] ?? [];
1309
+ const updateList = add_tags[lang];
1310
+ tagConfig.list[lang] = [...new Set([...originList, ...updateList])];
1311
+ });
1312
+
1313
+ await new User(this.app).setConfig({
1314
+ key: 'product_general_tags',
1315
+ user_id: 'manager',
1316
+ value: tagConfig,
1317
+ });
1318
+
1319
+ return tagConfig;
1320
+ }
1321
+
1322
+ async initOrderCustomizeTagConifg() {
1323
+ try {
1324
+ const managerTags = await new User(this.app).getConfigV2({ key: 'order_manager_tags', user_id: 'manager' });
1325
+
1326
+ if (managerTags && Array.isArray(managerTags.list)) {
1327
+ return managerTags;
1328
+ }
1329
+
1330
+ const getData = await db.query(
1331
+ `
1332
+ SELECT GROUP_CONCAT(DISTINCT JSON_UNQUOTE(JSON_EXTRACT(orderData, '$.tags')) SEPARATOR ',') AS unique_tags
1333
+ FROM \`${this.app}\`.t_checkout
1334
+ WHERE JSON_UNQUOTE(JSON_EXTRACT(orderData, '$.tags')) IS NOT NULL
1335
+ `,
1336
+ []
1337
+ );
1338
+ const unique_tags_string = getData[0]?.unique_tags ?? '';
1339
+ const unique_tags_array = JSON.parse(`[${unique_tags_string}]`);
1340
+ const unique_tags_flot = Array.isArray(unique_tags_array) ? unique_tags_array.flat() : [];
1341
+ const data = { list: [...new Set(unique_tags_flot)] };
1342
+
1343
+ await new User(this.app).setConfig({
1344
+ key: 'order_manager_tags',
1345
+ user_id: 'manager',
1346
+ value: data,
1347
+ });
1348
+
1349
+ return data;
1350
+ } catch (error) {
1351
+ throw exception.BadRequestError('BAD_REQUEST', 'Set order customize tag conifg Error:' + e, null);
1352
+ }
1353
+ }
1354
+
1355
+ async setOrderCustomizeTagConifg(add_tags: string[]) {
1356
+ const tagConfig = await new User(this.app).getConfigV2({ key: 'order_manager_tags', user_id: 'manager' });
1357
+ const tagList = tagConfig?.list ?? [];
1358
+ const data = { list: [...new Set([...tagList, ...add_tags])] };
1359
+
1360
+ await new User(this.app).setConfig({
1361
+ key: 'order_manager_tags',
1362
+ user_id: 'manager',
1363
+ value: data,
1364
+ });
1365
+
1366
+ return data;
1367
+ }
1368
+
1171
1369
  async getAllUseVoucher(userID: any): Promise<VoucherData[]> {
1172
1370
  const now = Date.now();
1173
1371
 
@@ -1739,8 +1937,6 @@ export class Shopping {
1739
1937
  );
1740
1938
  }
1741
1939
 
1742
-
1743
-
1744
1940
  async repayOrder(orderID: string, return_url: string) {
1745
1941
  const app = this.app;
1746
1942
 
@@ -1748,9 +1944,9 @@ export class Shopping {
1748
1944
  try {
1749
1945
  const result = await db.query(
1750
1946
  `
1751
- SELECT *
1752
- FROM \`${app}\`.t_checkout
1753
- WHERE cart_token = ?`,
1947
+ SELECT *
1948
+ FROM \`${app}\`.t_checkout
1949
+ WHERE cart_token = ?`,
1754
1950
  [orderID]
1755
1951
  );
1756
1952
  return result[0];
@@ -1792,7 +1988,7 @@ export class Shopping {
1792
1988
  count: number;
1793
1989
  voucher_id: string;
1794
1990
  }[];
1795
- language?: 'en-US' | 'zh-CN' | 'zh-TW';
1991
+ language?: LanguageLocation;
1796
1992
  pos_info?: any; //POS結帳資訊;
1797
1993
  invoice_select?: string;
1798
1994
  pre_order?: boolean;
@@ -1843,8 +2039,11 @@ export class Shopping {
1843
2039
  ReturnURL: '',
1844
2040
  NotifyURL: '',
1845
2041
  };
2042
+ //現在是new一個新的版本
2043
+ //todo 新增一個fake單號 直接做付款的動作 同時做訂單上的更新把這個付款單號記錄下來
1846
2044
  const newOrderID = Date.now();
1847
2045
  const carData: Cart = {
2046
+ orderID: `${newOrderID}`,
1848
2047
  discount: orderData.discount ?? 0,
1849
2048
  customer_info: orderData.customer_info || {},
1850
2049
  lineItems: orderData.lineItems ?? [],
@@ -1855,7 +2054,6 @@ export class Shopping {
1855
2054
  rebate: orderData.rebate ?? 0,
1856
2055
  goodsWeight: 0,
1857
2056
  use_rebate: orderData.use_rebate || 0,
1858
- orderID: `${newOrderID}`,
1859
2057
  shipment_support: shipment_setting.support as any,
1860
2058
  shipment_info: shipment_setting.info as any,
1861
2059
  shipment_selector: [
@@ -1890,10 +2088,17 @@ export class Shopping {
1890
2088
  fbp: sqlData.fbp as string,
1891
2089
  editRecord: [],
1892
2090
  };
1893
- console.log("orderData.customer_info.payment_select -- " , orderData.customer_info.payment_select);
1894
- const result = await new PaymentTransaction(this.app, orderData.customer_info.payment_select).processPayment(carData);
2091
+ await OrderEvent.insertOrder({
2092
+ cartData: orderData,
2093
+ status: 0,
2094
+ app: this.app,
2095
+ });
2096
+ const result = await new PaymentTransaction(this.app, orderData.customer_info.payment_select).processPayment(
2097
+ carData,
2098
+ return_url
2099
+ );
1895
2100
 
1896
- return result
2101
+ return result;
1897
2102
  }
1898
2103
 
1899
2104
  // return result
@@ -1967,7 +2172,7 @@ export class Shopping {
1967
2172
  if (query.archived === 'true') {
1968
2173
  querySql.push(`(archived="${query.archived}")`);
1969
2174
  } else if (query.archived === 'false') {
1970
- querySql.push(`((archived is null) or (archived!='true'))`);
2175
+ querySql.push(`((archived IS NULL) or (archived!='true'))`);
1971
2176
  }
1972
2177
  //退貨貨款狀態
1973
2178
  query.status && querySql.push(`status IN (${query.status})`);
@@ -2188,6 +2393,57 @@ export class Shopping {
2188
2393
 
2189
2394
  async splitOrder(obj: { orderData: Cart; splitOrderArray: OrderDetail[] }) {
2190
2395
  try {
2396
+ async function processCheckoutsStaggered(
2397
+ splitOrderArray: any[],
2398
+ orderData: any,
2399
+ context: any
2400
+ ): Promise<boolean | { result: string; reason: any }> {
2401
+ const promises = splitOrderArray.map((order, index) => {
2402
+ // 為每個操作返回一個新的 Promise
2403
+ return new Promise<void>((resolve, reject) => {
2404
+ // 可以定義更精確的 resolve 型別,這裡用 void 示意
2405
+ const delay = 1000 * index; // 計算延遲時間
2406
+
2407
+ setTimeout(() => {
2408
+ // 在 setTimeout 回呼中執行非同步操作
2409
+ const payload = {
2410
+ code_array: [],
2411
+ order_id: orderData?.splitOrders?.[index] ?? '',
2412
+ line_items: order.lineItems as any,
2413
+ customer_info: order.customer_info,
2414
+ return_url: '',
2415
+ user_info: order.user_info,
2416
+ discount: order.discount,
2417
+ voucher: order.voucher,
2418
+ total: order.total,
2419
+ pay_status: Number(order.pay_status),
2420
+ };
2421
+
2422
+ // 假設 context.toCheckout 本身返回一個 Promise
2423
+ context
2424
+ .toCheckout(payload, 'split')
2425
+ .then(() => {
2426
+ resolve(); // 當 toCheckout 成功時,resolve 外層的 Promise
2427
+ })
2428
+ .catch((error: any) => {
2429
+ reject(error); // 當 toCheckout 失敗時,reject 外層的 Promise
2430
+ });
2431
+ }, delay); // 使用計算出的延遲
2432
+ });
2433
+ }); // map 結束
2434
+
2435
+ try {
2436
+ await Promise.all(promises);
2437
+ return true; // 全部成功
2438
+ } catch (e) {
2439
+ console.error('處理拆分訂單結帳時至少發生一個錯誤 (從 Promise.all 捕獲):', e);
2440
+ return {
2441
+ result: 'failure',
2442
+ reason: e, // 返回捕獲到的錯誤
2443
+ };
2444
+ }
2445
+ }
2446
+
2191
2447
  const currentTime = new Date().toISOString();
2192
2448
 
2193
2449
  //給定訂單編號 產生 編號A 編號B... 依此類推
@@ -2204,7 +2460,7 @@ export class Shopping {
2204
2460
  return orderIdArray;
2205
2461
  }
2206
2462
 
2207
- //整理原本訂單的總價 優惠卷
2463
+ //整理原本訂單的總價 優惠卷的資訊 方便原本的訂單更新
2208
2464
  function refreshOrder(orderData: Cart, splitOrderArray: OrderDetail[]) {
2209
2465
  const { newTotal, newDiscount } = splitOrderArray.reduce(
2210
2466
  (acc, order) => {
@@ -2231,37 +2487,7 @@ export class Shopping {
2231
2487
  cart_token: orderData.orderID,
2232
2488
  orderData,
2233
2489
  });
2234
- for (const [index, order] of splitOrderArray.entries()) {
2235
- await (new CheckoutEvent(this.app, this.token)).toCheckout(
2236
- {
2237
- code_array: [],
2238
- order_id: orderData?.splitOrders?.[index] ?? '',
2239
- line_items: order.lineItems as any,
2240
- customer_info: order.customer_info,
2241
- return_url: '',
2242
- user_info: order.user_info,
2243
- discount: order.discount,
2244
- voucher: order.voucher,
2245
- total: order.total,
2246
- pay_status: Number(order.pay_status),
2247
- },
2248
- 'split'
2249
- );
2250
- }
2251
-
2252
- // try {
2253
- // await db.query(
2254
- // `UPDATE \`${this.app}\`.t_checkout
2255
- // SET orderData = ?
2256
- // WHERE cart_token = ?;`,
2257
- // [JSON.stringify(orderData), orderData.orderID]
2258
- // );
2259
- // }catch (e:any){
2260
- // console.error(e);
2261
- // throw exception.BadRequestError('BAD_REQUEST', 'putOrder Error:' + e, null);
2262
- // }
2263
-
2264
- return true;
2490
+ return await processCheckoutsStaggered(splitOrderArray, orderData, this);
2265
2491
  } catch (e) {
2266
2492
  throw exception.BadRequestError('BAD_REQUEST', 'splitOrder Error:' + e, null);
2267
2493
  }
@@ -2737,7 +2963,6 @@ export class Shopping {
2737
2963
  // 恢復取消訂單的庫存
2738
2964
  orderData.lineItems = resetLineItems(orderData.lineItems);
2739
2965
  origin.orderData.lineItems = resetLineItems(origin.orderData.lineItems);
2740
-
2741
2966
  // 釋放優惠券
2742
2967
  await this.releaseVoucherHistory(orderData.orderID, orderData.orderStatus === '-1' ? 0 : 1);
2743
2968
 
@@ -2783,7 +3008,14 @@ export class Shopping {
2783
3008
 
2784
3009
  // 當訂單出貨狀態變更,觸發通知事件
2785
3010
  const updateProgress = update.orderData.progress;
2786
- if (prevProgress !== updateProgress) {
3011
+
3012
+ if (
3013
+ updateProgress === 'wait' &&
3014
+ update.orderData.user_info.shipment_number &&
3015
+ update.orderData.user_info.shipment_number !== origin.orderData.user_info.shipment_number
3016
+ ) {
3017
+ await this.sendNotifications(orderData, 'in_stock');
3018
+ } else if (prevProgress !== updateProgress) {
2787
3019
  if (updateProgress === 'shipping') {
2788
3020
  await this.sendNotifications(orderData, 'shipment');
2789
3021
  } else if (updateProgress === 'arrived') {
@@ -2819,6 +3051,11 @@ export class Shopping {
2819
3051
  [updateData, origin.id]
2820
3052
  );
2821
3053
 
3054
+ // 更新訂單現有標籤
3055
+ if (Array.isArray(update.orderData.tags)) {
3056
+ await this.setOrderCustomizeTagConifg(update.orderData.tags);
3057
+ }
3058
+
2822
3059
  // 同步蝦皮商品
2823
3060
  await Promise.all(
2824
3061
  origin.orderData.lineItems.map(async (lineItem: any) => {
@@ -2999,12 +3236,13 @@ export class Shopping {
2999
3236
  /**
3000
3237
  * 寄送同時寄送購買人和寄件人
3001
3238
  * */
3002
- private async sendNotifications(orderData: any, type: 'shipment' | 'arrival') {
3239
+ private async sendNotifications(orderData: any, type: 'shipment' | 'arrival' | 'in_stock') {
3003
3240
  const { lineID } = orderData.customer_info;
3004
3241
  const messages = [];
3005
3242
  const typeMap = {
3006
3243
  shipment: 'shipment',
3007
3244
  arrival: 'shipment-arrival',
3245
+ in_stock: 'in-stock',
3008
3246
  };
3009
3247
 
3010
3248
  if (lineID) {
@@ -3245,12 +3483,19 @@ export class Shopping {
3245
3483
  payment_select?: string;
3246
3484
  is_reconciliation?: boolean;
3247
3485
  reconciliation_status?: string[];
3486
+ manager_tag?: string;
3487
+ member_levels?: string;
3248
3488
  }) {
3249
3489
  try {
3250
- let querySql = ['1=1'];
3251
- let orderString = 'order by id desc';
3252
3490
  const timer = new UtTimer('get-checkout-info');
3253
3491
  timer.checkPoint('start');
3492
+
3493
+ const querySql = ['o.id IS NOT NULL'];
3494
+ let orderString = 'order by created_time desc';
3495
+
3496
+ // 初始化訂單現有標籤
3497
+ await this.initOrderCustomizeTagConifg();
3498
+
3254
3499
  if (query.search && query.searchType) {
3255
3500
  switch (query.searchType) {
3256
3501
  case 'cart_token':
@@ -3305,7 +3550,7 @@ export class Shopping {
3305
3550
  let search: string[] = [];
3306
3551
  query.reconciliation_status!!.map(status => {
3307
3552
  if (status === 'pending_entry') {
3308
- search.push(`total_received is NULL`);
3553
+ search.push(`total_received IS NULL`);
3309
3554
  } else if (status === 'completed_entry') {
3310
3555
  search.push(`total_received = total`);
3311
3556
  } else if (status === 'refunded') {
@@ -3313,9 +3558,9 @@ export class Shopping {
3313
3558
  } else if (status === 'completed_offset') {
3314
3559
  search.push(`(total_received < total) && ((total_received + offset_amount) = total)`);
3315
3560
  } else if (status === 'pending_offset') {
3316
- search.push(`(total_received < total) && (offset_amount is null)`);
3561
+ search.push(`(total_received < total) && (offset_amount IS NULL)`);
3317
3562
  } else if (status === 'pending_refund') {
3318
- search.push(`(total_received > total) && (offset_amount is null)`);
3563
+ search.push(`(total_received > total) && (offset_amount IS NULL)`);
3319
3564
  }
3320
3565
  });
3321
3566
  querySql.push(
@@ -3326,6 +3571,7 @@ export class Shopping {
3326
3571
  .join(' or ')})`
3327
3572
  );
3328
3573
  }
3574
+
3329
3575
  if (query.orderStatus) {
3330
3576
  let orderArray = query.orderStatus.split(',');
3331
3577
  let temp = '';
@@ -3341,12 +3587,15 @@ export class Shopping {
3341
3587
 
3342
3588
  querySql.push(countingSQL);
3343
3589
  }
3590
+
3344
3591
  if (query.is_shipment) {
3345
3592
  querySql.push(`(shipment_number IS NOT NULL) and (shipment_number != '')`);
3346
3593
  }
3594
+
3347
3595
  if (query.is_reconciliation) {
3348
3596
  querySql.push(`((o.status in (1,-2)) or ((payment_method='cash_on_delivery' and progress='finish') ))`);
3349
3597
  }
3598
+
3350
3599
  if (query.payment_select) {
3351
3600
  querySql.push(
3352
3601
  `payment_method in (${query.payment_select
@@ -3355,13 +3604,14 @@ export class Shopping {
3355
3604
  .join(',')})`
3356
3605
  );
3357
3606
  }
3607
+
3358
3608
  if (query.progress) {
3359
3609
  //備貨中
3360
3610
  if (query.progress === 'in_stock') {
3361
3611
  query.progress = 'wait';
3362
3612
  querySql.push(`shipment_number is NOT null`);
3363
3613
  } else if (query.progress === 'wait') {
3364
- querySql.push(`shipment_number is null`);
3614
+ querySql.push(`shipment_number IS NULL`);
3365
3615
  }
3366
3616
  let newArray = query.progress.split(',');
3367
3617
  let temp = '';
@@ -3371,6 +3621,7 @@ export class Shopping {
3371
3621
  temp += `progress IN (${newArray.map(status => `"${status}"`).join(',')})`;
3372
3622
  querySql.push(`(${temp})`);
3373
3623
  }
3624
+
3374
3625
  if (query.distribution_code) {
3375
3626
  let codes = query.distribution_code.split(',');
3376
3627
  let temp = '';
@@ -3381,8 +3632,9 @@ export class Shopping {
3381
3632
  if (query.is_pos === 'true') {
3382
3633
  querySql.push(`order_source='POS'`);
3383
3634
  } else if (query.is_pos === 'false') {
3384
- querySql.push(`(order_source!='POS' or order_source is null)`);
3635
+ querySql.push(`(order_source!='POS' or order_source IS NULL)`);
3385
3636
  }
3637
+
3386
3638
  if (query.shipment) {
3387
3639
  let shipment = query.shipment.split(',');
3388
3640
  let temp = '';
@@ -3402,6 +3654,7 @@ export class Shopping {
3402
3654
  `);
3403
3655
  }
3404
3656
  }
3657
+
3405
3658
  if (query.shipment_time) {
3406
3659
  const shipment_time = query.shipment_time.split(',');
3407
3660
  if (shipment_time.length > 1) {
@@ -3428,37 +3681,104 @@ export class Shopping {
3428
3681
  break;
3429
3682
  }
3430
3683
  }
3431
- query.status && querySql.push(`o.status IN (${query.status})`);
3432
- const orderMath = [];
3433
3684
 
3434
- // JSON_EXTRACT(orderData, '$.customer_info.phone')
3685
+ if (query.manager_tag) {
3686
+ const tagSplit = query.manager_tag.split(',').map(tag => tag.trim());
3687
+ if (tagSplit.length > 0) {
3688
+ const tagJoin = tagSplit.map(tag => {
3689
+ return `JSON_CONTAINS(orderData->>'$.tags', '"${tag}"')`;
3690
+ });
3691
+ querySql.push(`(${tagJoin.join(' OR ')})`);
3692
+ }
3693
+ }
3694
+
3695
+ if (query.status) {
3696
+ querySql.push(`o.status IN (${query.status})`);
3697
+ }
3698
+
3699
+ const orderMath = [];
3435
3700
  query.email && orderMath.push(`(email=${db.escape(query.email)})`);
3436
3701
  query.phone && orderMath.push(`(email=${db.escape(query.phone)})`);
3437
3702
  if (orderMath.length) {
3438
- querySql.push(`(${orderMath.join(' or ')})`);
3703
+ querySql.push(`(${orderMath.join(' OR ')})`);
3704
+ }
3705
+
3706
+ if (query.member_levels) {
3707
+ let temp: string[] = [];
3708
+ const queryLevel = query.member_levels.split(',');
3709
+ const queryIdLevel = queryLevel.filter(level => level !== 'null');
3710
+
3711
+ if (queryLevel.includes('null')) {
3712
+ temp = [`u.member_level IS NULL`, `u.member_level = ''`];
3713
+ }
3714
+
3715
+ if (queryIdLevel.length > 0) {
3716
+ temp = [
3717
+ ...temp,
3718
+ `u.member_level IN (${queryIdLevel
3719
+ .map(level => {
3720
+ return db.escape(level);
3721
+ })
3722
+ .join(',')})`,
3723
+ ];
3724
+ }
3725
+
3726
+ if (temp.length > 0) {
3727
+ querySql.push(`(${temp.join(' OR ')})`);
3728
+ }
3439
3729
  }
3440
3730
 
3441
3731
  if (query.filter_type === 'true' || query.archived) {
3442
3732
  if (query.archived === 'true') {
3443
- querySql.push(`(archived="${query.archived}")
3444
- AND (order_status IS NULL OR order_status NOT IN (-99))`);
3733
+ querySql.push(`(archived="${query.archived}") AND (order_status IS NULL OR order_status NOT IN (-99))`);
3445
3734
  } else {
3446
- querySql.push(`((archived="${query.archived}") or (archived is null))`);
3735
+ querySql.push(`((archived="${query.archived}") or (archived IS NULL))`);
3447
3736
  }
3448
3737
  } else if (query.filter_type === 'normal') {
3449
- querySql.push(`((archived is null) or (archived!='true'))`);
3738
+ querySql.push(`((archived IS NULL) or (archived!='true'))`);
3450
3739
  }
3740
+
3451
3741
  if (!(query.filter_type === 'true' || query.archived)) {
3452
- querySql.push(`((order_status is null) or (order_status NOT IN (-99)))`);
3453
- }
3454
- let sql = `SELECT i.invoice_no,
3455
- i.invoice_data,
3456
- i.\`status\` as invoice_status,
3457
- o.*
3458
- FROM \`${this.app}\`.t_checkout o
3459
- LEFT JOIN \`${this.app}\`.t_invoice_memory i ON o.cart_token = i.order_id and i.status = 1
3460
- WHERE ${querySql.join(' and ')} ${orderString}`;
3461
- timer.checkPoint('start-query-sql');
3742
+ querySql.push(`((order_status IS NULL) or (order_status NOT IN (-99)))`);
3743
+ }
3744
+
3745
+ // 定義基礎查詢結構
3746
+ const baseSelect = `
3747
+ SELECT
3748
+ o.*,
3749
+ i.invoice_no,
3750
+ i.invoice_data,
3751
+ i.\`status\` as invoice_status
3752
+ FROM`;
3753
+
3754
+ const joinClause = `LEFT JOIN \`${this.app}\`.t_invoice_memory i ON o.cart_token = i.order_id AND i.status = 1`;
3755
+ const whereClause = `WHERE ${querySql.join(' AND ')}`;
3756
+
3757
+ let sql: string;
3758
+
3759
+ if (query.member_levels) {
3760
+ // 查詢會員等級資料
3761
+ sql = `
3762
+ (
3763
+ (
3764
+ ${baseSelect} \`${this.app}\`.t_user u
3765
+ LEFT JOIN \`${this.app}\`.t_checkout o ON o.email = u.phone
3766
+ ${joinClause}
3767
+ ${whereClause}
3768
+ )
3769
+ UNION
3770
+ (
3771
+ ${baseSelect} \`${this.app}\`.t_user u
3772
+ LEFT JOIN \`${this.app}\`.t_checkout o ON o.email = u.email
3773
+ ${joinClause}
3774
+ ${whereClause}
3775
+ )
3776
+ ) ${orderString}`;
3777
+ } else {
3778
+ // 直接查詢結帳資料
3779
+ sql = `${baseSelect} \`${this.app}\`.t_checkout o ${joinClause} ${whereClause} ${orderString}`;
3780
+ }
3781
+
3462
3782
  if (query.returnSearch == 'true') {
3463
3783
  const data = await db.query(
3464
3784
  `SELECT *
@@ -3487,8 +3807,8 @@ export class Shopping {
3487
3807
  }
3488
3808
  return data[0];
3489
3809
  }
3490
- const response_data: any = await new Promise(async (resolve, reject) => {
3491
- timer.checkPoint('start-query-response_data');
3810
+
3811
+ const response_data: any = await new Promise(async resolve => {
3492
3812
  if (query.id) {
3493
3813
  const data = (
3494
3814
  await db.query(
@@ -3498,6 +3818,7 @@ export class Shopping {
3498
3818
  []
3499
3819
  )
3500
3820
  )[0];
3821
+ timer.checkPoint('get response_data (has query.id)');
3501
3822
  resolve({
3502
3823
  data: data,
3503
3824
  result: !!data,
@@ -3509,21 +3830,20 @@ export class Shopping {
3509
3830
  `,
3510
3831
  []
3511
3832
  );
3512
- timer.checkPoint('finish-query-response_data');
3513
- console.log(sql);
3833
+ timer.checkPoint('get response_data (not query.id)');
3514
3834
  resolve({
3515
3835
  data: data,
3516
3836
  total: (
3517
3837
  await db.query(
3518
3838
  `SELECT count(1)
3519
- FROM (${sql}) as subqyery
3520
- `,
3839
+ FROM (${sql}) as subqyery`,
3521
3840
  []
3522
3841
  )
3523
3842
  )[0]['count(1)'],
3524
3843
  });
3525
3844
  }
3526
3845
  });
3846
+
3527
3847
  const obMap = Array.isArray(response_data.data) ? response_data.data : [response_data.data];
3528
3848
  const keyData = (
3529
3849
  await Private_config.getConfig({
@@ -3531,6 +3851,7 @@ export class Shopping {
3531
3851
  key: 'glitter_finance',
3532
3852
  })
3533
3853
  )[0].value;
3854
+
3534
3855
  await Promise.all(
3535
3856
  obMap
3536
3857
  .map(async (order: any) => {
@@ -3543,9 +3864,7 @@ export class Shopping {
3543
3864
  order.orderData.cash_flow = (
3544
3865
  await new PayNow(this.app, keyData['paynow']).confirmAndCaptureOrder(order.orderData.paynow_id)
3545
3866
  ).result;
3546
- }catch (e) {
3547
-
3548
- }
3867
+ } catch (e) {}
3549
3868
  }
3550
3869
  if (order.orderData.user_info.shipment_refer === 'paynow') {
3551
3870
  const pay_now = new PayNowLogistics(this.app);
@@ -3601,7 +3920,7 @@ export class Shopping {
3601
3920
  page: 0,
3602
3921
  limit: 1,
3603
3922
  search: order.cart_token,
3604
- searchType: order.orderData.order_number,
3923
+ searchType: order.orderData?.order_number,
3605
3924
  })
3606
3925
  ).data[0];
3607
3926
  order.invoice_number = invoice && invoice.invoice_no;
@@ -3614,7 +3933,9 @@ export class Shopping {
3614
3933
  })
3615
3934
  )
3616
3935
  );
3936
+
3617
3937
  timer.checkPoint('finish-query-all');
3938
+
3618
3939
  return response_data;
3619
3940
  } catch (e) {
3620
3941
  throw exception.BadRequestError('BAD_REQUEST', 'getCheckOut Error:' + e, null);
@@ -3967,31 +4288,40 @@ export class Shopping {
3967
4288
  } else if (Object.keys(variant.stockList).length === 0) {
3968
4289
  variant.stockList[storeConfig.list[0].id] = { count: variant.stock };
3969
4290
  }
4291
+ const insertObj:any = {
4292
+ content: JSON.stringify(variant),
4293
+ product_id: content.id,
4294
+ };
4295
+ const originalVariant = originVariants.find(
4296
+ (item: any) => JSON.parse(item.spec).join(',') === variant.spec.join(',')
4297
+ );
4298
+
4299
+ //如果有找到原先的variant不要替換掉ID
4300
+ if (originalVariant) {
4301
+ insertObj.id = originalVariant.id;
4302
+ sourceMap[originalVariant.id] = originalVariant.id;
4303
+ }
3970
4304
 
3971
4305
  const insertData = await db.query(
3972
4306
  `INSERT INTO \`${this.app}\`.t_variants
3973
4307
  SET ?
3974
4308
  `,
3975
- [
3976
- {
3977
- content: JSON.stringify(variant),
3978
- product_id: content.id,
3979
- },
3980
- ]
4309
+ [insertObj]
3981
4310
  );
3982
4311
 
3983
- const originalVariant = originVariants.find(
3984
- (item: any) => JSON.parse(item.spec).join(',') === variant.spec.join(',')
3985
- );
3986
-
3987
- if (originalVariant) {
3988
- sourceMap[originalVariant.id] = insertData.insertId;
3989
- }
3990
4312
 
3991
4313
  return insertData;
3992
4314
  });
3993
4315
 
3994
- await Promise.all(insertPromises);
4316
+ const chunk = 10;
4317
+ const chunkLength = Math.ceil(insertPromises.length / chunk);
4318
+
4319
+ for (let i = 0; i < chunkLength; i++) {
4320
+ const promisesArray = insertPromises.slice(i * chunk, (i + 1) * chunk);
4321
+ setTimeout(async () => {
4322
+ await Promise.all(promisesArray);
4323
+ }, 200);
4324
+ }
3995
4325
 
3996
4326
  const exhibitionConfig = await _user.getConfigV2({ key: 'exhibition_manager', user_id: 'manager' });
3997
4327
  exhibitionConfig.list = exhibitionConfig.list ?? [];
@@ -4679,6 +5009,7 @@ export class Shopping {
4679
5009
  delete product['content'];
4680
5010
  delete product['preview_image'];
4681
5011
  const og_content = og_data['content'];
5012
+
4682
5013
  if (og_content.language_data && og_content.language_data[store_info.language_setting.def]) {
4683
5014
  og_content.language_data[store_info.language_setting.def].seo = product.seo;
4684
5015
  og_content.language_data[store_info.language_setting.def].title = product.title;
@@ -4692,10 +5023,10 @@ export class Shopping {
4692
5023
  product.preview_image = og_data['content'].preview_image || [];
4693
5024
  productArray[index] = product;
4694
5025
  } else {
4695
- console.error('Product id not exist:', product);
5026
+ console.error('Product id not exist:', product.title);
4696
5027
  }
4697
5028
  } else {
4698
- console.error('Product has not id:', product);
5029
+ console.error('Product has not id:', product.title);
4699
5030
  }
4700
5031
  resolve(true);
4701
5032
  });
@@ -4729,8 +5060,9 @@ export class Shopping {
4729
5060
 
4730
5061
  if (productArray.length) {
4731
5062
  const data = await db.query(
4732
- `replace
4733
- INTO \`${this.app}\`.\`t_manager_post\` (id,userID,content) values ?`,
5063
+ `REPLACE
5064
+ INTO \`${this.app}\`.\`t_manager_post\` (id,userID,content) values ?
5065
+ `,
4734
5066
  [
4735
5067
  productArray.map((product: any) => {
4736
5068
  if (!product.id) {
@@ -4759,37 +5091,57 @@ export class Shopping {
4759
5091
  product.id = product.id || insertIDStart++;
4760
5092
  return new Shopping(this.app, this.token).postVariantsAndPriceValue(product);
4761
5093
  });
4762
- await Promise.all(promises);
4763
- }
4764
5094
 
4765
- async putProduct(content: any) {
4766
- if (content.language_data) {
4767
- const language = await App.getSupportLanguage(this.app);
4768
- for (const b of language) {
4769
- const find_conflict = await db.query(
4770
- `select count(1)
4771
- from \`${this.app}\`.\`t_manager_post\`
4772
- where content ->>'$.language_data."${b}".seo.domain'='${decodeURIComponent(content.language_data[b].seo.domain)}'
4773
- and id != ${content.id}`,
4774
- []
4775
- );
4776
- if (find_conflict[0]['count(1)'] > 0) {
4777
- throw exception.BadRequestError('BAD_REQUEST', 'DOMAIN ALREADY EXISTS:', {
4778
- message: '網域已被使用',
4779
- code: '733',
4780
- });
4781
- }
4782
- }
5095
+ const chunk = 10;
5096
+ const chunkLength = Math.ceil(promises.length / chunk);
5097
+
5098
+ for (let i = 0; i < chunkLength; i++) {
5099
+ const promisesArray = promises.slice(i * chunk, (i + 1) * chunk);
5100
+ setTimeout(async () => {
5101
+ await Promise.all(promisesArray);
5102
+ }, 200);
4783
5103
  }
5104
+ }
4784
5105
 
5106
+ async putProduct(content: any) {
4785
5107
  try {
4786
5108
  content.type = 'product';
4787
5109
 
5110
+ // 檢查 seo domain 是否重複
5111
+ if (content.language_data) {
5112
+ const language = await App.getSupportLanguage(this.app);
5113
+ for (const b of language) {
5114
+ const find_conflict = await db.query(
5115
+ `SELECT count(1)
5116
+ FROM \`${this.app}\`.t_manager_post
5117
+ WHERE content ->>'$.language_data."${b}".seo.domain'='${decodeURIComponent(content.language_data[b].seo.domain)}'
5118
+ AND id != ${content.id}`,
5119
+ []
5120
+ );
5121
+ if (find_conflict[0]['count(1)'] > 0) {
5122
+ throw exception.BadRequestError('BAD_REQUEST', 'DOMAIN ALREADY EXISTS:', {
5123
+ message: '網域已被使用',
5124
+ code: '733',
5125
+ });
5126
+ }
5127
+ }
5128
+ }
5129
+
5130
+ // 檢查 Variant 資料屬性
4788
5131
  this.checkVariantDataType(content.variants);
4789
- const data = await db.query(
4790
- `update \`${this.app}\`.\`t_manager_post\`
5132
+
5133
+ // 重新設置管理員標籤
5134
+ await Promise.all([
5135
+ this.setProductCustomizeTagConifg(content.product_customize_tag ?? []),
5136
+ this.setProductGeneralTagConifg(content.product_tag?.language ?? []),
5137
+ ]);
5138
+
5139
+ // 更新商品
5140
+ await db.query(
5141
+ `UPDATE \`${this.app}\`.\`t_manager_post\`
4791
5142
  SET ?
4792
- where id = ?`,
5143
+ WHERE id = ?
5144
+ `,
4793
5145
  [
4794
5146
  {
4795
5147
  content: JSON.stringify(content),
@@ -4797,7 +5149,11 @@ export class Shopping {
4797
5149
  content.id,
4798
5150
  ]
4799
5151
  );
5152
+
5153
+ // 更新商品 Variant
4800
5154
  await new Shopping(this.app, this.token).postVariantsAndPriceValue(content);
5155
+
5156
+ // 同步更新蝦皮
4801
5157
  if (content.shopee_id) {
4802
5158
  await new Shopee(this.app, this.token).asyncStockToShopee({
4803
5159
  product: {
@@ -5000,9 +5356,11 @@ export class Shopping {
5000
5356
  query.id && querySql.push(`(v.id = ${query.id})`);
5001
5357
  if (query.id_list) {
5002
5358
  if (query.id_list?.includes('-')) {
5003
- querySql.push(`(v.product_id in (${query.id_list.split(',').map((dd)=>{
5004
- return dd.split('-')[0]
5005
- })}))`);
5359
+ querySql.push(
5360
+ `(v.product_id in (${query.id_list.split(',').map(dd => {
5361
+ return dd.split('-')[0];
5362
+ })}))`
5363
+ );
5006
5364
  } else {
5007
5365
  querySql.push(`(v.id in (${query.id_list}))`);
5008
5366
  }
@@ -5102,11 +5460,11 @@ export class Shopping {
5102
5460
  if (query.id_list) {
5103
5461
  //過濾出需要的商品規格
5104
5462
  if (query.id_list?.includes('-')) {
5105
- data.data=data.data.filter((dd:any)=>{
5106
- return query.id_list?.split(',').find((d1)=>{
5107
- return d1 === [dd.product_id,...dd.variant_content.spec].join('-')
5108
- })
5109
- })
5463
+ data.data = data.data.filter((dd: any) => {
5464
+ return query.id_list?.split(',').find(d1 => {
5465
+ return d1 === [dd.product_id, ...dd.variant_content.spec].join('-');
5466
+ });
5467
+ });
5110
5468
  }
5111
5469
  }
5112
5470
  const shopee_data_list: { id: string; data: any }[] = [];
@@ -5208,8 +5566,8 @@ export class Shopping {
5208
5566
  let variants = (
5209
5567
  await db.query(
5210
5568
  `SELECT *
5211
- FROM \`${this.app}\`.t_variants
5212
- WHERE product_id = ?`,
5569
+ FROM \`${this.app}\`.t_variants
5570
+ WHERE product_id = ?`,
5213
5571
  [data.product_id]
5214
5572
  )
5215
5573
  ).map((dd: any) => {