ts-glitter 16.4.2 → 16.4.3

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 (52) hide show
  1. package/lowcode/Entry.js +3 -3
  2. package/lowcode/Entry.ts +3 -3
  3. package/lowcode/cms-plugin/module/order-setting.js +20 -2
  4. package/lowcode/cms-plugin/module/order-setting.ts +19 -2
  5. package/lowcode/cms-plugin/module/product-excel.js +32 -27
  6. package/lowcode/cms-plugin/module/product-excel.ts +40 -32
  7. package/lowcode/cms-plugin/module/product-setting.js +21 -5
  8. package/lowcode/cms-plugin/module/product-setting.ts +21 -5
  9. package/lowcode/cms-plugin/shopping-product-setting.ts +0 -1
  10. package/lowcode/cms-plugin/stock-history.js +1467 -540
  11. package/lowcode/cms-plugin/stock-history.ts +1530 -556
  12. package/lowcode/css/editor.css +8 -2
  13. package/lowcode/glitter-base/route/stock.js +1 -0
  14. package/lowcode/glitter-base/route/stock.ts +11 -2
  15. package/lowcode/jspage/function-page/setting_editor.ts +8 -0
  16. package/package.json +1 -1
  17. package/src/api-public/controllers/index.js +5 -0
  18. package/src/api-public/controllers/index.js.map +1 -1
  19. package/src/api-public/controllers/index.ts +5 -0
  20. package/src/api-public/controllers/shopee.d.ts +3 -0
  21. package/src/api-public/controllers/shopee.js +8 -0
  22. package/src/api-public/controllers/shopee.js.map +1 -0
  23. package/src/api-public/controllers/shopee.ts +45 -0
  24. package/src/api-public/controllers/stock.js +1 -0
  25. package/src/api-public/controllers/stock.js.map +1 -1
  26. package/src/api-public/controllers/stock.ts +1 -0
  27. package/src/api-public/services/ai-pointes.js.map +1 -1
  28. package/src/api-public/services/fake-data-model/fake-order.js.map +1 -1
  29. package/src/api-public/services/fake-data-model/fake-product.js.map +1 -1
  30. package/src/api-public/services/shopee.d.ts +7 -0
  31. package/src/api-public/services/shopee.js +19 -0
  32. package/src/api-public/services/shopee.js.map +1 -0
  33. package/src/api-public/services/shopee.ts +37 -0
  34. package/src/api-public/services/shopping.js +16 -2
  35. package/src/api-public/services/shopping.js.map +1 -1
  36. package/src/api-public/services/shopping.ts +23 -2
  37. package/src/api-public/services/sms-pointes.js.map +1 -1
  38. package/src/api-public/services/stock.d.ts +10 -1
  39. package/src/api-public/services/stock.js +136 -7
  40. package/src/api-public/services/stock.js.map +1 -1
  41. package/src/api-public/services/stock.ts +174 -17
  42. package/src/api-public/services/wallet.js.map +1 -1
  43. package/src/config.d.ts +2 -0
  44. package/src/config.js +2 -0
  45. package/src/config.js.map +1 -1
  46. package/src/config.ts +2 -0
  47. package/src/modules/tool.d.ts +1 -0
  48. package/src/modules/tool.js +12 -1
  49. package/src/modules/tool.js.map +1 -1
  50. package/src/modules/tool.ts +13 -114
  51. package/src/services/saas-table-check.js +2 -2
  52. package/src/services/saas-table-check.js.map +1 -1
