@things-factory/operato-wms 5.0.0-alpha.2 → 5.0.0-alpha.22

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/client/pages/inbound/serial-number-list-popup.js +342 -0
  2. package/client/pages/inbound/unload-product.js +220 -41
  3. package/client/pages/inbound/unloaded-inventories-popup.js +7 -0
  4. package/client/pages/inventory/non-loaded-inventory.js +297 -0
  5. package/client/pages/order/release-order/b2b/b2b-order-list.js +41 -18
  6. package/client/pages/order/release-order/b2c/b2c-order-requests.js +40 -18
  7. package/client/pages/outbound/packing-product.js +88 -80
  8. package/client/pages/outbound/picking-product.js +61 -36
  9. package/client/pages/outbound/serial-number-popup.js +150 -64
  10. package/client/pages/report/inbound-serial-number-report.js +452 -0
  11. package/client/pages/report/outbound-order-details-report.js +64 -9
  12. package/client/pages/report/outbound-serial-number-report.js +467 -0
  13. package/client/route.js +11 -0
  14. package/dist-server/graphql/resolvers/reports/inbound-serial-number-report.js +111 -0
  15. package/dist-server/graphql/resolvers/reports/inbound-serial-number-report.js.map +1 -0
  16. package/dist-server/graphql/resolvers/reports/index.js +3 -1
  17. package/dist-server/graphql/resolvers/reports/index.js.map +1 -1
  18. package/dist-server/graphql/resolvers/reports/outbound-order-details-report.js +53 -48
  19. package/dist-server/graphql/resolvers/reports/outbound-order-details-report.js.map +1 -1
  20. package/dist-server/graphql/resolvers/reports/outbound-serial-number-report.js +118 -0
  21. package/dist-server/graphql/resolvers/reports/outbound-serial-number-report.js.map +1 -0
  22. package/dist-server/graphql/types/reports/inbound-serial-number-report-list.js +14 -0
  23. package/dist-server/graphql/types/reports/inbound-serial-number-report-list.js.map +1 -0
  24. package/dist-server/graphql/types/reports/inbound-serial-number-report.js +23 -0
  25. package/dist-server/graphql/types/reports/inbound-serial-number-report.js.map +1 -0
  26. package/dist-server/graphql/types/reports/index.js +10 -0
  27. package/dist-server/graphql/types/reports/index.js.map +1 -1
  28. package/dist-server/graphql/types/reports/outbound-order-details-report.js +3 -0
  29. package/dist-server/graphql/types/reports/outbound-order-details-report.js.map +1 -1
  30. package/dist-server/graphql/types/reports/outbound-serial-number-report-list.js +14 -0
  31. package/dist-server/graphql/types/reports/outbound-serial-number-report-list.js.map +1 -0
  32. package/dist-server/graphql/types/reports/outbound-serial-number-report.js +25 -0
  33. package/dist-server/graphql/types/reports/outbound-serial-number-report.js.map +1 -0
  34. package/dist-server/migrations/1568858861188-SeedSetting.js +2 -1
  35. package/dist-server/migrations/1568858861188-SeedSetting.js.map +1 -1
  36. package/package.json +67 -66
  37. package/server/graphql/resolvers/reports/inbound-serial-number-report.ts +128 -0
  38. package/server/graphql/resolvers/reports/index.ts +5 -0
  39. package/server/graphql/resolvers/reports/outbound-order-details-report.ts +54 -48
  40. package/server/graphql/resolvers/reports/outbound-serial-number-report.ts +135 -0
  41. package/server/graphql/types/reports/inbound-serial-number-report-list.ts +8 -0
  42. package/server/graphql/types/reports/inbound-serial-number-report.ts +17 -0
  43. package/server/graphql/types/reports/index.ts +11 -0
  44. package/server/graphql/types/reports/outbound-order-details-report.ts +3 -0
  45. package/server/graphql/types/reports/outbound-serial-number-report-list.ts +8 -0
  46. package/server/graphql/types/reports/outbound-serial-number-report.ts +19 -0
  47. package/server/migrations/1568858861188-SeedSetting.ts +5 -2
  48. package/things-factory.config.js +12 -0
  49. package/translations/en.json +26 -6
  50. package/translations/ko.json +21 -2
  51. package/translations/ms.json +21 -2
  52. package/translations/zh.json +25 -6