@@ -32,52 +32,83 @@ type VM = {
32
32
  const typeConfig: {
33
33
  [key in StockHistoryType]: {
34
34
  name: string;
35
+ status: {
36
+ [key in number]: {
37
+ title: string;
38
+ badge: string;
39
+ };
40
+ };
35
41
  };
36
42
  } = {
37
43
  restocking: {
38
44
  name: '進貨',
45
+ status: {
46
+ 0: {
47
+ title: '已完成',
48
+ badge: 'info',
49
+ },
50
+ 1: {
51
+ title: '已補貨',
52
+ badge: 'info',
53
+ },
54
+ 2: {
55
+ title: '待進貨',
56
+ badge: 'warning',
57
+ },
58
+ 3: {
59
+ title: '核對中',
60
+ badge: 'warning',
61
+ },
62
+ 4: {
63
+ title: '已暫停',
64
+ badge: 'normal',
65
+ },
66
+ 5: {
67
+ title: '待補貨',
68
+ badge: 'notify',
69
+ },
70
+ 6: {
71
+ title: '已取消',
72
+ badge: 'notify',
73
+ },
74
+ },
39
75
  },
40
76
  transfer: {
41
77
  name: '調撥',
78
+ status: {
79
+ 0: {
80
+ title: '已完成',
81
+ badge: 'info',
82
+ },
83
+ 1: {
84
+ title: '已補貨',
85
+ badge: 'info',
86
+ },
87
+ 2: {
88
+ title: '待調撥',
89
+ badge: 'warning',
90
+ },
91
+ 3: {
92
+ title: '核對中',
93
+ badge: 'warning',
94
+ },
95
+ 4: {
96
+ title: '已暫停',
97
+ badge: 'normal',
98
+ },
99
+ 5: {
100
+ title: '待補貨',
101
+ badge: 'notify',
102
+ },
103
+ 6: {
104
+ title: '已取消',
105
+ badge: 'notify',
106
+ },
107
+ },
42
108
  },
43
109
  checking: {
44
110
  name: '盤點',
45
- },
46
- };
47
-
48
- const statusConfig: {
49
- [key in number]: {
50
- title: string;
51
- badge: string;
52
- };
53
- } = {
54
- 0: {
55
- title: '已完成',
56
- badge: 'info',
57
- },
58
- 1: {
59
- title: '已補貨',
60
- badge: 'info',
61
- },
62
- 2: {
63
- title: '待進貨',
64
- badge: 'warning',
65
- },
66
- 3: {
67
- title: '核對中',
68
- badge: 'warning',
69
- },
70
- 4: {
71
- title: '已暫停',
72
- badge: 'normal',
73
- },
74
- 5: {
75
- title: '待補貨',
76
- badge: 'notify',
77
- },
78
- 6: {
79
- title: '已取消',
80
- badge: 'notify',
111
+ status: {},
81
112
  },
82
113
  };
83
114
 
@@ -89,7 +120,7 @@ export class StockHistory {
89
120
  return {
90
121
  id: '',
91
122
  type: type,
92
- status: 2, // 新建立的訂單送出時,狀態為「待進貨」
123
+ status: 2, // 新建立的訂單送出時,狀態為「2」
93
124
  order_id: '',
94
125
  created_time: '',
95
126
  content: {
@@ -100,6 +131,7 @@ export class StockHistory {
100
131
  check_according: 'all',
101
132
  note: '',
102
133
  product_list: [],
134
+ changeLogs: [],
103
135
  },
104
136
  };
105
137
  };
@@ -132,7 +164,28 @@ export class StockHistory {
132
164
  }
133
165
 
134
166
  if (vm.view === 'replace') {
135
- return this.replaceOrder(gvc, vm);
167
+ const glitter = gvc.glitter;
168
+ const dialog = new ShareDialog(glitter);
169
+ dialog.dataLoading({ visible: true });
170
+ return new Promise<StockHistoryData>((resolve) => {
171
+ ApiStock.getStockHistory({
172
+ page: 0,
173
+ limit: 1,
174
+ order_id: vm.data.order_id,
175
+ search: '',
176
+ type: vm.data.type,
177
+ }).then((r) => {
178
+ if (r.result && r.response.data[0]) {
179
+ resolve(r.response.data[0]);
180
+ } else {
181
+ resolve(emptyData());
182
+ }
183
+ });
184
+ }).then((data) => {
185
+ dialog.dataLoading({ visible: false });
186
+ vm.data = data;
187
+ return this.replaceOrder(gvc, vm);
188
+ });
136
189
  }
137
190
 
138
191
  if (vm.view === 'create') {
@@ -151,40 +204,87 @@ export class StockHistory {
151
204
  vm.filter = ListComp.getFilterObject();
152
205
  let vmi: any = undefined;
153
206
 
207
+ // 列表表格資料
154
208
  function getDatalist() {
155
209
  return vm.dataList.map((dd: StockHistoryData) => {
156
- return [
157
- {
158
- key: '進貨單編號',
159
- value: `<span class="fs-7">${dd.order_id}</span>`,
160
- },
161
- {
162
- key: '進貨日期',
163
- value: `<span class="fs-7">${dd.created_time}</span>`,
164
- },
165
- {
166
- key: '庫存點名稱',
167
- value: `<span class="fs-7">${(() => {
168
- const store = vm.storeList.find((s) => s.id === dd.content.store_in);
169
- return store ? store.name : '';
170
- })()}</span>`,
171
- },
172
- {
173
- key: '總金額',
174
- value: `<span class="fs-7">$ ${(dd.content.total_price || 0).toLocaleString()}</span>`,
175
- },
176
- {
177
- key: '供應商',
178
- value: `<span class="fs-7">${(() => {
179
- const vendor = vm.vendorList.find((v) => v.id === dd.content.vendor);
180
- return vendor ? vendor.name : '';
181
- })()}</span>`,
182
- },
183
- {
184
- key: '進貨狀態',
185
- value: `<span class="fs-7">${StockHistory.getStatusBadge(dd.status)}</span>`,
186
- },
187
- ];
210
+ switch (dd.type) {
211
+ case 'restocking':
212
+ return [
213
+ {
214
+ key: `${typeData.name}單編號`,
215
+ value: `<span class="fs-7">${dd.order_id}</span>`,
216
+ },
217
+ {
218
+ key: `${typeData.name}日期`,
219
+ value: `<span class="fs-7">${dd.created_time}</span>`,
220
+ },
221
+ {
222
+ key: '庫存點名稱',
223
+ value: html`<span class="fs-7"
224
+ >${(() => {
225
+ const store = vm.storeList.find((s) => s.id === dd.content.store_in);
226
+ return store ? store.name : '';
227
+ })()}</span
228
+ >`,
229
+ },
230
+ {
231
+ key: '總金額',
232
+ value: `<span class="fs-7">$ ${(dd.content.total_price || 0).toLocaleString()}</span>`,
233
+ },
234
+ {
235
+ key: '供應商',
236
+ value: html`<span class="fs-7"
237
+ >${(() => {
238
+ const vendor = vm.vendorList.find((v) => v.id === dd.content.vendor);
239
+ return vendor ? vendor.name : '';
240
+ })()}</span
241
+ >`,
242
+ },
243
+ {
244
+ key: `${typeData.name}狀態`,
245
+ value: `<span class="fs-7">${StockHistory.getStatusBadge(dd.type, dd.status)}</span>`,
246
+ },
247
+ ];
248
+ case 'transfer':
249
+ return [
250
+ {
251
+ key: `${typeData.name}單編號`,
252
+ value: `<span class="fs-7">${dd.order_id}</span>`,
253
+ },
254
+ {
255
+ key: `${typeData.name}日期`,
256
+ value: `<span class="fs-7">${dd.created_time}</span>`,
257
+ },
258
+ {
259
+ key: '調出庫存點',
260
+ value: html`<span class="fs-7"
261
+ >${(() => {
262
+ const store = vm.storeList.find((s) => s.id === dd.content.store_out);
263
+ return store ? store.name : '';
264
+ })()}</span
265
+ >`,
266
+ },
267
+ {
268
+ key: '調入庫存點',
269
+ value: html`<span class="fs-7"
270
+ >${(() => {
271
+ const store = vm.storeList.find((s) => s.id === dd.content.store_in);
272
+ return store ? store.name : '';
273
+ })()}</span
274
+ >`,
275
+ },
276
+ {
277
+ key: '備註',
278
+ value: `<span class="fs-7">${dd.content.note}</span>`,
279
+ },
280
+ {
281
+ key: `${typeData.name}狀態`,
282
+ value: `<span class="fs-7">${StockHistory.getStatusBadge(dd.type, dd.status)}</span>`,
283
+ },
284
+ ];
285
+ case 'checking':
286
+ return [];
287
+ }
188
288
  });
189
289
  }
190
290
 
@@ -327,12 +427,12 @@ export class StockHistory {
327
427
  type: 'all',
328
428
  };
329
429
 
330
- function specDatalist(page: number, limit: number) {
430
+ function checkSpecTable(page: number, limit: number) {
331
431
  const x = (page - 1) * limit;
332
432
  const specs = vm.data.content.product_list.slice(x, x + limit);
333
433
  return specs.map((dd: ContentProduct, index: number) => {
334
434
  const realData = vm.data.content.product_list[x + index];
335
- return [
435
+ const startArr = [
336
436
  {
337
437
  key: '商品',
338
438
  value: `<span class="fs-7">${dd.title || '-'}</span>`,
@@ -349,32 +449,8 @@ export class StockHistory {
349
449
  key: '商品條碼',
350
450
  value: `<span class="fs-7">${dd.sku || '-'}</span>`,
351
451
  },
352
- {
353
- key: '原定進貨數量',
354
- value: `<span class="fs-7">${dd.transfer_count ?? 0}</span>`,
355
- },
356
- {
357
- key: '實際到貨數量',
358
- value: html` <div style="width: 100px" onclick="${gvc.event((e, event) => event.stopPropagation())}">
359
- <input
360
- class="form-control"
361
- type="number"
362
- min="0"
363
- style="border-radius: 10px; border: 1px solid #DDD; padding-left: 18px;"
364
- onchange="${gvc.event((e) => {
365
- let n = parseInt(e.value, 10);
366
- if (n < 0) {
367
- n = 0;
368
- e.value = n;
369
- }
370
- realData.recent_count = isNaN(n) ? undefined : n;
371
- gvc.notifyDataChange(cvm.buttonsId);
372
- gvc.notifyDataChange(`${cvm.iconId}${index}`);
373
- })}"
374
- value="${dd.recent_count ?? ''}"
375
- />
376
- </div>`,
377
- },
452
+ ];
453
+ const endArr = [
378
454
  {
379
455
  key: '備註',
380
456
  value: html` <div style="width: 120px" onclick="${gvc.event((e, event) => event.stopPropagation())}">
@@ -397,17 +473,81 @@ export class StockHistory {
397
473
  if (realData.recent_count === undefined) {
398
474
  return '';
399
475
  }
400
- if (realData.transfer_count === realData.recent_count) {
401
- return html`<i class="fa-solid fa-circle-check"></i>`;
402
- }
403
- if (realData.transfer_count !== realData.recent_count) {
476
+ if (realData.transfer_count > realData.recent_count) {
404
477
  return html`<i class="fa-light fa-circle-exclamation"></i>`;
405
478
  }
406
- return '';
479
+ return html`<i class="fa-solid fa-circle-check"></i>`;
407
480
  },
408
481
  }),
409
482
  },
410
483
  ];
484
+
485
+ switch (vm.data.type) {
486
+ case 'restocking':
487
+ return [
488
+ ...startArr,
489
+ {
490
+ key: '原定進貨數量',
491
+ value: `<span class="fs-7">${dd.transfer_count ?? 0}</span>`,
492
+ },
493
+ {
494
+ key: '實際到貨數量',
495
+ value: html` <div style="width: 100px" onclick="${gvc.event((e, event) => event.stopPropagation())}">
496
+ <input
497
+ class="form-control"
498
+ type="number"
499
+ min="0"
500
+ style="border-radius: 10px; border: 1px solid #DDD; padding-left: 18px;"
501
+ onchange="${gvc.event((e) => {
502
+ let n = parseInt(e.value, 10);
503
+ if (n < 0) {
504
+ n = 0;
505
+ e.value = n;
506
+ }
507
+ realData.recent_count = isNaN(n) ? undefined : n;
508
+ gvc.notifyDataChange(cvm.buttonsId);
509
+ gvc.notifyDataChange(`${cvm.iconId}${index}`);
510
+ })}"
511
+ value="${dd.recent_count ?? ''}"
512
+ />
513
+ </div>`,
514
+ },
515
+ ...endArr,
516
+ ];
517
+ case 'transfer':
518
+ return [
519
+ ...startArr,
520
+ {
521
+ key: '原定調入數量',
522
+ value: `<span class="fs-7">${dd.transfer_count ?? 0}</span>`,
523
+ },
524
+ {
525
+ key: '實際調入數量',
526
+ value: html` <div style="width: 100px" onclick="${gvc.event((e, event) => event.stopPropagation())}">
527
+ <input
528
+ class="form-control"
529
+ type="number"
530
+ min="0"
531
+ style="border-radius: 10px; border: 1px solid #DDD; padding-left: 18px;"
532
+ onchange="${gvc.event((e) => {
533
+ let n = parseInt(e.value, 10);
534
+ if (n < 0) {
535
+ n = 0;
536
+ e.value = n;
537
+ }
538
+ realData.recent_count = isNaN(n) ? undefined : n;
539
+ gvc.notifyDataChange(cvm.buttonsId);
540
+ gvc.notifyDataChange(`${cvm.iconId}${index}`);
541
+ })}"
542
+ value="${dd.recent_count ?? ''}"
543
+ />
544
+ </div>`,
545
+ },
546
+ ...endArr,
547
+ ];
548
+ case 'checking':
549
+ return [...startArr, ...endArr];
550
+ }
411
551
  });
412
552
  }
413
553
 
@@ -418,7 +558,7 @@ export class StockHistory {
418
558
  gvc.event(() => {
419
559
  vm.view = 'replace';
420
560
  })
421
- )}${BgWidget.title('進貨核對')}
561
+ )}${BgWidget.title(`${typeData.name}核對`)}
422
562
  <div class="flex-fill"></div>
423
563
  </div>
424
564
  <div class="title-container">
@@ -512,7 +652,7 @@ export class StockHistory {
512
652
  vm.data.content.product_list = response;
513
653
  vmi.pageSize = Math.ceil(response.length / limit);
514
654
  vmi.originalData = response;
515
- vmi.tableData = specDatalist(vmi.page, limit);
655
+ vmi.tableData = checkSpecTable(vmi.page, limit);
516
656
  vmi.loading = false;
517
657
  vmi.callback();
518
658
  }
@@ -539,6 +679,396 @@ export class StockHistory {
539
679
  );
540
680
  }
541
681
 
682
+ static getFormStructure(gvc: GVC, vm: VM) {
683
+ const glitter = gvc.glitter;
684
+ switch (vm.type) {
685
+ case 'restocking':
686
+ return [
687
+ html`<div class="row">
688
+ <div class="col-12 col-md-6">
689
+ <div class="tx_normal">供應商</div>
690
+ ${BgWidget.mbContainer(8)}
691
+ ${gvc.bindView(
692
+ (() => {
693
+ const id = glitter.getUUID();
694
+ let dataList: any[] = [];
695
+ let loading = true;
696
+ return {
697
+ bind: id,
698
+ view: () => {
699
+ if (loading) {
700
+ return BgWidget.spinner({
701
+ container: { style: 'margin-top: 0;' },
702
+ circle: { visible: false },
703
+ });
704
+ } else {
705
+ return BgWidget.selectOptionAndClickEvent({
706
+ gvc: gvc,
707
+ default: vm.data.content.vendor ?? '',
708
+ options: dataList.map((item) => {
709
+ return {
710
+ key: item.id,
711
+ value: item.name,
712
+ note: item.address,
713
+ };
714
+ }),
715
+ showNote: BgWidget.grayNote(
716
+ (() => {
717
+ const d = dataList.find((item) => {
718
+ return item.id === vm.data.content.vendor;
719
+ });
720
+ return d ? d.address : '';
721
+ })(),
722
+ 'margin: 0 4px;'
723
+ ),
724
+ callback: (data) => {
725
+ vm.data.content.vendor = data ? data.key : '';
726
+ gvc.notifyDataChange(id);
727
+ },
728
+ clickElement: {
729
+ html: html`<div>新增供應商</div>
730
+ <div>
731
+ <i class="fa-solid fa-plus ps-2" style="font-size: 16px; height: 14px; width: 14px;"></i>
732
+ </div>`,
733
+ event: (gvc2) => {
734
+ const newVendorData = StockVendors.emptyData();
735
+ BgWidget.settingDialog({
736
+ gvc: gvc2,
737
+ title: '新增供應點',
738
+ innerHTML: (gvc2) => {
739
+ return StockHistory.vendorForm(gvc2, newVendorData);
740
+ },
741
+ footer_html: (gvc2) => {
742
+ return `${BgWidget.cancel(
743
+ gvc2.event(() => {
744
+ gvc2.closeDialog();
745
+ })
746
+ )}
747
+ ${BgWidget.save(
748
+ gvc2.event(() => {
749
+ StockVendors.verifyStoreForm(glitter, 'create', newVendorData, (response) => {
750
+ gvc2.closeDialog();
751
+ vm.data.content.vendor = response.id;
752
+ loading = true;
753
+ gvc.notifyDataChange(id);
754
+ });
755
+ }),
756
+ '完成'
757
+ )}`;
758
+ },
759
+ });
760
+ },
761
+ },
762
+ });
763
+ }
764
+ },
765
+ divCreate: {},
766
+ onCreate: () => {
767
+ if (loading) {
768
+ ApiUser.getPublicConfig('vendor_manager', 'manager').then((dd: any) => {
769
+ if (dd.result && dd.response.value) {
770
+ dataList = dd.response.value.list;
771
+ }
772
+ loading = false;
773
+ gvc.notifyDataChange(id);
774
+ });
775
+ }
776
+ },
777
+ };
778
+ })()
779
+ )}
780
+ </div>
781
+ <div class="col-12 col-md-6">
782
+ <div class="tx_normal">庫存點</div>
783
+ ${BgWidget.mbContainer(8)}
784
+ ${gvc.bindView(
785
+ (() => {
786
+ const id = glitter.getUUID();
787
+ let dataList: any[] = [];
788
+ let loading = true;
789
+ return {
790
+ bind: id,
791
+ view: () => {
792
+ if (loading) {
793
+ return BgWidget.spinner({
794
+ container: { style: 'margin-top: 0;' },
795
+ circle: { visible: false },
796
+ });
797
+ } else {
798
+ return BgWidget.selectOptionAndClickEvent({
799
+ gvc: gvc,
800
+ default: vm.data.content.store_in ?? '',
801
+ options: dataList.map((item) => {
802
+ return {
803
+ key: item.id,
804
+ value: item.name,
805
+ note: item.address,
806
+ };
807
+ }),
808
+ showNote: BgWidget.grayNote(
809
+ (() => {
810
+ const d = dataList.find((item) => {
811
+ return item.id === vm.data.content.store_in;
812
+ });
813
+ return d ? d.address : '';
814
+ })(),
815
+ 'margin: 0 4px;'
816
+ ),
817
+ callback: (data) => {
818
+ vm.data.content.store_in = data ? data.key : '';
819
+ gvc.notifyDataChange(id);
820
+ },
821
+ clickElement: {
822
+ html: html`<div>新增庫存點</div>
823
+ <div>
824
+ <i class="fa-solid fa-plus ps-2" style="font-size: 16px; height: 14px; width: 14px;"></i>
825
+ </div>`,
826
+ event: (gvc2) => {
827
+ const newStoreData = StockStores.emptyData();
828
+ BgWidget.settingDialog({
829
+ gvc: gvc2,
830
+ title: '新增庫存點',
831
+ innerHTML: (gvc2) => {
832
+ return StockHistory.storeForm(gvc2, newStoreData);
833
+ },
834
+ footer_html: (gvc2) => {
835
+ return `${BgWidget.cancel(
836
+ gvc2.event(() => {
837
+ gvc2.closeDialog();
838
+ })
839
+ )}
840
+ ${BgWidget.save(
841
+ gvc2.event(() => {
842
+ StockStores.verifyStoreForm(glitter, 'create', newStoreData, (response) => {
843
+ gvc2.closeDialog();
844
+ vm.data.content.store_in = response.id;
845
+ loading = true;
846
+ gvc.notifyDataChange(id);
847
+ });
848
+ }),
849
+ '完成'
850
+ )}`;
851
+ },
852
+ });
853
+ },
854
+ },
855
+ });
856
+ }
857
+ },
858
+ divCreate: {},
859
+ onCreate: () => {
860
+ if (loading) {
861
+ ApiUser.getPublicConfig('store_manager', 'manager').then((dd: any) => {
862
+ if (dd.result && dd.response.value) {
863
+ dataList = dd.response.value.list;
864
+ }
865
+ loading = false;
866
+ gvc.notifyDataChange(id);
867
+ });
868
+ }
869
+ },
870
+ };
871
+ })()
872
+ )}
873
+ </div>
874
+ </div> `,
875
+ ];
876
+ case 'transfer':
877
+ return [
878
+ html`<div class="row">
879
+ <div class="col-12 col-md-6">
880
+ <div class="tx_normal">調出庫存點</div>
881
+ ${BgWidget.mbContainer(8)}
882
+ ${gvc.bindView(
883
+ (() => {
884
+ const id = glitter.getUUID();
885
+ let dataList: any[] = [];
886
+ let loading = true;
887
+ return {
888
+ bind: id,
889
+ view: () => {
890
+ if (loading) {
891
+ return BgWidget.spinner({
892
+ container: { style: 'margin-top: 0;' },
893
+ circle: { visible: false },
894
+ });
895
+ } else {
896
+ return BgWidget.selectOptionAndClickEvent({
897
+ gvc: gvc,
898
+ default: vm.data.content.store_out ?? '',
899
+ options: dataList.map((item) => {
900
+ return {
901
+ key: item.id,
902
+ value: item.name,
903
+ note: item.address,
904
+ };
905
+ }),
906
+ showNote: BgWidget.grayNote(
907
+ (() => {
908
+ const d = dataList.find((item) => {
909
+ return item.id === vm.data.content.store_out;
910
+ });
911
+ return d ? d.address : '';
912
+ })(),
913
+ 'margin: 0 4px;'
914
+ ),
915
+ callback: (data) => {
916
+ vm.data.content.store_out = data ? data.key : '';
917
+ gvc.notifyDataChange(id);
918
+ },
919
+ clickElement: {
920
+ html: html`<div>新增庫存點</div>
921
+ <div>
922
+ <i class="fa-solid fa-plus ps-2" style="font-size: 16px; height: 14px; width: 14px;"></i>
923
+ </div>`,
924
+ event: (gvc2) => {
925
+ const newStoreData = StockStores.emptyData();
926
+ BgWidget.settingDialog({
927
+ gvc: gvc2,
928
+ title: '新增庫存點',
929
+ innerHTML: (gvc2) => {
930
+ return StockHistory.storeForm(gvc2, newStoreData);
931
+ },
932
+ footer_html: (gvc2) => {
933
+ return `${BgWidget.cancel(
934
+ gvc2.event(() => {
935
+ gvc2.closeDialog();
936
+ })
937
+ )}
938
+ ${BgWidget.save(
939
+ gvc2.event(() => {
940
+ StockStores.verifyStoreForm(glitter, 'create', newStoreData, (response) => {
941
+ gvc2.closeDialog();
942
+ vm.data.content.store_out = response.id;
943
+ loading = true;
944
+ gvc.notifyDataChange(id);
945
+ });
946
+ }),
947
+ '完成'
948
+ )}`;
949
+ },
950
+ });
951
+ },
952
+ },
953
+ });
954
+ }
955
+ },
956
+ divCreate: {},
957
+ onCreate: () => {
958
+ if (loading) {
959
+ ApiUser.getPublicConfig('store_manager', 'manager').then((dd: any) => {
960
+ if (dd.result && dd.response.value) {
961
+ dataList = dd.response.value.list;
962
+ }
963
+ loading = false;
964
+ gvc.notifyDataChange(id);
965
+ });
966
+ }
967
+ },
968
+ };
969
+ })()
970
+ )}
971
+ </div>
972
+ <div class="col-12 col-md-6">
973
+ <div class="tx_normal">調入庫存點</div>
974
+ ${BgWidget.mbContainer(8)}
975
+ ${gvc.bindView(
976
+ (() => {
977
+ const id = glitter.getUUID();
978
+ let dataList: any[] = [];
979
+ let loading = true;
980
+ return {
981
+ bind: id,
982
+ view: () => {
983
+ if (loading) {
984
+ return BgWidget.spinner({
985
+ container: { style: 'margin-top: 0;' },
986
+ circle: { visible: false },
987
+ });
988
+ } else {
989
+ return BgWidget.selectOptionAndClickEvent({
990
+ gvc: gvc,
991
+ default: vm.data.content.store_in ?? '',
992
+ options: dataList.map((item) => {
993
+ return {
994
+ key: item.id,
995
+ value: item.name,
996
+ note: item.address,
997
+ };
998
+ }),
999
+ showNote: BgWidget.grayNote(
1000
+ (() => {
1001
+ const d = dataList.find((item) => {
1002
+ return item.id === vm.data.content.store_in;
1003
+ });
1004
+ return d ? d.address : '';
1005
+ })(),
1006
+ 'margin: 0 4px;'
1007
+ ),
1008
+ callback: (data) => {
1009
+ vm.data.content.store_in = data ? data.key : '';
1010
+ gvc.notifyDataChange(id);
1011
+ },
1012
+ clickElement: {
1013
+ html: html`<div>新增庫存點</div>
1014
+ <div>
1015
+ <i class="fa-solid fa-plus ps-2" style="font-size: 16px; height: 14px; width: 14px;"></i>
1016
+ </div>`,
1017
+ event: (gvc2) => {
1018
+ const newStoreData = StockStores.emptyData();
1019
+ BgWidget.settingDialog({
1020
+ gvc: gvc2,
1021
+ title: '新增庫存點',
1022
+ innerHTML: (gvc2) => {
1023
+ return StockHistory.storeForm(gvc2, newStoreData);
1024
+ },
1025
+ footer_html: (gvc2) => {
1026
+ return `${BgWidget.cancel(
1027
+ gvc2.event(() => {
1028
+ gvc2.closeDialog();
1029
+ })
1030
+ )}
1031
+ ${BgWidget.save(
1032
+ gvc2.event(() => {
1033
+ StockStores.verifyStoreForm(glitter, 'create', newStoreData, (response) => {
1034
+ gvc2.closeDialog();
1035
+ vm.data.content.store_in = response.id;
1036
+ loading = true;
1037
+ gvc.notifyDataChange(id);
1038
+ });
1039
+ }),
1040
+ '完成'
1041
+ )}`;
1042
+ },
1043
+ });
1044
+ },
1045
+ },
1046
+ });
1047
+ }
1048
+ },
1049
+ divCreate: {},
1050
+ onCreate: () => {
1051
+ if (loading) {
1052
+ ApiUser.getPublicConfig('store_manager', 'manager').then((dd: any) => {
1053
+ if (dd.result && dd.response.value) {
1054
+ dataList = dd.response.value.list;
1055
+ }
1056
+ loading = false;
1057
+ gvc.notifyDataChange(id);
1058
+ });
1059
+ }
1060
+ },
1061
+ };
1062
+ })()
1063
+ )}
1064
+ </div>
1065
+ </div> `,
1066
+ ];
1067
+ case 'checking':
1068
+ return [];
1069
+ }
1070
+ }
1071
+
542
1072
  static createOrder(gvc: GVC, vm: VM) {
543
1073
  const glitter = gvc.glitter;
544
1074
  const dialog = new ShareDialog(glitter);
@@ -551,241 +1081,12 @@ export class StockHistory {
551
1081
  tableLoading: true,
552
1082
  };
553
1083
 
554
- function getFormStructure() {
555
- switch (vm.type) {
556
- case 'restocking':
557
- return [
558
- html` <div class="row">
559
- <div class="col-12 col-md-6">
560
- <div class="tx_normal">進貨單編號</div>
561
- ${BgWidget.mbContainer(8)}
562
- ${BgWidget.editeInput({
563
- gvc: gvc,
564
- title: '',
565
- default: vm.data.order_id || '系統將自動產生流水號',
566
- placeHolder: '',
567
- callback: () => {},
568
- readonly: true,
569
- })}
570
- </div>
571
- ${document.body.clientWidth > 768 ? '' : BgWidget.mbContainer(18)}
572
- <div class="col-12 col-md-6">
573
- <div class="tx_normal">進貨日期</div>
574
- ${BgWidget.mbContainer(8)}
575
- ${BgWidget.editeInput({
576
- gvc: gvc,
577
- title: '',
578
- type: 'date',
579
- default: vm.data.created_time ?? '',
580
- placeHolder: '請輸入進貨日期',
581
- callback: (text) => {
582
- vm.data.created_time = text;
583
- },
584
- })}
585
- </div>
586
- </div>`,
587
- html`<div class="row">
588
- <div class="col-12 col-md-6">
589
- <div class="tx_normal">供應商</div>
590
- ${BgWidget.mbContainer(8)}
591
- ${gvc.bindView(
592
- (() => {
593
- const id = glitter.getUUID();
594
- let dataList: any[] = [];
595
- let loading = true;
596
- return {
597
- bind: id,
598
- view: () => {
599
- if (loading) {
600
- return BgWidget.spinner({
601
- container: { style: 'margin-top: 0;' },
602
- circle: { visible: false },
603
- });
604
- } else {
605
- return BgWidget.selectOptionAndClickEvent({
606
- gvc: gvc,
607
- default: vm.data.content.vendor ?? '',
608
- options: dataList.map((item) => {
609
- return {
610
- key: item.id,
611
- value: item.name,
612
- note: item.address,
613
- };
614
- }),
615
- showNote: BgWidget.grayNote(
616
- (() => {
617
- const d = dataList.find((item) => {
618
- return item.id === vm.data.content.vendor;
619
- });
620
- return d ? d.address : '';
621
- })(),
622
- 'margin: 0 4px;'
623
- ),
624
- callback: (data) => {
625
- vm.data.content.vendor = data ? data.key : '';
626
- gvc.notifyDataChange(id);
627
- },
628
- clickElement: {
629
- html: html`<div>新增供應商</div>
630
- <div>
631
- <i class="fa-solid fa-plus ps-2" style="font-size: 16px; height: 14px; width: 14px;"></i>
632
- </div>`,
633
- event: (gvc2) => {
634
- const newVendorData = StockVendors.emptyData();
635
- BgWidget.settingDialog({
636
- gvc: gvc2,
637
- title: '新增供應點',
638
- innerHTML: (gvc2) => {
639
- return StockHistory.vendorForm(gvc2, newVendorData);
640
- },
641
- footer_html: (gvc2) => {
642
- return `${BgWidget.cancel(
643
- gvc2.event(() => {
644
- gvc2.closeDialog();
645
- })
646
- )}
647
- ${BgWidget.save(
648
- gvc2.event(() => {
649
- StockVendors.verifyStoreForm(glitter, 'create', newVendorData, (response) => {
650
- gvc2.closeDialog();
651
- vm.data.content.vendor = response.id;
652
- loading = true;
653
- gvc.notifyDataChange(id);
654
- });
655
- }),
656
- '完成'
657
- )}`;
658
- },
659
- });
660
- },
661
- },
662
- });
663
- }
664
- },
665
- divCreate: {},
666
- onCreate: () => {
667
- if (loading) {
668
- ApiUser.getPublicConfig('vendor_manager', 'manager').then((dd: any) => {
669
- if (dd.result && dd.response.value) {
670
- dataList = dd.response.value.list;
671
- }
672
- loading = false;
673
- gvc.notifyDataChange(id);
674
- });
675
- }
676
- },
677
- };
678
- })()
679
- )}
680
- </div>
681
- <div class="col-12 col-md-6">
682
- <div class="tx_normal">庫存點</div>
683
- ${BgWidget.mbContainer(8)}
684
- ${gvc.bindView(
685
- (() => {
686
- const id = glitter.getUUID();
687
- let dataList: any[] = [];
688
- let loading = true;
689
- return {
690
- bind: id,
691
- view: () => {
692
- if (loading) {
693
- return BgWidget.spinner({
694
- container: { style: 'margin-top: 0;' },
695
- circle: { visible: false },
696
- });
697
- } else {
698
- return BgWidget.selectOptionAndClickEvent({
699
- gvc: gvc,
700
- default: vm.data.content.store_in ?? '',
701
- options: dataList.map((item) => {
702
- return {
703
- key: item.id,
704
- value: item.name,
705
- note: item.address,
706
- };
707
- }),
708
- showNote: BgWidget.grayNote(
709
- (() => {
710
- const d = dataList.find((item) => {
711
- return item.id === vm.data.content.store_in;
712
- });
713
- return d ? d.address : '';
714
- })(),
715
- 'margin: 0 4px;'
716
- ),
717
- callback: (data) => {
718
- vm.data.content.store_in = data ? data.key : '';
719
- gvc.notifyDataChange(id);
720
- },
721
- clickElement: {
722
- html: html`<div>新增庫存點</div>
723
- <div>
724
- <i class="fa-solid fa-plus ps-2" style="font-size: 16px; height: 14px; width: 14px;"></i>
725
- </div>`,
726
- event: (gvc2) => {
727
- const newStoreData = StockStores.emptyData();
728
- BgWidget.settingDialog({
729
- gvc: gvc2,
730
- title: '新增庫存點',
731
- innerHTML: (gvc2) => {
732
- return StockHistory.storeForm(gvc2, newStoreData);
733
- },
734
- footer_html: (gvc2) => {
735
- return `${BgWidget.cancel(
736
- gvc2.event(() => {
737
- gvc2.closeDialog();
738
- })
739
- )}
740
- ${BgWidget.save(
741
- gvc2.event(() => {
742
- StockStores.verifyStoreForm(glitter, 'create', newStoreData, (response) => {
743
- gvc2.closeDialog();
744
- vm.data.content.store_in = response.id;
745
- loading = true;
746
- gvc.notifyDataChange(id);
747
- });
748
- }),
749
- '完成'
750
- )}`;
751
- },
752
- });
753
- },
754
- },
755
- });
756
- }
757
- },
758
- divCreate: {},
759
- onCreate: () => {
760
- if (loading) {
761
- ApiUser.getPublicConfig('store_manager', 'manager').then((dd: any) => {
762
- if (dd.result && dd.response.value) {
763
- dataList = dd.response.value.list;
764
- }
765
- loading = false;
766
- gvc.notifyDataChange(id);
767
- });
768
- }
769
- },
770
- };
771
- })()
772
- )}
773
- </div>
774
- </div> `,
775
- ];
776
- case 'transfer':
777
- return [];
778
- case 'checking':
779
- return [];
780
- }
781
- }
782
-
783
1084
  function specDatalist(page: number, limit: number) {
784
1085
  const x = (page - 1) * limit;
785
1086
  const specs = vm.data.content.product_list.slice(x, x + limit);
786
1087
  return specs.map((dd: ContentProduct, index: number) => {
787
1088
  const realData = vm.data.content.product_list[x + index];
788
- return [
1089
+ const startArr = [
789
1090
  {
790
1091
  key: '商品',
791
1092
  value: `<span class="fs-7">${dd.title || '-'}</span>`,
@@ -798,61 +1099,8 @@ export class StockHistory {
798
1099
  key: '存貨單位(SKU)',
799
1100
  value: `<span class="fs-7">${dd.sku || '-'}</span>`,
800
1101
  },
801
- {
802
- key: '進貨成本',
803
- value: html` <div style="width: 100px" onclick="${gvc.event((e, event) => event.stopPropagation())}">
804
- <input
805
- class="form-control"
806
- type="number"
807
- min="0"
808
- style="border-radius: 10px; border: 1px solid #DDD; padding-left: 18px;"
809
- onchange="${gvc.event((e) => {
810
- let n = parseInt(e.value, 10);
811
- if (n < 0) {
812
- n = 0;
813
- e.value = n;
814
- }
815
- realData.cost = n;
816
- gvc.notifyDataChange(`subtotoal_${index}`);
817
- })}"
818
- value="${dd.cost ?? 0}"
819
- />
820
- </div>`,
821
- },
822
- {
823
- key: '數量',
824
- value: html` <div style="width: 100px" onclick="${gvc.event((e, event) => event.stopPropagation())}">
825
- <input
826
- class="form-control"
827
- type="number"
828
- min="0"
829
- style="border-radius: 10px; border: 1px solid #DDD; padding-left: 18px;"
830
- onchange="${gvc.event((e) => {
831
- let n = parseInt(e.value, 10);
832
- if (n < 0) {
833
- n = 0;
834
- e.value = n;
835
- }
836
- realData.transfer_count = n;
837
- gvc.notifyDataChange(`subtotoal_${index}`);
838
- })}"
839
- value="${dd.transfer_count ?? 0}"
840
- />
841
- </div>`,
842
- },
843
- {
844
- key: '小計',
845
- value: gvc.bindView({
846
- bind: `subtotoal_${index}`,
847
- view: () => {
848
- const subtotal = dd.cost * dd.transfer_count;
849
- return html`<span class="fs-7">$ ${subtotal.toLocaleString()}</span>`;
850
- },
851
- onCreate: () => {
852
- gvc.notifyDataChange(dvm.totalId);
853
- },
854
- }),
855
- },
1102
+ ];
1103
+ const endArr = [
856
1104
  {
857
1105
  key: '備註',
858
1106
  value: html` <div style="width: 120px" onclick="${gvc.event((e, event) => event.stopPropagation())}">
@@ -868,6 +1116,100 @@ export class StockHistory {
868
1116
  </div>`,
869
1117
  },
870
1118
  ];
1119
+ switch (vm.data.type) {
1120
+ case 'restocking':
1121
+ return [
1122
+ ...startArr,
1123
+ {
1124
+ key: '進貨成本',
1125
+ value: html` <div style="width: 100px" onclick="${gvc.event((e, event) => event.stopPropagation())}">
1126
+ <input
1127
+ class="form-control"
1128
+ type="number"
1129
+ min="0"
1130
+ style="border-radius: 10px; border: 1px solid #DDD; padding-left: 18px;"
1131
+ onchange="${gvc.event((e) => {
1132
+ let n = parseInt(e.value, 10);
1133
+ if (n < 0) {
1134
+ n = 0;
1135
+ e.value = n;
1136
+ }
1137
+ realData.cost = n;
1138
+ gvc.notifyDataChange(`subtotoal_${index}`);
1139
+ })}"
1140
+ value="${dd.cost ?? 0}"
1141
+ />
1142
+ </div>`,
1143
+ },
1144
+ {
1145
+ key: '數量',
1146
+ value: html` <div style="width: 100px" onclick="${gvc.event((e, event) => event.stopPropagation())}">
1147
+ <input
1148
+ class="form-control"
1149
+ type="number"
1150
+ min="0"
1151
+ style="border-radius: 10px; border: 1px solid #DDD; padding-left: 18px;"
1152
+ onchange="${gvc.event((e) => {
1153
+ let n = parseInt(e.value, 10);
1154
+ if (n < 0) {
1155
+ n = 0;
1156
+ e.value = n;
1157
+ }
1158
+ realData.transfer_count = n;
1159
+ gvc.notifyDataChange(`subtotoal_${index}`);
1160
+ })}"
1161
+ value="${dd.transfer_count ?? 0}"
1162
+ />
1163
+ </div>`,
1164
+ },
1165
+ {
1166
+ key: '小計',
1167
+ value: gvc.bindView({
1168
+ bind: `subtotoal_${index}`,
1169
+ view: () => {
1170
+ const subtotal = dd.cost * dd.transfer_count;
1171
+ return html`<span class="fs-7">$ ${subtotal.toLocaleString()}</span>`;
1172
+ },
1173
+ onCreate: () => {
1174
+ gvc.notifyDataChange(dvm.totalId);
1175
+ },
1176
+ }),
1177
+ },
1178
+ ...endArr,
1179
+ ];
1180
+ case 'transfer':
1181
+ return [
1182
+ ...startArr,
1183
+ {
1184
+ key: '來源庫存數量',
1185
+ value: 'unknown',
1186
+ },
1187
+ {
1188
+ key: '調入數量',
1189
+ value: html` <div style="width: 100px" onclick="${gvc.event((e, event) => event.stopPropagation())}">
1190
+ <input
1191
+ class="form-control"
1192
+ type="number"
1193
+ min="0"
1194
+ style="border-radius: 10px; border: 1px solid #DDD; padding-left: 18px;"
1195
+ onchange="${gvc.event((e) => {
1196
+ let n = parseInt(e.value, 10);
1197
+ if (n < 0) {
1198
+ n = 0;
1199
+ e.value = n;
1200
+ }
1201
+ realData.transfer_count = n;
1202
+ gvc.notifyDataChange(`subtotoal_${index}`);
1203
+ })}"
1204
+ value="${dd.transfer_count ?? 0}"
1205
+ />
1206
+ </div>`,
1207
+ },
1208
+ ...endArr,
1209
+ ];
1210
+ case 'checking':
1211
+ return [...startArr, ...endArr];
1212
+ }
871
1213
  });
872
1214
  }
873
1215
 
@@ -893,7 +1235,36 @@ export class StockHistory {
893
1235
  BgWidget.mainCard(
894
1236
  [
895
1237
  html` <div class="tx_700">${typeData.name}單資料</div>`,
896
- ...getFormStructure(),
1238
+ html` <div class="row">
1239
+ <div class="col-12 col-md-6">
1240
+ <div class="tx_normal">${typeData.name}編號</div>
1241
+ ${BgWidget.mbContainer(8)}
1242
+ ${BgWidget.editeInput({
1243
+ gvc: gvc,
1244
+ title: '',
1245
+ default: vm.data.order_id || '系統將自動產生流水號',
1246
+ placeHolder: '',
1247
+ callback: () => {},
1248
+ readonly: true,
1249
+ })}
1250
+ </div>
1251
+ ${document.body.clientWidth > 768 ? '' : BgWidget.mbContainer(18)}
1252
+ <div class="col-12 col-md-6">
1253
+ <div class="tx_normal">${typeData.name}日期</div>
1254
+ ${BgWidget.mbContainer(8)}
1255
+ ${BgWidget.editeInput({
1256
+ gvc: gvc,
1257
+ title: '',
1258
+ type: 'date',
1259
+ default: vm.data.created_time ?? '',
1260
+ placeHolder: `請輸入${typeData.name}日期`,
1261
+ callback: (text) => {
1262
+ vm.data.created_time = text;
1263
+ },
1264
+ })}
1265
+ </div>
1266
+ </div>`,
1267
+ ...this.getFormStructure(gvc, vm),
897
1268
  html` <div class="tx_normal">備註</div>