@@ -7,6 +7,7 @@ import '../components/worksheet-information-popup'
7
7
  import './unloaded-inventories-popup'
8
8
  import './undo-unload-popup'
9
9
  import './select-product-batch'
10
+ import './serial-number-list-popup'
10
11
 
11
12
  import gql from 'graphql-tag'
12
13
  import { css, html } from 'lit-element'
@@ -38,7 +39,9 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
38
39
  _isLooseItem: Boolean,
39
40
  _isQtyChecked: Boolean,
40
41
  _isRequiredCheckExpiry: Boolean,
42
+ _isRequireSerialNumberScanningInbound: Boolean,
41
43
  _orderNo: String,
44
+ _orderId: String,
42
45
  _palletId: String,
43
46
  _reusablePallet: Object,
44
47
  _scanning: Boolean,
@@ -95,6 +98,10 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
95
98
  return this.shadowRoot.querySelector('barcode-scanable-input[name=cartonId]').shadowRoot.querySelector('input')
96
99
  }
97
100
 
101
+ get serialNumberInput() {
102
+ return this.shadowRoot.querySelector('barcode-scanable-input[name=serialNumber]').shadowRoot.querySelector('input')
103
+ }
104
+
98
105
  get completable() {
99
106
  let completable = false
100
107
  const orderProductWithIssues = this.orderProductData.records.filter(orderProduct => !orderProduct.validity)
@@ -124,6 +131,14 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
124
131
  })
125
132
  }
126
133
 