898
1269
  ${EditorElem.editeText({
899
1270
  gvc: gvc,
@@ -909,7 +1280,7 @@ export class StockHistory {
909
1280
  BgWidget.mainCard(
910
1281
  [
911
1282
  html`
912
- <div class="tx_700">進貨商品</div>
1283
+ <div class="tx_700">${typeData.name}商品</div>
913
1284
  ${BgWidget.mbContainer(18)}
914
1285
  ${gvc.bindView({
915
1286
  bind: dvm.tableId,
@@ -921,62 +1292,112 @@ export class StockHistory {
921
1292
  dvm.tableLoading = false;
922
1293
  }
923
1294
 
924
- return [
925
- BgWidget.tableV3({
926
- gvc: gvc,
927
- getData: (vd) => {
928
- vmi = vd;
929
- const limit = 99999;
930
- this.setVariantList(dvm.variantIds, vm.data, (response) => {
931
- vm.data.content.product_list = response;
932
- vmi.pageSize = Math.ceil(response.length / limit);
933
- vmi.originalData = response;
934
- vmi.tableData = specDatalist(vmi.page, limit);
935
- vmi.loading = false;
936
- vmi.callback();
937
- });
938
- },
939
- rowClick: () => {},
940
- filter: [],
941
- hiddenPageSplit: true,
942
- }),
943
- html`<div
944
- class="w-100 d-flex align-items-center justify-content-center cursor_pointer"
945
- style="color: #36B; font-size: 16px; font-weight: 400;"
946
- onclick="${gvc.event(() => {
947
- BgWidget.variantDialog({
948
- gvc,
949
- title: '新增商品規格',
950
- default: dvm.variantIds,
951
- callback: (resultData) => {
952
- dvm.variantIds = resultData;
953
- gvc.notifyDataChange(dvm.tableId);
1295
+ switch (vm.data.type) {
1296
+ case 'restocking':
1297
+ return [
1298
+ BgWidget.tableV3({
1299
+ gvc: gvc,
1300
+ getData: (vd) => {
1301
+ vmi = vd;
1302
+ const limit = 99999;
1303
+ this.setVariantList(dvm.variantIds, vm.data, (response) => {
1304
+ vm.data.content.product_list = response;
1305
+ vmi.pageSize = Math.ceil(response.length / limit);
1306
+ vmi.originalData = response;
1307
+ vmi.tableData = specDatalist(vmi.page, limit);
1308
+ vmi.loading = false;
1309
+ vmi.callback();
1310
+ });
954
1311
  },
955
- });
956
- })}"
957
- >
958
- <div>新增進貨商品</div>
959
- <div>
960
- <i class="fa-solid fa-plus ps-2" style="font-size: 16px; height: 14px; width: 14px;"></i>
961
- </div>
962
- </div>`,
963
- BgWidget.horizontalLine({ margin: 1.75 }),
964
- gvc.bindView({
965
- bind: dvm.totalId,
966
- view: () => {
967
- const total = vm.data.content.product_list.reduce((sum, item) => {
968
- return sum + item.cost * item.transfer_count;
969
- }, 0);
970
-
971
- return html` <div class="flex-fill"></div>
972
- <div class="d-flex justify-content-between tx_700" style="width: 200px;">
973
- <div>進貨總成本</div>
974
- <div>$ ${total.toLocaleString()}</div>
975
- </div>`;
976
- },
977
- divCreate: { class: 'd-flex w-100' },
978
- }),
979
- ].join('');
1312
+ rowClick: () => {},
1313
+ filter: [],
1314
+ hiddenPageSplit: true,
1315
+ }),
1316
+ html`<div
1317
+ class="w-100 d-flex align-items-center justify-content-center cursor_pointer"
1318
+ style="color: #36B; font-size: 16px; font-weight: 400;"
1319
+ onclick="${gvc.event(() => {
1320
+ BgWidget.variantDialog({
1321
+ gvc,
1322
+ title: '搜尋商品',
1323
+ default: dvm.variantIds,
1324
+ callback: (resultData) => {
1325
+ dvm.variantIds = resultData;
1326
+ gvc.notifyDataChange(dvm.tableId);
1327
+ },
1328
+ });
1329
+ })}"
1330
+ >
1331
+ <div>新增${typeData.name}商品</div>
1332
+ <div>
1333
+ <i class="fa-solid fa-plus ps-2" style="font-size: 16px; height: 14px; width: 14px;"></i>
1334
+ </div>
1335
+ </div>`,
1336
+ BgWidget.horizontalLine({ margin: 1.75 }),
1337
+ gvc.bindView({
1338
+ bind: dvm.totalId,
1339
+ view: () => {
1340
+ const total = vm.data.content.product_list.reduce((sum, item) => {
1341
+ return sum + item.cost * item.transfer_count;
1342
+ }, 0);
1343
+
1344
+ return html` <div class="flex-fill"></div>
1345
+ <div class="d-flex justify-content-between tx_700" style="width: 200px;">
1346
+ <div>進貨總成本</div>
1347
+ <div>$ ${total.toLocaleString()}</div>
1348
+ </div>`;
1349
+ },
1350
+ divCreate: { class: 'd-flex w-100' },
1351
+ }),
1352
+ ].join('');
1353
+ case 'transfer':
1354
+ return [
1355
+ BgWidget.tableV3({
1356
+ gvc: gvc,
1357
+ getData: (vd) => {
1358
+ vmi = vd;
1359
+ const limit = 99999;
1360
+ this.setVariantList(dvm.variantIds, vm.data, (response) => {
1361
+ vm.data.content.product_list = response;
1362
+ vmi.pageSize = Math.ceil(response.length / limit);
1363
+ vmi.originalData = response;
1364
+ vmi.tableData = specDatalist(vmi.page, limit);
1365
+ vmi.loading = false;
1366
+ vmi.callback();
1367
+ });
1368
+ },
1369
+ rowClick: () => {},
1370
+ filter: [],
1371
+ hiddenPageSplit: true,
1372
+ }),
1373
+ html`<div
1374
+ class="w-100 d-flex align-items-center justify-content-center cursor_pointer"
1375
+ style="color: #36B; font-size: 16px; font-weight: 400;"
1376
+ onclick="${gvc.event(() => {
1377
+ if (CheckInput.isEmpty(vm.data.content.store_out)) {
1378
+ dialog.errorMessage({ text: '請先選擇「調出庫存點」' });
1379
+ return;
1380
+ }
1381
+ BgWidget.variantDialog({
1382
+ gvc,
1383
+ title: '搜尋商品',
1384
+ default: dvm.variantIds,
1385
+ callback: (resultData) => {
1386
+ dvm.variantIds = resultData;
1387
+ gvc.notifyDataChange(dvm.tableId);
1388
+ },
1389
+ });
1390
+ })}"
1391
+ >
1392
+ <div>新增${typeData.name}商品</div>
1393
+ <div>
1394
+ <i class="fa-solid fa-plus ps-2" style="font-size: 16px; height: 14px; width: 14px;"></i>
1395
+ </div>
1396
+ </div>`,
1397
+ ].join('');
1398
+ case 'checking':
1399
+ return ['全部商品', '特定分類', '特定商品'].join('');
1400
+ }
980
1401
  },
981
1402
  })}
982
1403
  `,
@@ -998,6 +1419,45 @@ export class StockHistory {
998
1419
  )}
999
1420
  ${BgWidget.save(
1000
1421
  gvc.event(() => {
1422
+ if (CheckInput.isEmpty(vm.data.created_time)) {
1423
+ dialog.errorMessage({ text: `請輸入${typeData.name}時間` });
1424
+ return;
1425
+ }
1426
+
1427
+ if (vm.data.type === 'restocking') {
1428
+ if (CheckInput.isEmpty(vm.data.content.vendor)) {
1429
+ dialog.errorMessage({ text: '請輸入供應商' });
1430
+ return;
1431
+ }
1432
+
1433
+ if (CheckInput.isEmpty(vm.data.content.store_in)) {
1434
+ dialog.errorMessage({ text: '請輸入庫存點' });
1435
+ return;
1436
+ }
1437
+ }
1438
+
1439
+ if (vm.data.type === 'transfer') {
1440
+ if (CheckInput.isEmpty(vm.data.content.store_out)) {
1441
+ dialog.errorMessage({ text: '請輸入調出庫存點' });
1442
+ return;
1443
+ }
1444
+
1445
+ if (CheckInput.isEmpty(vm.data.content.store_in)) {
1446
+ dialog.errorMessage({ text: '請輸入調入庫存點' });
1447
+ return;
1448
+ }
1449
+
1450
+ if (vm.data.content.store_in === vm.data.content.store_out) {
1451
+ dialog.errorMessage({ text: '調出與調入的庫存點不可相同' });
1452
+ return;
1453
+ }
1454
+ }
1455
+
1456
+ if (vm.data.content.product_list.length === 0) {
1457
+ dialog.errorMessage({ text: `請新增${typeData.name}商品` });
1458
+ return;
1459
+ }
1460
+
1001
1461
  dialog.dataLoading({ visible: true });
1002
1462
  if (vm.data.id === '') {
1003
1463
  ApiStock.postStockHistory(vm.data).then((r) => {
@@ -1028,30 +1488,33 @@ export class StockHistory {
1028
1488
  );
1029
1489
  }
1030
1490
 
1031
- static replaceOrder(gvc: GVC, vm: VM) {
1032
- const glitter = gvc.glitter;
1033
- const dialog = new ShareDialog(glitter);
1034
- const typeData = typeConfig[vm.type];
1035
- let vmi: any = undefined;
1036
-
1037
- function specDatalist(page: number, limit: number) {
1038
- const x = (page - 1) * limit;
1039
- const nonDetailed = [0, 1, 2].includes(vm.data.status);
1040
- return vm.data.content.product_list.slice(x, x + limit).map((dd: ContentProduct, index: number) => {
1041
- if (nonDetailed) {
1491
+ static restockingDetailTable(json: { type: 'details' | 'nonDetails' | 'logs'; list: ContentProduct[]; page: number; limit: number }) {
1492
+ const x = (json.page - 1) * json.limit;
1493
+ return json.list.slice(x, x + json.limit).map((dd: ContentProduct) => {
1494
+ const startArr = [
1495
+ {
1496
+ key: '商品',
1497
+ value: `<span class="fs-7">${dd.title || '-'}</span>`,
1498
+ },
1499
+ {
1500
+ key: '規格',
1501
+ value: `<span class="fs-7">${dd.spec}</span>`,
1502
+ },
1503
+ {
1504
+ key: '存貨單位(SKU)',
1505
+ value: `<span class="fs-7">${dd.sku || '-'}</span>`,
1506
+ },
1507
+ ];
1508
+ const endArr = [
1509
+ {
1510
+ key: '備註',
1511
+ value: `<span class="fs-7">${dd.note || '-'}</span>`,
1512
+ },
1513
+ ];
1514
+ switch (json.type) {
1515
+ case 'nonDetails':
1042
1516
  return [
1043
- {
1044
- key: '商品',
1045
- value: `<span class="fs-7">${dd.title || '-'}</span>`,
1046
- },
1047
- {
1048
- key: '規格',
1049
- value: `<span class="fs-7">${dd.spec}</span>`,
1050
- },
1051
- {
1052
- key: '存貨單位(SKU)',
1053
- value: `<span class="fs-7">${dd.sku || '-'}</span>`,
1054
- },
1517
+ ...startArr,
1055
1518
  {
1056
1519
  key: '進貨成本',
1057
1520
  value: `<span class="fs-7">${dd.cost || '-'}</span>`,
@@ -1067,25 +1530,11 @@ export class StockHistory {
1067
1530
  return html`<span class="fs-7">$ ${subtotal.toLocaleString()}</span>`;
1068
1531
  })(),
1069
1532
  },
1070
- {
1071
- key: '備註',
1072
- value: `<span class="fs-7">${dd.note || '-'}</span>`,
1073
- },
1533
+ ...endArr,
1074
1534
  ];
1075
- } else {
1535
+ case 'details':
1076
1536
  return [
1077
- {
1078
- key: '商品',
1079
- value: `<span class="fs-7">${dd.title || '-'}</span>`,
1080
- },
1081
- {
1082
- key: '規格',
1083
- value: `<span class="fs-7">${dd.spec}</span>`,
1084
- },
1085
- {
1086
- key: '存貨單位(SKU)',
1087
- value: `<span class="fs-7">${dd.sku || '-'}</span>`,
1088
- },
1537
+ ...startArr,
1089
1538
  {
1090
1539
  key: '進貨成本',
1091
1540
  value: `<span class="fs-7">${dd.cost || '-'}</span>`,
@@ -1132,14 +1581,166 @@ export class StockHistory {
1132
1581
  return html`<span class="fs-7">$ ${subtotal.toLocaleString()}</span>`;
1133
1582
  })(),
1134
1583
  },
1584
+ ...endArr,
1585
+ ];
1586
+ case 'logs':
1587
+ return [
1588
+ ...startArr,
1589
+ {
1590
+ key: `原訂進貨數量`,
1591
+ value: `<span class="fs-7">${dd.transfer_count || '-'}</span>`,
1592
+ },
1593
+ {
1594
+ key: '實際進貨數量',
1595
+ value: `<span class="fs-7">${(dd.recent_count ?? 0) - (dd.replenishment_count ?? 0)}</span>`,
1596
+ },
1135
1597
  {
1136
- key: '備註',
1137
- value: `<span class="fs-7">${dd.note || '-'}</span>`,
1598
+ key: '差異數量',
1599
+ value: (() => {
1600
+ if (dd.recent_count === undefined) {
1601
+ return html`<span class="fs-7">-</span>`;
1602
+ }
1603
+
1604
+ const n = dd.recent_count - dd.transfer_count - (dd.replenishment_count ?? 0);
1605
+ if (n === 0) {
1606
+ return html`<span class="fs-7">0</span>`;
1607
+ } else if (n < 0) {
1608
+ return html`<span class="fs-7 tc_danger">${n}</span>`;
1609
+ } else if (dd.recent_count > dd.transfer_count) {
1610
+ return html`<span class="fs-7 tc_success">+${n}</span>`;
1611
+ }
1612
+ })(),
1138
1613
  },
1614
+ {
1615
+ key: '此次補貨數量',
1616
+ value: dd.replenishment_count ? html`<span class="fs-7 tc_success">+${dd.replenishment_count ?? 0}</span>` : html`<span class="fs-7">-</span>`,
1617
+ },
1618
+ ...endArr,
1139
1619
  ];
1140
- }
1141
- });
1142
- }
1620
+ }
1621
+ });
1622
+ }
1623
+
1624
+ static transferDetailTable(json: { type: 'details' | 'nonDetails' | 'logs'; list: ContentProduct[]; page: number; limit: number }) {
1625
+ const x = (json.page - 1) * json.limit;
1626
+ return json.list.slice(x, x + json.limit).map((dd: ContentProduct) => {
1627
+ const startArr = [
1628
+ {
1629
+ key: '商品',
1630
+ value: `<span class="fs-7">${dd.title || '-'}</span>`,
1631
+ },
1632
+ {
1633
+ key: '規格',
1634
+ value: `<span class="fs-7">${dd.spec}</span>`,
1635
+ },
1636
+ {
1637
+ key: '存貨單位(SKU)',
1638
+ value: `<span class="fs-7">${dd.sku || '-'}</span>`,
1639
+ },
1640
+ ];
1641
+ const endArr = [
1642
+ {
1643
+ key: '備註',
1644
+ value: `<span class="fs-7">${dd.note || '-'}</span>`,
1645
+ },
1646
+ ];
1647
+ switch (json.type) {
1648
+ case 'nonDetails':
1649
+ return [
1650
+ ...startArr,
1651
+ {
1652
+ key: '來源庫存數量',
1653
+ value: `<span class="fs-7">unknown1</span>`,
1654
+ },
1655
+ {
1656
+ key: '預計調入數量',
1657
+ value: `<span class="fs-7">${dd.transfer_count || '-'}</span>`,
1658
+ },
1659
+ ...endArr,
1660
+ ];
1661
+ case 'details':
1662
+ return [
1663
+ ...startArr,
1664
+ {
1665
+ key: '來源庫存數量',
1666
+ value: `<span class="fs-7">unknown1</span>`,
1667
+ },
1668
+ {
1669
+ key: '原訂調入數量',
1670
+ value: `<span class="fs-7">${dd.transfer_count || '-'}</span>`,
1671
+ },
1672
+ {
1673
+ key: '實際調入數量',
1674
+ value: `<span class="fs-7">${dd.recent_count || '-'}</span>`,
1675
+ },
1676
+ {
1677
+ key: '差異數量',
1678
+ value: (() => {
1679
+ if (dd.recent_count === undefined) {
1680
+ return html`<span class="fs-7">-</span>`;
1681
+ }
1682
+
1683
+ const n = dd.recent_count - dd.transfer_count;
1684
+ if (n === 0) {
1685
+ return html`<span class="fs-7">0</span>`;
1686
+ } else if (n < 0) {
1687
+ return html`<span class="fs-7 tc_danger">${n}</span>`;
1688
+ } else if (dd.recent_count > dd.transfer_count) {
1689
+ return html`<span class="fs-7 tc_success">+${n}</span>`;
1690
+ }
1691
+ })(),
1692
+ },
1693
+ ...endArr,
1694
+ ];
1695
+ case 'logs':
1696
+ return [
1697
+ ...startArr,
1698
+ {
1699
+ key: '原訂調入數量',
1700
+ value: `<span class="fs-7">${dd.transfer_count || '-'}</span>`,
1701
+ },
1702
+ {
1703
+ key: '實際調入數量',
1704
+ value: `<span class="fs-7">${(dd.recent_count ?? 0) - (dd.replenishment_count ?? 0)}</span>`,
1705
+ },
1706
+ {
1707
+ key: '差異數量',
1708
+ value: (() => {
1709
+ if (dd.recent_count === undefined) {
1710
+ return html`<span class="fs-7">-</span>`;
1711
+ }
1712
+
1713
+ const n = dd.recent_count - dd.transfer_count - (dd.replenishment_count ?? 0);
1714
+ if (n === 0) {
1715
+ return html`<span class="fs-7">0</span>`;
1716
+ } else if (n < 0) {
1717
+ return html`<span class="fs-7 tc_danger">${n}</span>`;
1718
+ } else if (dd.recent_count > dd.transfer_count) {
1719
+ return html`<span class="fs-7 tc_success">+${n}</span>`;
1720
+ }
1721
+ })(),
1722
+ },
1723
+ {
1724
+ key: '此次補貨數量',
1725
+ value: dd.replenishment_count ? html`<span class="fs-7 tc_success">+${dd.replenishment_count ?? 0}</span>` : html`<span class="fs-7">-</span>`,
1726
+ },
1727
+ ...endArr,
1728
+ ];
1729
+ }
1730
+ });
1731
+ }
1732
+
1733
+ static replaceOrder(gvc: GVC, vm: VM) {
1734
+ const typeData = typeConfig[vm.type];
1735
+ let vmi: any = undefined;
1736
+
1737
+ const transfer_total = vm.data.content.product_list.reduce((sum, item) => {
1738
+ return sum + item.cost * item.transfer_count;
1739
+ }, 0);
1740
+
1741
+ const recent_total = vm.data.content.product_list.reduce((sum, item) => {
1742
+ return sum + item.cost * (item.recent_count ?? 0);
1743
+ }, 0);
1143
1744
 
1144
1745
  return BgWidget.container(
1145
1746
  [
@@ -1150,7 +1751,7 @@ export class StockHistory {
1150
1751
  })
1151
1752
  )}
1152
1753
  <div>${BgWidget.title(vm.data.order_id)}</div>
1153
- <span class="d-none mt-1 ms-2 fs-7">${StockHistory.getStatusBadge(vm.data.status)}</span>
1754
+ <span class="mt-1 ms-2 fs-7">${StockHistory.getStatusBadge(vm.data.type, vm.data.status)}</span>
1154
1755
  </div>
1155
1756
  <div class="flex-fill"></div>`,
1156
1757
  html` <div class="d-flex justify-content-center ${document.body.clientWidth < 768 ? 'flex-column' : ''}" style="gap: 24px">
@@ -1160,13 +1761,20 @@ export class StockHistory {
1160
1761
  [
1161
1762
  html` <div class="tx_700">${typeData.name}單資料</div>`,
1162
1763
  BgWidget.horizontalLine({ margin: 0 }),
1163
- html` <div class="d-flex flex-wrap" style="gap: 18px 0;">${this.getContentHTML(gvc, vm.data)}</div> `,
1764
+ html`
1765
+ <div class="d-flex flex-wrap" style="gap: 18px 0;">
1766
+ ${this.getContentHTML(gvc, vm.data, {
1767
+ transfer_total,
1768
+ recent_total,
1769
+ })}
1770
+ </div>
1771
+ `,
1164
1772
  ].join(BgWidget.mbContainer(18))
1165
1773
  ),
1166
1774
  BgWidget.mainCard(
1167
1775
  [
1168
1776
  html`
1169
- <div class="tx_700">進貨商品</div>
1777
+ <div class="tx_700">${typeData.name}商品</div>
1170
1778
  ${BgWidget.mbContainer(18)}
1171
1779
  ${[
1172
1780
  BgWidget.tableV3({
@@ -1183,7 +1791,46 @@ export class StockHistory {
1183
1791
  vm.data.content.product_list = response;
1184
1792
  vmi.pageSize = Math.ceil(response.length / limit);
1185
1793
  vmi.originalData = response;
1186
- vmi.tableData = specDatalist(vmi.page, limit);
1794
+
1795
+ switch (vm.data.type) {
1796
+ case 'restocking':
1797
+ if ([0, 1, 2].includes(vm.data.status)) {
1798
+ vmi.tableData = this.restockingDetailTable({
1799
+ type: 'nonDetails',
1800
+ list: vm.data.content.product_list,
1801
+ page: vmi.page,
1802
+ limit,
1803
+ });
1804
+ } else {
1805
+ vmi.tableData = this.restockingDetailTable({
1806
+ type: 'details',
1807
+ list: vm.data.content.product_list,
1808
+ page: vmi.page,
1809
+ limit,
1810
+ });
1811
+ }
1812
+ break;
1813
+ case 'transfer':
1814
+ if ([0, 1, 2].includes(vm.data.status)) {
1815
+ vmi.tableData = this.transferDetailTable({
1816
+ type: 'nonDetails',
1817
+ list: vm.data.content.product_list,
1818
+ page: vmi.page,
1819
+ limit,
1820
+ });
1821
+ } else {
1822
+ vmi.tableData = this.transferDetailTable({
1823
+ type: 'details',
1824
+ list: vm.data.content.product_list,
1825
+ page: vmi.page,
1826
+ limit,
1827
+ });
1828
+ }
1829
+ break;
1830
+ case 'checking':
1831
+ break;
1832
+ }
1833
+
1187
1834
  vmi.loading = false;
1188
1835
  vmi.callback();
1189
1836
  }
@@ -1193,25 +1840,101 @@ export class StockHistory {
1193
1840
  filter: [],
1194
1841
  hiddenPageSplit: true,
1195
1842
  }),
1196
- BgWidget.horizontalLine({ margin: 1.75 }),
1197
1843
  (() => {
1198
- const total = vm.data.content.product_list.reduce((sum, item) => {
1199
- return sum + item.cost * item.transfer_count;
1200
- }, 0);
1201
-
1202
- return html` <div class="d-flex w-100">
1203
- <div class="flex-fill"></div>
1204
- <div class="d-flex justify-content-between tx_700" style="width: 200px;">
1205
- <div>進貨總成本</div>
1206
- <div>$ ${total.toLocaleString()}</div>
1207
- </div>
1208
- </div>`;
1844
+ if (vm.data.type !== 'restocking') {
1845
+ return '';
1846
+ }
1847
+ const priceHTML = (obj: { name: string; price: number; className?: string; incompletion?: boolean }) => {
1848
+ return html`<div class="d-flex w-100 mb-2">
1849
+ <div class="flex-fill"></div>
1850
+ <div class="d-flex justify-content-between" style="width: 250px;">
1851
+ <div class="${obj.className ?? ''}">${obj.name}</div>
1852
+ ${obj.incompletion
1853
+ ? html`<div style="color: #8D8D8D">商品尚未核對完成</div>`
1854
+ : html`<div class="${obj.className ?? ''}">$ ${obj.price.toLocaleString()}</div>`}
1855
+ </div>
1856
+ </div>`;
1857
+ };
1858
+
1859
+ return [
1860
+ BgWidget.horizontalLine({ margin: 1.75 }),
1861
+ priceHTML({
1862
+ name: '原訂總成本',
1863
+ price: transfer_total,
1864
+ }),
1865
+ priceHTML({
1866
+ name: '實際總成本',
1867
+ price: recent_total,
1868
+ className: 'tx_700',
1869
+ incompletion: vm.data.status === 4,
1870
+ }),
1871
+ priceHTML({
1872
+ name: '差異金額',
1873
+ price: transfer_total - recent_total,
1874
+ className: 'tx_700',
1875
+ incompletion: vm.data.status === 4,
1876
+ }),
1877
+ ].join('');
1209
1878
  })(),
1210
1879
  ].join('')}
1211
1880
  `,
1212
1881
  ].join(BgWidget.mbContainer(18))
1213
1882
  ),
1214
- BgWidget.mainCard([html` <div class="tx_700">${typeData.name}紀錄</div>`].join(BgWidget.mbContainer(18))),
1883
+ BgWidget.mainCard(
1884
+ [
1885
+ html` <div class="tx_700">${typeData.name}紀錄</div>`,
1886
+ vm.data.content.changeLogs
1887
+ .sort((a, b) => {
1888
+ return a.time > b.time ? -1 : 1;
1889
+ })
1890
+ .map((log) => {
1891
+ return html`<div class="d-flex justify-content-between align-items-center mt-2">
1892
+ <div class="d-flex align-items-center">
1893
+ <div class="me-3">${log.time}</div>
1894
+ <div class="me-1">${log.text}</div>
1895
+ ${log.status === 1 || log.status === 5
1896
+ ? html`<i
1897
+ class="fa-thin fa-square-list cursor_pointer"
1898
+ onclick="${gvc.event(() => {
1899
+ BgWidget.dialog({
1900
+ gvc,
1901
+ title: `${typeData.name}紀錄`,
1902
+ width: 1000,
1903
+ innerHTML: (gvc) => {
1904
+ return BgWidget.tableV3({
1905
+ gvc: gvc,
1906
+ getData: (vd) => {
1907
+ vmi = vd;
1908
+ const limit = 99999;
1909
+ this.getVariantInfo(log.product_list ?? [], (response) => {
1910
+ vmi.pageSize = Math.ceil(response.length / limit);
1911
+ vmi.originalData = response;
1912
+ vmi.tableData = this.restockingDetailTable({
1913
+ type: 'logs',
1914
+ list: response,
1915
+ page: vmi.page,
1916
+ limit,
1917
+ });
1918
+ vmi.loading = false;
1919
+ vmi.callback();
1920
+ });
1921
+ },
1922
+ rowClick: () => {},
1923
+ filter: [],
1924
+ hiddenPageSplit: true,
1925
+ });
1926
+ },
1927
+ });
1928
+ })}"
1929
+ ></i>`
1930
+ : ''}
1931
+ </div>
1932
+ <div>${log.user}</div>
1933
+ </div>`;
1934
+ })
1935
+ .join(''),
1936
+ ].join(BgWidget.mbContainer(18))
1937
+ ),
1215
1938
  ].join(BgWidget.mbContainer(18))
1216
1939
  )}