134
+ if (this._selectedOrderProduct && this._isRequireSerialNumberScanningInbound) {
135
+ actions.push({
136
+ title: i18next.t('button.serial_number'),
137
+ action: this._openSerialNumberList.bind(this),
138
+ ...CommonButtonStyles.activate
139
+ })
140
+ }
141
+
127
142
  if (this._selectedOrderProduct && !this._selectedOrderProduct.validity) {
128
143
  actions.push({
129
144
  title: i18next.t('button.issue'),
@@ -259,7 +274,7 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
259
274
  <barcode-scanable-input name="productBarcode" without-enter custom-input></barcode-scanable-input>
260
275
  `
261
276
  : ''}
262
- ${this._enableInputQty
277
+ ${this._enableInputQty && !this._isRequireSerialNumberScanningInbound
263
278
  ? html`
264
279
  <label>${i18next.t('label.actual_qty')}</label>
265
280
  <input name="qty" type="number" min="1" />
@@ -272,6 +287,12 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
272
287
  `
273
288
  : ''}
274
289
  </fieldset>
290
+ ${this._isRequireSerialNumberScanningInbound
291
+ ? html`<fieldset>
292
+ <label>${i18next.t('label.serial_number')}</label>
293
+ <barcode-scanable-input name="serialNumber" without-enter custom-input></barcode-scanable-input>
294
+ </fieldset>`
295
+ : ''}
275
296
  </form>
276
297
 
277
298
  <data-grist
@@ -307,6 +328,7 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
307
328
  this._isLooseItem = false
308
329
  this._isQtyChecked = false
309
330
  this._isRequiredCheckExpiry = false
331
+ this._isRequireSerialNumberScanningInbound = false
310
332
  this._orderNo = ''
311
333
  this._scanning = false
312
334
  this.refOrderType = AVAIL_ORDER_TYPES.ARRIVAL_NOTICE.value
@@ -341,6 +363,7 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
341
363
  if (record && record.batchId) {
342
364
  this._selectedOrderProduct = record
343
365
  this._isRequiredCheckExpiry = record.product?.isRequiredCheckExpiry
366
+ this._isRequireSerialNumberScanningInbound = record.product?.isRequireSerialNumberScanningInbound
344
367
  this._isQtyChecked = false
345
368
 
346
369
  this.inputForm.reset()
@@ -349,6 +372,9 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
349
372
  this.productBarcodeInput.readOnly = false
350
373
  this.productBarcodeInput.value = ''
351
374
  }
375
+ if (this.serialNumberInput) {
376
+ this.serialNumberInput.value = ''
377
+ }
352
378
  this.cartonInput.value = ''
353
379
  this._focusOnCartonInput()
354
380
  } else {
@@ -373,6 +399,7 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
373
399
  'actualPalletQty',
374
400
  'packQty',
375
401
  'actualPackQty',
402
+ 'manufactureDate',
376
403
  'issue'
377
404
  ]
378
405
  },
@@ -484,6 +511,13 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
484
511
  header: i18next.t('field.actual_pack_qty'),
485
512
  width: 100
486
513
  },
514
+ {
515
+ type: 'date',
516
+ name: 'manufactureDate',
517
+ label: true,
518
+ header: i18next.t('field.manufacture_date'),
519
+ width: 100
520
+ },
487
521
  {
488
522
  type: 'string',
489
523
  name: 'issue',
@@ -502,6 +536,10 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
502
536
  query unloadingWorksheet($arrivalNoticeNo: String!) {
503
537
  unloadingWorksheet(arrivalNoticeNo: $arrivalNoticeNo) {
504
538
  worksheetInfo {
539
+ arrivalNotice {
540
+ id
541
+ name
542
+ }
505
543
  bizplaceName
506
544
  partnerDomainId
507
545
  customerCompanyDomainId
@@ -537,6 +575,7 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
537
575
  name
538
576
  description
539
577
  isRequiredCheckExpiry
578
+ isRequireSerialNumberScanningInbound
540
579
  }
541
580
  name
542
581
  targetName
@@ -548,6 +587,7 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
548
587
  packQty
549
588
  actualPackQty
550
589
  issue
590
+ manufactureDate
551
591
  remark
552
592
  }
553
593
  }
@@ -562,6 +602,7 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
562
602
  const orderVasInfo = worksheetInfo.orderVas
563
603
 
564
604
  this._orderNo = orderNo
605
+ this._orderId = worksheetInfo.arrivalNotice.id
565
606
  this._bizplaceName = worksheetInfo.bizplaceName
566
607
  this._isLooseItem = worksheetInfo.looseItem
567
608
  this._worksheetInfo = worksheetInfo
@@ -585,20 +626,29 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
585
626
  }
586
627
  : { records: [] }
587
628
 
629
+ const worksheetDetailInfo = orderBy(
630
+ response.data.unloadingWorksheet.worksheetDetailInfos.map(worksheetDetailInfo => {
631
+ return {
632
+ ...worksheetDetailInfo,
633
+ validity:
634
+ worksheetDetailInfo.actualPackQty === worksheetDetailInfo.packQty &&
635
+ worksheetDetailInfo.actualPalletQty === worksheetDetailInfo.palletQty,
636
+ sku: worksheetDetailInfo.product.sku
637
+ }
638
+ }),
639
+ ['validity'],
640
+ ['asc']
641
+ )
642
+
588
643
  this.orderProductData = {
589
- records: orderBy(
590
- response.data.unloadingWorksheet.worksheetDetailInfos.map(worksheetDetailInfo => {
591
- return {
592
- ...worksheetDetailInfo,
593
- validity:
594
- worksheetDetailInfo.actualPackQty === worksheetDetailInfo.packQty &&
595
- worksheetDetailInfo.actualPalletQty === worksheetDetailInfo.palletQty,
596
- sku: worksheetDetailInfo.product.sku
597
- }
598
- }),
599
- ['validity'],
600
- ['asc']
601
- )
644
+ records: worksheetDetailInfo
645
+ }
646
+
647
+ if (!this._selectedOrderProduct) {
648
+ this._selectedOrderProduct = worksheetDetailInfo[0]
649
+ this._isRequiredCheckExpiry = worksheetDetailInfo[0].product?.isRequiredCheckExpiry
650
+ this._isRequireSerialNumberScanningInbound =
651
+ worksheetDetailInfo[0].product?.isRequireSerialNumberScanningInbound
602
652
  }
603
653
 
604
654
  const partnerDomainId = worksheetInfo.partnerDomainId
@@ -635,6 +685,7 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
635
685
  description
636
686
  sku
637
687
  isRequiredCheckExpiry
688
+ isRequireSerialNumberScanningInbound
638
689
  }
639
690
  inventory {
640
691
  id
@@ -707,12 +758,14 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
707
758
  cartonId
708
759
  qty
709
760
  expirationDate
761
+ manufactureDate
710
762
  status
711
763
  product {
712
764
  id
713
765
  name
714
766
  sku
715
767
  isRequiredCheckExpiry
768
+ isRequireSerialNumberScanningInbound
716
769
  }
717
770
  reusablePallet {
718
771
  id
@@ -749,21 +802,33 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
749
802
  if (this._selectedOrderProduct?.isRequiredCheckExpiry) this.expDateInput.value = null
750
803
 
751
804
  if (this._enableCartonLabel) {
752
- if (this._enableInputQty) {
753
- this.actualQtyInput.value = ''
754
- this.cartonInput.value = ''
755
- this._focusOnCartonInput()
805
+ if (this._isRequireSerialNumberScanningInbound) {
806
+ this.serialNumberInput.value = ''
807
+ this._focusOnSerialNumberInput()
808
+ } else {
809
+ if (this._enableInputQty) {
810
+ this.actualQtyInput.value = ''
811
+ this.cartonInput.value = ''
812
+ this._focusOnCartonInput()
813
+ }
756
814
  }
757
815
  } else {
758
- this.lotInput.value = ''
759
- if (this._enableInputQty) this.actualQtyInput.value = ''
760
- this._focusOnLotInput()
816
+ if (this._isRequireSerialNumberScanningInbound) {
817
+ this.serialNumberInput.value = ''
818
+ this._focusOnSerialNumberInput()
819
+ } else {
820
+ this.lotInput.value = ''
821
+ if (this._enableInputQty) this.actualQtyInput.value = ''
822
+ this._focusOnLotInput()
823
+ }
761
824
  }
762
825
 
763
826
  if (this._enableProductScanning) {
764
- this.productBarcodeInput.value = ''
765
- if (this.cartonInput?.value) {
766
- this._focusOnProductBarcodeInput()
827
+ if (!this._isRequireSerialNumberScanningInbound) {
828
+ this.productBarcodeInput.value = ''
829
+ if (this.cartonInput?.value) {
830
+ this._focusOnProductBarcodeInput()
831
+ }
767
832
  }
768
833
  }
769
834
  }
@@ -783,13 +848,17 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
783
848
  try {
784
849
  if (!this._enableCartonLabel) return this._unloadSelected()
785
850
  await this._validateUnloading()
786
- if (!(this._enableProductScanning && !this._enableInputQty)) return this._qtyUnload()
851
+
852
+ if (this._isRequireSerialNumberScanningInbound) {
853
+ return this._scanSerialNumberUnload()
854
+ } else {
855
+ if (!(this._enableProductScanning && !this._enableInputQty)) return this._qtyUnload()
856
+ }
787
857
  this._scanProductUnload()
788
858
  } catch (e) {
789
859
  this._showToast(e)
790
860
  }
791
861
  }
792
-
793
862
  async _scanProductUnload() {
794
863
  if (this._scanning) return this._showToast({ message: i18next.t('text.previous_scan_is_executing') })
795
864
  this._scanning = true
@@ -839,6 +908,62 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
839
908
  }
840
909
  }
841
910
 
911
+ async _scanSerialNumberUnload() {
912
+ if (this._scanning) {
913
+ return this._showToast({ message: i18next.t('text.previous_scan_is_executing') })
914
+ }
915
+ this._scanning = true
916
+
917
+ if (this.serialNumberInput.value == '') {
918
+ this._scanning = false
919
+ return this._showToast({ message: i18next.t('text.enter_serial_number') })
920
+ }
921
+
922
+ if (this._isRequiredCheckExpiry && this._expirationPeriod > 0) {
923
+ const answer = await this._checkExpiry()
924
+ if (answer && !answer.value) return (this._scanning = false)
925
+ }
926
+
927
+ try {
928
+ const response = await client.mutate({
929
+ mutation: gql`
930
+ mutation scanSerialNumberUnload(
931
+ $worksheetDetailName: String!
932
+ $serialNumber: String!
933
+ $inventory: InventoryPatch!
934
+ ) {
935
+ scanSerialNumberUnload(
936
+ worksheetDetailName: $worksheetDetailName
937
+ serialNumber: $serialNumber
938
+ inventory: $inventory
939
+ )
940
+ }
941
+ `,
942
+ variables: {
943
+ worksheetDetailName: this._selectedOrderProduct.name,
944
+ serialNumber: this.serialNumberInput.value.trim(),
945
+ inventory: {
946
+ palletId: this._enableCartonLabel ? null : this.lotInput.value.trim(),
947
+ cartonId: this._enableCartonLabel ? this.cartonInput.value.trim() : null,
948
+ expirationDate: this.expDateInput?.value ? this.expDateInput.value : null
949
+ }
950
+ }
951
+ })
952
+
953
+ if (!response.errors) {
954
+ await this._fetchProducts(this._orderNo)
955
+ }
956
+ } catch (e) {
957
+ // for cartonId + product scanning
958
+ // show custom toast for incorrect product barcodes
959
+ // full errors for everything else
960
+ if (!(e instanceof TypeError)) return this._showToast(e)
961
+ this._showToast({ message: i18next.t('text.incorrect_serial_number') })
962
+ } finally {
963
+ this._scanning = false
964
+ }
965
+ }
966
+
842
967
  async _checkExpiry() {
843
968
  let date = new Date()
844
969
  const acceptBefore = new Date(date.setDate(date.getDate() + this._expirationPeriod))
@@ -885,8 +1010,9 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
885
1010
  }
886
1011
  } catch (e) {
887
1012
  this._showToast(e)
1013
+ } finally {
1014
+ this._scanning = false
888
1015
  }
889
- this._scanning = false
890
1016
  }
891
1017
 
892
1018
  async fetchProductDetail(gtin, productId) {
@@ -904,6 +1030,7 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
904
1030
  name
905
1031
  sku
906
1032
  isRequiredCheckExpiry
1033
+ isRequireSerialNumberScanningInbound
907
1034
  expirationPeriod
908
1035
  }
909
1036
  }
@@ -943,9 +1070,14 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
943
1070
 
944
1071
  if (!foundOrderProducts?.length) {
945
1072
  if (!foundParentProducts?.length) {
946
- if (this._enableInputQty) {
1073
+ if (this._enableInputQty && !this._isRequireSerialNumberScanningInbound) {
947
1074
  if (this.actualQtyInput?.value) this.actualQtyInput.value = ''
948
1075
  }
1076
+
1077
+ if (this._isRequireSerialNumberScanningInbound) {
1078
+ if (this.serialNumberInput?.value) this.serialNumberInput.value = ''
1079
+ }
1080
+
949
1081
  this.productBarcodeInput.value = ''
950
1082
  this._focusOnProductBarcodeInput()
951
1083
  throw new Error(i18next.t('text.no_matching_product_found'))
@@ -953,6 +1085,7 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
953
1085
  }
954
1086
  this._expirationPeriod = product.expirationPeriod
955
1087
  this._isRequiredCheckExpiry = product.isRequiredCheckExpiry
1088
+ this._isRequireSerialNumberScanningInbound = product.isRequireSerialNumberScanningInbound
956
1089
 
957
1090
  if (this._selectedOrderProduct && this._selectedOrderProduct.product.sku !== product.sku)
958
1091
  this._selectedOrderProduct = null
@@ -975,10 +1108,15 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
975
1108
  .orderProducts="${orderProducts}"
976
1109
  @selected-batch="${async e => {
977
1110
  this._selectedOrderProduct = e.detail
978
- if (this._enableProductScanning && !this._enableInputQty) {
979
- await this._scanProductUnload()
1111
+
1112
+ if (e.detail.product.isRequireSerialNumberScanningInbound) {
1113
+ await this._scanSerialNumberUnload()
980
1114
  } else {
981
- this._focusOnActualQtyInput()
1115
+ if (this._enableProductScanning && !this._enableInputQty) {
1116
+ await this._scanProductUnload()
1117
+ } else {
1118
+ this._focusOnActualQtyInput()
1119
+ }
982
1120
  }
983
1121
  }}"
984
1122
  ></select-product-batch>
@@ -1007,16 +1145,23 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
1007
1145
  if (!this._enableProductScanning) {
1008
1146
  if (!this._selectedOrderProduct) throw new Error(i18next.t('text.target_does_not_selected'))
1009
1147
 
1010
- // 4. qty value existing
1011
- if (!parseInt(this.actualQtyInput.value)) {
1012
- this._focusOnActualQtyInput()
1013
- throw new Error(i18next.t('text.qty_is_empty'))
1014
- }
1148
+ if (this._isRequireSerialNumberScanningInbound) {
1149
+ if (!this.serialNumberInput.value) {
1150
+ this._focusOnSerialNumberInput()
1151
+ throw new Error(i18next.t('text.serial_number_is_empty'))
1152
+ }
1153
+ } else {
1154
+ // 4. qty value existing
1155
+ if (!parseInt(this.actualQtyInput.value)) {
1156
+ this._focusOnActualQtyInput()
1157
+ throw new Error(i18next.t('text.qty_is_empty'))
1158
+ }
1015
1159
 
1016
- // 5. qty value has to be positive
1017
- if (!(parseInt(this.actualQtyInput.value) > 0)) {
1018
- setTimeout(() => this.actualQtyInput.select(), 100)
1019
- throw new Error(i18next.t('text.qty_should_be_positive'))
1160
+ // 5. qty value has to be positive
1161
+ if (!(parseInt(this.actualQtyInput.value) > 0)) {
1162
+ setTimeout(() => this.actualQtyInput.select(), 100)
1163
+ throw new Error(i18next.t('text.qty_should_be_positive'))
1164
+ }
1020
1165
  }
1021
1166
 
1022
1167
  if (this._isRequiredCheckExpiry) {
@@ -1035,7 +1180,7 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
1035
1180
 
1036
1181
  await this._checkedScannedProduct()
1037
1182
 
1038
- if (this._enableInputQty) {
1183
+ if (this._enableInputQty && !this._isRequireSerialNumberScanningInbound) {
1039
1184
  if (!parseInt(this.actualQtyInput.value)) {
1040
1185
  this._focusOnActualQtyInput()
1041
1186
  throw new Error(i18next.t('text.enter_qty'))
@@ -1045,6 +1190,11 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
1045
1190
  setTimeout(() => this.actualQtyInput.select(), 100)
1046
1191
  throw new Error(i18next.t('text.qty_should_be_positive'))
1047
1192
  }
1193
+ } else if (this._isRequireSerialNumberScanningInbound) {
1194
+ if (!this.serialNumberInput.value) {
1195
+ this._focusOnSerialNumberInput()
1196
+ throw new Error(i18next.t('text.enter_serial_number'))
1197
+ }
1048
1198
  }
1049
1199
 
1050
1200
  if (this._isRequiredCheckExpiry) {
@@ -1249,6 +1399,8 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
1249
1399
  if (!this.lotInput.value) return
1250
1400
  await this._validateUnloading()
1251
1401
  await this._checkedLotScannedProduct()
1402
+
1403
+ if (this._isRequireSerialNumberScanningInbound) this._scanSerialNumberUnload()
1252
1404
  this._qtyUnload()
1253
1405
  } catch (e) {
1254
1406
  this._showToast(e)
@@ -1314,6 +1466,29 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
1314
1466
  )
1315
1467
  }
1316
1468
 
1469
+ _openSerialNumberList() {
1470
+ openPopup(
1471
+ html`
1472
+ <serial-number-list-popup
1473
+ .title="${i18next.t('title.serial_number_list')}"
1474
+ .orderType="${i18next.t('text.inbound')}"
1475
+ .orderId="${this._orderId}"
1476
+ .data="${this._selectedOrderProduct}"
1477
+ @close-serial-number-list="${async e => {
1478
+ await this._fetchProducts(this._orderNo)
1479
+ }}"
1480
+ ></serial-number-list-popup>
1481
+ `,
1482
+ {
1483
+ closable: false,
1484
+ backdrop: false,
1485
+ escapable: false,
1486
+ size: 'large',
1487
+ title: i18next.t('title.serial_number_list')
1488
+ }
1489
+ )
1490
+ }
1491
+
1317
1492
  async _normalPalletMode() {
1318
1493
  const result = await CustomAlert({
1319
1494
  title: i18next.t('title.are_you_sure'),
@@ -1404,6 +1579,10 @@ class UnloadProduct extends connect(store)(localize(i18next)(PageView)) {
1404
1579
  setTimeout(() => this.productBarcodeInput.focus(), 100)
1405
1580
  }
1406
1581
 
1582
+ _focusOnSerialNumberInput() {
1583
+ setTimeout(() => this.serialNumberInput.focus(), 100)
1584
+ }
1585
+
1407
1586
  orderTypeChangeHandler(e) {
1408
1587
  this.refOrderType = e.currentTarget.value
1409
1588
  this._clearView()
@@ -103,6 +103,13 @@ class UnloadedInventoriesPopup extends connect(store)(localize(i18next)(LitEleme
103
103
  label: true,
104
104
  width: 120
105
105
  },
106
+ {
107
+ type: 'date',
108
+ name: 'manufactureDate',
109
+ header: i18next.t('field.manufacture_date'),
110
+ label: true,
111
+ width: 120
112
+ },
106
113
  {
107
114
  type: 'object',
108
115
  name: 'reusablePallet',