1217
1940
  </div>`,
@@ -1351,8 +2074,8 @@ export class StockHistory {
1351
2074
  </div>`;
1352
2075
  }
1353
2076
 
1354
- static getStatusBadge(status: number) {
1355
- const statusData = statusConfig[status];
2077
+ static getStatusBadge(type: StockHistoryType, status: number) {
2078
+ const statusData = typeConfig[type].status[status];
1356
2079
  switch (statusData.badge) {
1357
2080
  case 'info':
1358
2081
  return BgWidget.infoInsignia(statusData.title);
@@ -1367,7 +2090,14 @@ export class StockHistory {
1367
2090
  }
1368
2091
  }
1369
2092
 
1370
- static getContentHTML(gvc: GVC, data: StockHistoryData) {
2093
+ static getContentHTML(
2094
+ gvc: GVC,
2095
+ data: StockHistoryData,
2096
+ obj: {
2097
+ transfer_total: number;
2098
+ recent_total: number;
2099
+ }
2100
+ ) {
1371
2101
  const glitter = gvc.glitter;
1372
2102
  const vm = {
1373
2103
  id: glitter.getUUID(),
@@ -1376,6 +2106,7 @@ export class StockHistory {
1376
2106
  storeList: [] as { id: string; name: string }[],
1377
2107
  vendorList: [] as { id: string; name: string }[],
1378
2108
  };
2109
+ const typeData = typeConfig[data.type];
1379
2110
  return gvc.bindView({
1380
2111
  bind: vm.id,
1381
2112
  view: () => {
@@ -1385,22 +2116,78 @@ export class StockHistory {
1385
2116
  circle: { visible: false },
1386
2117
  });
1387
2118
  } else {
1388
- const total = vm.data.content.product_list.reduce((sum, item) => {
1389
- return sum + item.cost * item.transfer_count;
1390
- }, 0);
1391
2119
  const vendor = vm.vendorList.find((v) => v.id === vm.data.content.vendor);
1392
- const store = vm.storeList.find((s) => s.id === vm.data.content.store_in);
2120
+ const storeIn = vm.storeList.find((s) => s.id === vm.data.content.store_in);
2121
+ const storeOut = vm.storeList.find((s) => s.id === vm.data.content.store_out);
1393
2122
 
1394
- return [
1395
- { title: '進貨單編號', value: vm.data.order_id },
1396
- { title: '進貨日期', value: vm.data.created_time },
1397
- { title: '進貨單狀態', value: StockHistory.getStatusBadge(vm.data.status) },
1398
- { title: '供應商', value: vendor ? vendor.name : '' },
1399
- { title: '庫存點', value: store ? store.name : '' },
1400
- { title: '原定總成本 / 實際總成本', value: `$${total.toLocaleString()} / -` },
1401
- { title: '差異金額', value: (total - 0).toLocaleString() },
1402
- { title: '備註', value: vm.data.content.note ?? '', width: 40 },
1403
- ]
2123
+ const startArr = [
2124
+ {
2125
+ title: `${typeData.name}單編號`,
2126
+ value: vm.data.order_id,
2127
+ },
2128
+ {
2129
+ title: `${typeData.name}日期`,
2130
+ value: vm.data.created_time,
2131
+ },
2132
+ {
2133
+ title: `${typeData.name}單狀態`,
2134
+ value: typeConfig[vm.data.type].status[vm.data.status].title,
2135
+ },
2136
+ ];
2137
+ const endArr = [
2138
+ {
2139
+ title: '備註',
2140
+ value: vm.data.content.note ?? '',
2141
+ width: 40,
2142
+ },
2143
+ ];
2144
+
2145
+ const arr: {
2146
+ title: string;
2147
+ value: string;
2148
+ width?: number;
2149
+ }[] = (() => {
2150
+ switch (data.type) {
2151
+ case 'restocking':
2152
+ return [
2153
+ ...startArr,
2154
+ {
2155
+ title: '供應商',
2156
+ value: vendor ? vendor.name : '',
2157
+ },
2158
+ {
2159
+ title: '庫存點',
2160
+ value: storeIn ? storeIn.name : '',
2161
+ },
2162
+ {
2163
+ title: '原定總成本 / 實際總成本',
2164
+ value: `$${obj.transfer_total.toLocaleString()} / $${obj.recent_total.toLocaleString()}`,
2165
+ },
2166
+ {
2167
+ title: '差異金額',
2168
+ value: `$${(obj.transfer_total - obj.recent_total).toLocaleString()}`,
2169
+ },
2170
+ ...endArr,
2171
+ ];
2172
+ case 'transfer':
2173
+ return [
2174
+ ...startArr,
2175
+ {
2176
+ title: '調出庫存點',
2177
+ value: storeOut ? storeOut.name : '',
2178
+ },
2179
+ {
2180
+ title: '調出庫入點',
2181
+ value: storeIn ? storeIn.name : '',
2182
+ },
2183
+ ...endArr,
2184
+ ];
2185
+ case 'checking':
2186
+ return [...startArr, ...endArr];
2187
+ }
2188
+ })();
2189
+
2190
+ return arr
1404
2191
  .map((item) => {
1405
2192
  return html`<div style="${document.body.clientWidth > 768 ? `width: ${item.width ?? 20}%;` : ''}">
1406
2193
  <div class="tx_700" style="margin-bottom: 8px;">${item.title}</div>
@@ -1436,6 +2223,7 @@ export class StockHistory {
1436
2223
  static getButtonBar(gvc: GVC, vm: VM) {
1437
2224
  const glitter = gvc.glitter;
1438
2225
  const dialog = new ShareDialog(glitter);
2226
+ const typeData = typeConfig[vm.data.type];
1439
2227
  const buttonList = [
1440
2228
  BgWidget.cancel(
1441
2229
  gvc.event(() => {
@@ -1450,32 +2238,75 @@ export class StockHistory {
1450
2238
  ),
1451
2239
  ];
1452
2240
 
1453
- function updateData(status: number) {
1454
- vm.data.status = status;
1455
- ApiStock.putStockHistory(vm.data).then((r) => {
1456
- dialog.dataLoading({ visible: false });
1457
- if (r.result && r.response) {
1458
- dialog.successMessage({ text: '保存成功' });
1459
- setTimeout(() => {
1460
- vm.view = 'replace';
1461
- }, 700);
1462
- } else {
1463
- dialog.successMessage({ text: '保存失敗' });
1464
- }
2241
+ function updateData(status: number, warningText?: string) {
2242
+ dialog.warningMessage({
2243
+ callback: (bool) => {
2244
+ if (bool) {
2245
+ vm.data.status = status;
2246
+ ApiStock.putStockHistory(vm.data).then((r) => {
2247
+ dialog.dataLoading({ visible: false });
2248
+ if (r.result && r.response) {
2249
+ dialog.successMessage({ text: '更新成功' });
2250
+ setTimeout(() => {
2251
+ vm.view = 'replace';
2252
+ }, 700);
2253
+ } else {
2254
+ dialog.successMessage({ text: '更新失敗' });
2255
+ }
2256
+ });
2257
+ }
2258
+ },
2259
+ text: warningText && warningText.length > 0 ? warningText : `確定要更新此${typeData.name}單?`,
1465
2260
  });
1466
2261
  }
1467
2262
 
1468
2263
  function deleteData() {
1469
- ApiStock.deleteStockHistory(vm.data).then((r) => {
1470
- dialog.dataLoading({ visible: false });
1471
- if (r.result && r.response) {
1472
- dialog.successMessage({ text: '刪除成功' });
1473
- setTimeout(() => {
1474
- vm.view = 'mainList';
1475
- }, 700);
1476
- } else {
1477
- dialog.successMessage({ text: '刪除失敗' });
1478
- }
2264
+ dialog.warningMessage({
2265
+ callback: (bool) => {
2266
+ if (bool) {
2267
+ ApiStock.deleteStockHistory(vm.data).then((r) => {
2268
+ dialog.dataLoading({ visible: false });
2269
+ if (r.result && r.response) {
2270
+ dialog.successMessage({ text: '刪除成功' });
2271
+ setTimeout(() => {
2272
+ vm.view = 'mainList';
2273
+ }, 700);
2274
+ } else {
2275
+ dialog.successMessage({ text: '刪除失敗' });
2276
+ }
2277
+ });
2278
+ }
2279
+ },
2280
+ text: (() => {
2281
+ switch (vm.data.type) {
2282
+ case 'restocking':
2283
+ return html`
2284
+ <div class="my-2">
2285
+ <div class="tx_normal">刪除${typeData.name}單後將無法復原,${typeData.name}記錄將被移除,且不會</div>
2286
+ <div class="tx_normal">對現有庫存數量產生影響。確定要刪除此${typeData.name}單嗎?</div>
2287
+ ${BgWidget.mbContainer(8)}
2288
+ <div class="tx_gray_14">※提醒您,請確認${typeData.name}單貨品是否已到貨,若已到貨,請先進</div>
2289
+ <div class="tx_gray_14">行核對,確保庫存正確,避免退貨單扣除尚未新增的庫存。</div>
2290
+ </div>
2291
+ `;
2292
+ case 'transfer':
2293
+ return html`
2294
+ <div class="my-2">
2295
+ <div class="tx_normal">刪除調撥單後將無法復原,調撥記錄將被移除,且不會</div>
2296
+ <div class="tx_normal">對現有庫存數量產生影響。確定要刪除此調撥單嗎?</div>
2297
+ ${BgWidget.mbContainer(8)}
2298
+ <div class="tx_gray_14">※提醒您,請確認調撥單貨品是否已到貨,若已到貨,請先進</div>
2299
+ <div class="tx_gray_14">行核對,避免退還原庫存點時,扣除尚未新增的庫存。</div>
2300
+ </div>
2301
+ `;
2302
+ case 'checking':
2303
+ return html`
2304
+ <div class="my-2">
2305
+ <div class="tx_normal">刪除盤點單後將無法復原,確定要刪除此調撥單嗎?</div>
2306
+ </div>
2307
+ `;
2308
+ }
2309
+ })(),
1479
2310
  });
1480
2311
  }
1481
2312
 
@@ -1486,37 +2317,149 @@ export class StockHistory {
1486
2317
  gvc.event(() => {
1487
2318
  deleteData();
1488
2319
  }),
1489
- '刪除進貨單'
2320
+ `刪除${typeData.name}單`
1490
2321
  )
1491
2322
  );
1492
2323
  }
2324
+
1493
2325
  if ([5].includes(vm.data.status)) {
1494
2326
  buttonList.push(
1495
2327
  BgWidget.grayButton(
2328
+ `完成${typeData.name}}`,
1496
2329
  gvc.event(() => {
1497
- updateData(1);
1498
- }),
1499
- '完成進貨'
2330
+ updateData(
2331
+ 0,
2332
+ (() => {
2333
+ switch (vm.data.type) {
2334
+ case 'restocking':
2335
+ return html`
2336
+ <div class="my-2">
2337
+ <div class="tx_normal">目前${typeData.name}的商品數量與原訂數量存在差異,</div>
2338
+ <div class="tx_normal">確定要完成${typeData.name}嗎?</div>
2339
+ ${BgWidget.mbContainer(8)}
2340
+ <div class="tx_gray_14">※完成${typeData.name}後,此${typeData.name}單將被標記為已完成,</div>
2341
+ <div class="tx_gray_14">後續無法再進行補貨操作。</div>
2342
+ </div>
2343
+ `;
2344
+ case 'transfer':
2345
+ return html`
2346
+ <div class="my-2">
2347
+ <div class="tx_normal">目前調撥的商品數量與原訂數量存在差異,</div>
2348
+ <div class="tx_normal">確定要完成調撥嗎?</div>
2349
+ ${BgWidget.mbContainer(8)}
2350
+ <div class="tx_gray_14">※完成調撥後,此調撥單將被標記為已完成,</div>
2351
+ <div class="tx_gray_14">後續無法再進行補貨操作。</div>
2352
+ </div>
2353
+ `;
2354
+ case 'checking':
2355
+ return html`finished check`;
2356
+ }
2357
+ })()
2358
+ );
2359
+ })
1500
2360
  )
1501
2361
  );
1502
2362
  }
2363
+
1503
2364
  if ([0, 1, 4, 5].includes(vm.data.status)) {
2365
+ const text = (() => {
2366
+ switch (vm.data.status) {
2367
+ case 4:
2368
+ switch (vm.data.type) {
2369
+ case 'restocking':
2370
+ case 'transfer':
2371
+ return html`
2372
+ <div class="my-2">
2373
+ <div class="tx_normal">${typeData.name}單目前處於「已暫停」狀態,請完成所有商品數量的</div>
2374
+ <div class="tx_normal">核對,確認庫存數據無誤後再進行取消操作。</div>
2375
+ </div>
2376
+ `;
2377
+ case 'checking':
2378
+ return '';
2379
+ }
2380
+ case 5:
2381
+ switch (vm.data.type) {
2382
+ case 'restocking':
2383
+ return html`
2384
+ <div class="my-2">
2385
+ <div class="tx_normal">取消後將無法再修正,確定要取消此${typeData.name}單嗎?</div>
2386
+ ${BgWidget.mbContainer(8)}
2387
+ <div class="tx_gray_14">※請確認商品是否已補貨,若已補貨但尚未核對,</div>
2388
+ <div class="tx_gray_14">取消${typeData.name}單可能會導致庫存數據不正確。</div>
2389
+ ${BgWidget.mbContainer(8)}
2390
+ <div class="tx_gray_14">※取消後請新增「${typeData.name}退回單」,並退還商品與發票。</div>
2391
+ </div>
2392
+ `;
2393
+ case 'transfer':
2394
+ return html`
2395
+ <div class="my-2">
2396
+ <div class="tx_normal">取消後將無法再修正,確定要取消此${typeData.name}單嗎?</div>
2397
+ ${BgWidget.mbContainer(8)}
2398
+ <div class="tx_gray_14">※請確認商品是否已補貨,若已補貨但尚未核對,</div>
2399
+ <div class="tx_gray_14">取消${typeData.name}單可能會導致庫存數據不正確。</div>
2400
+ ${BgWidget.mbContainer(8)}
2401
+ <div class="tx_gray_14">※取消後請新增全新的「調撥單」,並退還商品。</div>
2402
+ </div>
2403
+ `;
2404
+ case 'checking':
2405
+ return html`
2406
+ <div class="my-2">
2407
+ <div class="tx_normal">取消後將無法再修正,確定要取消此${typeData.name}單嗎?</div>
2408
+ ${BgWidget.mbContainer(8)}
2409
+ <div class="tx_gray_14">※提醒您,此盤點單存在數量差異,請確認該差異是否無需更新至庫存。</div>
2410
+ </div>
2411
+ `;
2412
+ }
2413
+ default:
2414
+ switch (vm.data.type) {
2415
+ case 'restocking':
2416
+ return html`
2417
+ <div class="my-2">
2418
+ <div class="tx_normal">取消後將無法復原,確定要取消此${typeData.name}單嗎?</div>
2419
+ ${BgWidget.mbContainer(8)}
2420
+ <div class="tx_gray_14">※提醒您,取消${typeData.name}單後,請新增「${typeData.name}退回單」並將</div>
2421
+ <div class="tx_gray_14">商品及發票一併退還給供應商,確保退貨流程完整。</div>
2422
+ </div>
2423
+ `;
2424
+ case 'transfer':
2425
+ return html`
2426
+ <div class="my-2">
2427
+ <div class="tx_normal">取消後將無法復原,確定要取消此${typeData.name}單嗎?</div>
2428
+ ${BgWidget.mbContainer(8)}
2429
+ <div class="tx_gray_14">※提醒您,取消後請新增一張全新的「調撥單」,將商</div>
2430
+ <div class="tx_gray_14">品調回原庫存點,以確保庫存準確且流程完整。</div>
2431
+ </div>
2432
+ `;
2433
+ case 'checking':
2434
+ return html`
2435
+ <div class="my-2">
2436
+ <div class="tx_normal">取消後將無法復原,確定要取消此${typeData.name}單嗎?</div>
2437
+ ${BgWidget.mbContainer(8)}
2438
+ <div class="tx_gray_14">※提醒您,若盤點單已提交且存在數量差異,系統將回</div>
2439
+ <div class="tx_gray_14">復至調整前的庫存狀態。</div>
2440
+ </div>
2441
+ `;
2442
+ }
2443
+ }
2444
+ })();
2445
+
1504
2446
  buttonList.push(
1505
2447
  BgWidget.danger(
1506
2448
  gvc.event(() => {
1507
- updateData(6);
2449
+ updateData(6, text);
1508
2450
  }),
1509
- '取消進貨單'
2451
+ `取消${typeData.name}單`
1510
2452
  )
1511
2453
  );
1512
2454
  }
2455
+
1513
2456
  if ([2, 4, 5].includes(vm.data.status)) {
1514
2457
  buttonList.push(
1515
2458
  BgWidget.save(
1516
2459
  gvc.event(() => {
1517
2460
  vm.view = 'checkList';
1518
2461
  }),
1519
- '進貨核對'
2462
+ `${typeData.name}核對`
1520
2463
  )
1521
2464
  );
1522
2465
  }
@@ -1528,7 +2471,7 @@ export class StockHistory {
1528
2471
  return typeof item.recent_count === 'number' && !isNaN(item.recent_count);
1529
2472
  });
1530
2473
  const isEqual = vm.data.content.product_list.every((item) => {
1531
- return typeof item.recent_count === 'number' && !isNaN(item.recent_count) && item.recent_count === item.transfer_count;
2474
+ return typeof item.recent_count === 'number' && !isNaN(item.recent_count) && item.recent_count >= item.transfer_count;
1532
2475
  });
1533
2476
 
1534
2477
  buttonList.push(
@@ -1622,6 +2565,37 @@ export class StockHistory {
1622
2565
  callback(product_list);
1623
2566
  });
1624
2567
  }
2568
+
2569
+ static getVariantInfo(dataList: ContentProduct[], callback: (list: ContentProduct[]) => void) {
2570
+ ApiShop.getVariants({
2571
+ page: 0,
2572
+ limit: 99999,
2573
+ id_list: dataList.map((item) => item.variant_id).join(','),
2574
+ productType: 'all',
2575
+ }).then((r) => {
2576
+ let product_list: ContentProduct[] = [];
2577
+ if (r.result && r.response.data) {
2578
+ r.response.data.forEach((item: any) => {
2579
+ const origin = dataList.find((o) => {
2580
+ return o.variant_id === item.id;
2581
+ });
2582
+ const title = item.product_content.title;
2583
+ const spec = item.variant_content.spec;
2584
+ const sku = item.variant_content.sku;
2585
+
2586
+ if (origin) {
2587
+ product_list.push({
2588
+ ...origin,
2589
+ title: title,
2590
+ spec: spec && spec.length > 0 ? spec.join('/') : '單一規格',
2591
+ sku: sku ?? '',
2592
+ });
2593
+ }
2594
+ });
2595
+ }
2596
+ callback(product_list);
2597
+ });
2598
+ }
1625
2599
  }
1626
2600
 
1627
2601
  (window as any).glitter.setModule(import.meta.url, StockHistory);