@things-factory/operato-wms 3.7.2 → 3.7.7

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 (84) hide show
  1. package/client/pages/components/select-product-popup.js +5 -1
  2. package/client/pages/constants/order.js +10 -0
  3. package/client/pages/inbound/putaway-product.js +162 -139
  4. package/client/pages/inventory-check/inspecting-product.js +146 -80
  5. package/client/pages/manifest/create-loading-manifest.js +314 -0
  6. package/client/pages/manifest/dispatcher-verification-popup.js +86 -0
  7. package/client/pages/manifest/loading-manifest-detail.js +345 -0
  8. package/client/pages/manifest/loading-manifest-list.js +305 -0
  9. package/client/pages/order/arrival-notice/create-arrival-notice.js +8 -1
  10. package/client/pages/order/goods-received-note/received-note-list.js +138 -6
  11. package/client/pages/order/release-order/b2b/b2b-order-list.js +45 -5
  12. package/client/pages/order/release-order/b2b/b2b-order-requests.js +45 -5
  13. package/client/pages/order/release-order/b2c/b2c-order-requests.js +181 -21
  14. package/client/pages/order/release-order/bulk-print-packing-list.js +23 -0
  15. package/client/pages/order/release-order/create-release-order.js +25 -4
  16. package/client/pages/order/release-order/receive-release-order-request.js +27 -24
  17. package/client/pages/order/release-order/release-extra-product-popup.js +189 -56
  18. package/client/pages/order/release-order/release-order-detail.js +292 -71
  19. package/client/pages/order/reverse-kitting-order/reverse-kitting-order-detail.js +115 -50
  20. package/client/pages/order/reverse-kitting-order/reverse-kitting-order-list.js +1 -6
  21. package/client/pages/order/reverse-kitting-order/reverse-kitting-pallet-label-popup.js +239 -0
  22. package/client/pages/order/transport-order/delivery-order-list.js +99 -59
  23. package/client/pages/outbound/loading-product.js +4 -1
  24. package/client/pages/outbound/merged-outbound-worksheet.js +39 -1
  25. package/client/pages/outbound/packing-product.js +4 -1
  26. package/client/pages/outbound/packing-worksheet-list.js +39 -1
  27. package/client/pages/outbound/picking-product.js +622 -290
  28. package/client/pages/outbound/serial-number-popup.js +280 -0
  29. package/client/pages/outbound/worksheet-picking.js +28 -2
  30. package/client/pages/report/product-label-report.js +401 -0
  31. package/client/pages/support/inventory-comparison.js +296 -0
  32. package/client/pages/vas/print-product-label.js +298 -132
  33. package/client/pages/vas/reverse-kitting/execute-reverse-kitting.js +30 -12
  34. package/client/pages/vas/reverse-kitting/popup-combination-sets.js +75 -5
  35. package/client/pages/vas/reverse-kitting/popup-reverse-kitting-template.js +113 -18
  36. package/client/route.js +23 -0
  37. package/dist-server/graphql/resolvers/custom/elccl/elccl-inventory-history-summary-report.js +64 -54
  38. package/dist-server/graphql/resolvers/custom/elccl/elccl-inventory-history-summary-report.js.map +1 -1
  39. package/dist-server/graphql/resolvers/extra/add-release-good-products.js +34 -9
  40. package/dist-server/graphql/resolvers/extra/add-release-good-products.js.map +1 -1
  41. package/dist-server/graphql/resolvers/index.js +3 -1
  42. package/dist-server/graphql/resolvers/index.js.map +1 -1
  43. package/dist-server/graphql/resolvers/inventory-comparison/index.js +6 -0
  44. package/dist-server/graphql/resolvers/inventory-comparison/index.js.map +1 -0
  45. package/dist-server/graphql/resolvers/inventory-comparison/inventory-comparison-list.js +78 -0
  46. package/dist-server/graphql/resolvers/inventory-comparison/inventory-comparison-list.js.map +1 -0
  47. package/dist-server/graphql/resolvers/reports/index.js +2 -1
  48. package/dist-server/graphql/resolvers/reports/index.js.map +1 -1
  49. package/dist-server/graphql/resolvers/reports/product-label-report.js +56 -0
  50. package/dist-server/graphql/resolvers/reports/product-label-report.js.map +1 -0
  51. package/dist-server/graphql/types/index.js +5 -2
  52. package/dist-server/graphql/types/index.js.map +1 -1
  53. package/dist-server/graphql/types/inventory-comparison/index.js +13 -0
  54. package/dist-server/graphql/types/inventory-comparison/index.js.map +1 -0
  55. package/dist-server/graphql/types/inventory-comparison/inventory-comparison-list.js +14 -0
  56. package/dist-server/graphql/types/inventory-comparison/inventory-comparison-list.js.map +1 -0
  57. package/dist-server/graphql/types/inventory-comparison/inventory-comparison.js +18 -0
  58. package/dist-server/graphql/types/inventory-comparison/inventory-comparison.js.map +1 -0
  59. package/dist-server/graphql/types/reports/index.js +6 -1
  60. package/dist-server/graphql/types/reports/index.js.map +1 -1
  61. package/dist-server/graphql/types/reports/product-label-report-list.js +14 -0
  62. package/dist-server/graphql/types/reports/product-label-report-list.js.map +1 -0
  63. package/dist-server/graphql/types/reports/product-label-report.js +16 -0
  64. package/dist-server/graphql/types/reports/product-label-report.js.map +1 -0
  65. package/package.json +65 -65
  66. package/server/graphql/resolvers/custom/elccl/elccl-inventory-history-summary-report.ts +75 -65
  67. package/server/graphql/resolvers/extra/add-release-good-products.ts +57 -15
  68. package/server/graphql/resolvers/index.ts +3 -1
  69. package/server/graphql/resolvers/inventory-comparison/index.ts +5 -0
  70. package/server/graphql/resolvers/inventory-comparison/inventory-comparison-list.ts +99 -0
  71. package/server/graphql/resolvers/reports/index.ts +3 -1
  72. package/server/graphql/resolvers/reports/product-label-report.ts +56 -0
  73. package/server/graphql/types/index.ts +5 -2
  74. package/server/graphql/types/inventory-comparison/index.ts +11 -0
  75. package/server/graphql/types/inventory-comparison/inventory-comparison-list.ts +8 -0
  76. package/server/graphql/types/inventory-comparison/inventory-comparison.ts +12 -0
  77. package/server/graphql/types/reports/index.ts +6 -1
  78. package/server/graphql/types/reports/product-label-report-list.ts +8 -0
  79. package/server/graphql/types/reports/product-label-report.ts +10 -0
  80. package/things-factory.config.js +24 -0
  81. package/translations/en.json +64 -12
  82. package/translations/ko.json +50 -1
  83. package/translations/ms.json +51 -1
  84. package/translations/zh.json +50 -1
@@ -11,7 +11,7 @@ import { i18next, localize } from '@things-factory/i18n-base'
11
11
  import { openPopup } from '@things-factory/layout-base'
12
12
  import { client, CustomAlert, PageView, store, UPDATE_CONTEXT } from '@things-factory/shell'
13
13
  import { CommonButtonStyles } from '@things-factory/styles'
14
- import { gqlBuilder, isMobileDevice } from '@things-factory/utils'
14
+ import { isMobileDevice } from '@things-factory/utils'
15
15
 
16
16
  import { fetchLocationSortingRule } from '../../fetch-location-sorting-rule'
17
17
  import { fetchSettingRule } from '../../fetch-setting-value'
@@ -233,12 +233,7 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
233
233
  : html` <barcode-scanable-input name="palletId" custom-input></barcode-scanable-input>`}
234
234
 
235
235
  <label>${i18next.t('label.inspected_batch_no')}</label>
236
- <input
237
- name="inspectedBatchNo"
238
- .value="${this._hideCCColumnSetting
239
- ? this.selectedInventory?.inspectedBatchNo || ''
240
- : this.selectedInventory?.inspectedBatchNo || this.selectedInventory?.batchId || ''}"
241
- />
236
+ <input name="inspectedBatchNo" .value="${this.selectedInventory?.batchId || ''}" />
242
237
 
243
238
  <label>${i18next.t('label.inspected_qty')}</label>
244
239
  <input
@@ -434,6 +429,7 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
434
429
  { type: 'gutter', gutterName: 'sequence' },
435
430
  { type: 'boolean', name: 'completed', header: i18next.t('button.completed'), width: 80 },
436
431
  { type: 'string', name: 'palletId', header: i18next.t('label.lot_id'), width: 160 },
432
+ { type: 'string', name: 'batchId', header: i18next.t('label.batch_id'), width: 120 },
437
433
  {
438
434
  type: 'string',
439
435
  name: 'orderInventoryStatus',
@@ -900,19 +896,34 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
900
896
  inspectedQty = Number(inspectedQty)
901
897
  inspectedUomValue = Number(inspectedUomValue)
902
898
 
903
- const response = await client.query({
904
- query: gql`
905
- mutation {
906
- addExtraPallet(${gqlBuilder.buildArgs({
907
- cycleCountNo: this.cycleCountNo,
908
- palletId,
909
- inspectedBatchNo,
910
- inspectedQty,
911
- inspectedUomValue,
912
- locationName
913
- })})
899
+ const response = await client.mutate({
900
+ mutation: gql`
901
+ mutation addExtraPallet(
902
+ $cycleCountNo: String!
903
+ $palletId: String!
904
+ $inspectedBatchNo: String!
905
+ $inspectedQty: Int!
906
+ $inspectedUomValue: Float!
907
+ $locationName: String!
908
+ ) {
909
+ addExtraPallet(
910
+ cycleCountNo: $cycleCountNo
911
+ palletId: $palletId
912
+ inspectedBatchNo: $inspectedBatchNo
913
+ inspectedQty: $inspectedQty
914
+ inspectedUomValue: $inspectedUomValue
915
+ locationName: $locationName
916
+ )
914
917
  }
915
- `
918
+ `,
919
+ variables: {
920
+ cycleCountNo: this.cycleCountNo,
921
+ palletId,
922
+ inspectedBatchNo,
923
+ inspectedQty,
924
+ inspectedUomValue,
925
+ locationName
926
+ }
916
927
  })
917
928
 
918
929
  if (!response.errors) {
@@ -1003,10 +1014,8 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
1003
1014
 
1004
1015
  const response = await client.query({
1005
1016
  query: gql`
1006
- query {
1007
- orderInventories(${gqlBuilder.buildArgs({
1008
- filters
1009
- })}) {
1017
+ query orderInventories($filters: [Filter]) {
1018
+ orderInventories(filters: $filters) {
1010
1019
  items {
1011
1020
  id
1012
1021
  name
@@ -1014,7 +1023,8 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
1014
1023
  total
1015
1024
  }
1016
1025
  }
1017
- `
1026
+ `,
1027
+ variables: { filters }
1018
1028
  })
1019
1029
 
1020
1030
  if (!response.errors) {
@@ -1044,14 +1054,13 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
1044
1054
  return
1045
1055
  }
1046
1056
 
1047
- const response = await client.query({
1048
- query: gql`
1049
- mutation {
1050
- checkMissingPallet(${gqlBuilder.buildArgs({
1051
- worksheetDetailName: this.selectedInventory.worksheetDetailName
1052
- })})
1057
+ const response = await client.mutate({
1058
+ mutation: gql`
1059
+ mutation checkMissingPallet($worksheetDetailName: String!) {
1060
+ checkMissingPallet(worksheetDetailName: $worksheetDetailName)
1053
1061
  }
1054
- `
1062
+ `,
1063
+ variables: { worksheetDetailName: this.selectedInventory.worksheetDetailName }
1055
1064
  })
1056
1065
 
1057
1066
  if (!response.errors) {
@@ -1065,7 +1074,7 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
1065
1074
 
1066
1075
  async relocatePallet() {
1067
1076
  try {
1068
- this.checkInputFormValidity()
1077
+ await this.checkInputFormValidity()
1069
1078
 
1070
1079
  const result = await CustomAlert({
1071
1080
  title: i18next.t('title.are_you_sure'),
@@ -1078,25 +1087,35 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
1078
1087
  return
1079
1088
  }
1080
1089
 
1081
- let { inspectedBatchNo, inspectedQty, inspectedUomValue } = Object.fromEntries(
1090
+ const { inspectedBatchNo, inspectedQty, inspectedUomValue } = Object.fromEntries(
1082
1091
  new FormData(this.inputForm).entries()
1083
1092
  )
1084
- inspectedQty = Number(inspectedQty)
1085
- inspectedUomValue = Number(inspectedUomValue)
1086
- var locationName = this.locationInput.value
1087
1093
 
1088
- const response = await client.query({
1089
- query: gql`
1090
- mutation {
1091
- relocatePallet(${gqlBuilder.buildArgs({
1092
- worksheetDetailName: this.selectedInventory.worksheetDetailName,
1093
- inspectedBatchNo,
1094
- inspectedQty,
1095
- inspectedUomValue,
1096
- inspectedLocationName: locationName
1097
- })})
1094
+ const response = await client.mutate({
1095
+ mutation: gql`
1096
+ mutation relocatePallet(
1097
+ $worksheetDetailName: String!
1098
+ $inspectedBatchNo: String!
1099
+ $inspectedQty: Int!
1100
+ $inspectedUomValue: Float!
1101
+ $inspectedLocationName: String!
1102
+ ) {
1103
+ relocatePallet(
1104
+ worksheetDetailName: $worksheetDetailName
1105
+ inspectedBatchNo: $inspectedBatchNo
1106
+ inspectedQty: $inspectedQty
1107
+ inspectedUomValue: $inspectedUomValue
1108
+ inspectedLocationName: $inspectedLocationName
1109
+ )
1098
1110
  }
1099
- `
1111
+ `,
1112
+ variables: {
1113
+ worksheetDetailName: this.selectedInventory.worksheetDetailName,
1114
+ inspectedBatchNo,
1115
+ inspectedQty: Number(inspectedQty),
1116
+ inspectedUomValue: Number(inspectedUomValue),
1117
+ inspectedLocationName: this.locationInput.value
1118
+ }
1100
1119
  })
1101
1120
 
1102
1121
  if (!response.errors) {
@@ -1119,24 +1138,34 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
1119
1138
  inspectedQty = Number(inspectedQty)
1120
1139
  inspectedUomValue = Number(inspectedUomValue)
1121
1140
 
1122
- const response = await client.query({
1123
- query: gql`
1124
- mutation {
1125
- inspecting(${gqlBuilder.buildArgs({
1126
- worksheetDetailName: this.selectedInventory.worksheetDetailName,
1127
- inspectedBatchNo,
1128
- inspectedQty,
1129
- inspectedUomValue
1130
- })})
1141
+ const response = await client.mutate({
1142
+ mutation: gql`
1143
+ mutation inspecting(
1144
+ $worksheetDetailName: String!
1145
+ $inspectedBatchNo: String!
1146
+ $inspectedQty: Int!
1147
+ $inspectedUomValue: Float!
1148
+ ) {
1149
+ inspecting(
1150
+ worksheetDetailName: $worksheetDetailName
1151
+ inspectedBatchNo: $inspectedBatchNo
1152
+ inspectedQty: $inspectedQty
1153
+ inspectedUomValue: $inspectedUomValue
1154
+ )
1131
1155
  }
1132
- `
1156
+ `,
1157
+ variables: {
1158
+ worksheetDetailName: this.selectedInventory.worksheetDetailName,
1159
+ inspectedBatchNo,
1160
+ inspectedQty,
1161
+ inspectedUomValue
1162
+ }
1133
1163
  })
1134
1164
 
1135
1165
  if (!response.errors) {
1136
1166
  await this.fetchCycleCountWorksheet()
1137
1167
  this.renewInventoryGrist()
1138
- this.inspectedQtyInput.value = ''
1139
- this.locationInput.value = ''
1168
+ this.resetInput()
1140
1169
  }
1141
1170
  } catch (e) {
1142
1171
  this.showToast(e)
@@ -1145,14 +1174,13 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
1145
1174
 
1146
1175
  async undoInventoryCheck() {
1147
1176
  try {
1148
- const response = await client.query({
1149
- query: gql`
1150
- mutation {
1151
- undoInspection(${gqlBuilder.buildArgs({
1152
- worksheetDetailName: this.selectedInventory.worksheetDetailName
1153
- })})
1177
+ const response = await client.mutate({
1178
+ mutation: gql`
1179
+ mutation undoInspection($worksheetDetailName: String!) {
1180
+ undoInspection(worksheetDetailName: $worksheetDetailName)
1154
1181
  }
1155
- `
1182
+ `,
1183
+ variables: { worksheetDetailName: this.selectedInventory.worksheetDetailName }
1156
1184
  })
1157
1185
 
1158
1186
  if (!response.errors) {
@@ -1182,14 +1210,13 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
1182
1210
  })
1183
1211
 
1184
1212
  try {
1185
- const response = await client.query({
1186
- query: gql`
1187
- mutation {
1188
- completeInspection(${gqlBuilder.buildArgs({
1189
- inventoryCheckNo: this.cycleCountNo
1190
- })})
1213
+ const response = await client.mutate({
1214
+ mutation: gql`
1215
+ mutation completeInspection($inventoryCheckNo: String!) {
1216
+ completeInspection(inventoryCheckNo: $inventoryCheckNo)
1191
1217
  }
1192
- `
1218
+ `,
1219
+ variables: { inventoryCheckNo: this.cycleCountNo }
1193
1220
  })
1194
1221
 
1195
1222
  if (!response.errors) {
@@ -1213,6 +1240,12 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
1213
1240
  }
1214
1241
  }
1215
1242
 
1243
+ resetInput() {
1244
+ this.inspectedQtyInput.value = ''
1245
+ this.locationInput.value = ''
1246
+ this.inspectedUomValueInput.value = ''
1247
+ }
1248
+
1216
1249
  renewInventoryGrist() {
1217
1250
  this.selectedLocation = this.selectedLocation?.id
1218
1251
  ? this.formattedLocations.find(loc => loc.id === this.selectedLocation.id)
@@ -1226,13 +1259,11 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
1226
1259
  try {
1227
1260
  const response = await client.query({
1228
1261
  query: gql`
1229
- query {
1230
- checkInventoryOwner(${gqlBuilder.buildArgs({
1231
- palletId,
1232
- bizplaceName
1233
- })})
1262
+ query checkInventoryOwner($palletId: String!, $bizplaceName: String!) {
1263
+ checkInventoryOwner(palletId: $palletId, bizplaceName: $bizplaceName)
1234
1264
  }
1235
- `
1265
+ `,
1266
+ variables: { palletId, bizplaceName }
1236
1267
  })
1237
1268
 
1238
1269
  if (!response.errors) {
@@ -1243,7 +1274,37 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
1243
1274
  }
1244
1275
  }
1245
1276
 
1246
- checkInputFormValidity() {
1277
+ async validateLocation(scannedLocation) {
1278
+ try {
1279
+ const response = await client.query({
1280
+ query: gql`
1281
+ query locations($filters: [Filter]) {
1282
+ locations(filters: $filters) {
1283
+ items {
1284
+ id
1285
+ name
1286
+ }
1287
+ }
1288
+ }
1289
+ `,
1290
+ variables: { filters: [{ name: 'name', operator: 'eq', value: scannedLocation }] }
1291
+ })
1292
+
1293
+ if (!response.errors) {
1294
+ const locations = response.data.locations.items || []
1295
+
1296
+ if (!locations?.length) {
1297
+ return false
1298
+ } else {
1299
+ return true
1300
+ }
1301
+ }
1302
+ } catch (e) {
1303
+ this.showToast(e)
1304
+ }
1305
+ }
1306
+
1307
+ async checkInputFormValidity() {
1247
1308
  let { inspectedBatchNo, inspectedQty, inspectedUomValue, location } = Object.fromEntries(
1248
1309
  new FormData(this.inputForm).entries()
1249
1310
  )
@@ -1285,6 +1346,11 @@ class InspectingProduct extends connect(store)(localize(i18next)(PageView)) {
1285
1346
  if (!locationName) {
1286
1347
  this.selectOnInput(this.locationInput)
1287
1348
  throw new Error(i18next.t('text.invalid_x', { state: { x: i18next.t('label.location') } }))
1349
+ } else {
1350
+ const locationExist = await this.validateLocation(locationName)
1351
+ if (!locationExist) {
1352
+ throw new Error(i18next.t('text.invalid_x', { state: { x: i18next.t('label.location') } }))
1353
+ }
1288
1354
  }
1289
1355
  }
1290
1356
 
@@ -0,0 +1,314 @@
1
+ import '@things-factory/grist-ui'
2
+ import '@things-factory/barcode-ui'
3
+
4
+ import gql from 'graphql-tag'
5
+ import { css, html } from 'lit-element'
6
+
7
+ import { MultiColumnFormStyles } from '@things-factory/form-ui'
8
+ import { i18next, localize } from '@things-factory/i18n-base'
9
+ import { client, navigate, PageView } from '@things-factory/shell'
10
+ import { CommonButtonStyles } from '@things-factory/styles'
11
+ import { isMobileDevice } from '@things-factory/utils'
12
+
13
+ class CreateLoadingManifest extends localize(i18next)(PageView) {
14
+ static get styles() {
15
+ return [
16
+ MultiColumnFormStyles,
17
+ css`
18
+ :host {
19
+ display: flex;
20
+ flex-direction: column;
21
+ overflow-x: auto;
22
+ }
23
+ .container {
24
+ flex: 1;
25
+ display: flex;
26
+ overflow-y: auto;
27
+ min-height: 50vh;
28
+ }
29
+ .grist {
30
+ background-color: var(--main-section-background-color);
31
+ display: flex;
32
+ flex-direction: column;
33
+ flex: 1;
34
+ overflow-y: auto;
35
+ }
36
+ data-grist {
37
+ overflow-y: hidden;
38
+ flex: 1;
39
+ }
40
+ h2 {
41
+ padding: var(--subtitle-padding);
42
+ font: var(--subtitle-font);
43
+ color: var(--subtitle-text-color);
44
+ border-bottom: var(--subtitle-border-bottom);
45
+ }
46
+ .grist h2 {
47
+ margin: var(--grist-title-margin);
48
+ border: var(--grist-title-border);
49
+ font: var(--grist-title-font);
50
+ color: var(--secondary-color);
51
+ }
52
+
53
+ .grist h2 mwc-icon {
54
+ vertical-align: middle;
55
+ margin: var(--grist-title-icon-margin);
56
+ font-size: var(--grist-title-icon-size);
57
+ color: var(--grist-title-icon-color);
58
+ }
59
+
60
+ h2 + data-grist {
61
+ padding-top: var(--grist-title-with-grid-padding);
62
+ }
63
+ `
64
+ ]
65
+ }
66
+
67
+ static get properties() {
68
+ return {
69
+ shippingData: Object,
70
+ shippingGristConfig: Object
71
+ }
72
+ }
73
+
74
+ get context() {
75
+ return {
76
+ title: i18next.t('title.manifest'),
77
+ actions: [
78
+ {
79
+ title: i18next.t('button.submit'),
80
+ action: this._generateLoadingManifest.bind(this),
81
+ ...CommonButtonStyles.submit
82
+ }
83
+ ]
84
+ }
85
+ }
86
+
87
+ render() {
88
+ return html`
89
+ <form name="manifest" class="multi-column-form" autocomplete="off">
90
+ <fieldset>
91
+ <legend>${i18next.t('title.create_loading_manifest')}</legend>
92
+ <label>${i18next.t('label.scan_tracking_no')}</label>
93
+ <barcode-scanable-input
94
+ name="trackingNo"
95
+ custom-input
96
+ @keypress="${e => {
97
+ if (e.keyCode === 13) {
98
+ e.preventDefault()
99
+ if (this.trackingNoInput.value) {
100
+ this._fetchManifestItems(this.trackingNoInput.value)
101
+ }
102
+ }
103
+ }}"
104
+ ></barcode-scanable-input>
105
+ </fieldset>
106
+ </form>
107
+
108
+ <div class="container">
109
+ <div class="grist">
110
+ <h2><mwc-icon>list_alt</mwc-icon>${i18next.t('title.manifest_items')}</h2>
111
+
112
+ <data-grist
113
+ .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
114
+ .config=${this.shippingGristConfig}
115
+ .data=${this.shippingData}
116
+ ></data-grist>
117
+ </div>
118
+ </div>
119
+ `
120
+ }
121
+
122
+ constructor() {
123
+ super()
124
+ this.shippingData = { records: [] }
125
+ }
126
+
127
+ get shippingGrist() {
128
+ return this.shadowRoot.querySelector('data-grist')
129
+ }
130
+
131
+ get manifestForm() {
132
+ return this.shadowRoot.querySelector('form[name=manifest]')
133
+ }
134
+
135
+ get trackingNoInput() {
136
+ return this.shadowRoot.querySelector('barcode-scanable-input[name=trackingNo]')?.shadowRoot.querySelector('input')
137
+ }
138
+
139
+ pageUpdated(changes, lifecycle, before) {
140
+ if (this.active) {
141
+ this._focusOnTrackingNoInput()
142
+ }
143
+ }
144
+
145
+ pageInitialized() {
146
+ this.shippingGristConfig = {
147
+ list: { fields: ['refNo', 'trackingNo', 'transporter'] },
148
+ pagination: { infinite: true },
149
+ columns: [
150
+ { type: 'gutter', gutterName: 'sequence' },
151
+ {
152
+ type: 'gutter',
153
+ gutterName: 'button',
154
+ icon: 'close',
155
+ handlers: {
156
+ click: (columns, data, column, record, rowIndex) => {
157
+ const newData = data.records.filter((_, idx) => idx !== rowIndex)
158
+ this.shippingData = { ...this.shippingData, records: newData }
159
+ this.shippingGrist.dirtyData.records = newData
160
+ }
161
+ }
162
+ },
163
+ {
164
+ type: 'string',
165
+ name: 'refNo',
166
+ label: true,
167
+ header: i18next.t('field.order_no'),
168
+ width: 200
169
+ },
170
+ {
171
+ type: 'string',
172
+ name: 'trackingNo',
173
+ label: true,
174
+ header: i18next.t('field.tracking_no'),
175
+ width: 200
176
+ },
177
+ {
178
+ type: 'string',
179
+ name: 'transporter',
180
+ label: true,
181
+ header: i18next.t('field.shipping_provider'),
182
+ width: 200
183
+ }
184
+ ]
185
+ }
186
+ }
187
+
188
+ async _fetchManifestItems() {
189
+ try {
190
+ this._validateTrackingNo()
191
+
192
+ const filters = [
193
+ { name: 'trackingNo', operator: 'eq', value: this.trackingNoInput.value.trim() },
194
+ { name: 'manifest_id', operator: 'is_null', value: '' },
195
+ { name: 'status', operator: 'in', value: ['PACKING', 'DONE'] }
196
+ ]
197
+ const response = await client.query({
198
+ query: gql`
199
+ query releaseGoods($filters: [Filter], $sortings: [Sorting]) {
200
+ releaseGoods(filters: $filters, sortings: $sortings) {
201
+ items {
202
+ id
203
+ name
204
+ trackingNo
205
+ refNo
206
+ transporter
207
+ }
208
+ }
209
+ }
210
+ `,
211
+ variables: { filters, sortings: [] }
212
+ })
213
+
214
+ if (!response.errors) {
215
+ const releaseGood = (response.data.releaseGoods.items || []).map(record => {
216
+ return {
217
+ ...record,
218
+ orderNo: record?.refNo
219
+ }
220
+ })[0]
221
+
222
+ if (releaseGood && !this.shippingData.records.map(record => record.refNo).includes(releaseGood.refNo)) {
223
+ let manifestItems = this.shippingData.records || []
224
+ manifestItems.push({ ...releaseGood })
225
+ this.shippingData = { records: manifestItems }
226
+ } else {
227
+ this._showToast({ message: i18next.t('text.tracking_no_already_exist_in_manifest_list') })
228
+ }
229
+
230
+ this._clearTrackingNoInput()
231
+ }
232
+ } catch (e) {
233
+ this._showToast(e)
234
+ }
235
+ }
236
+
237
+ async _generateLoadingManifest() {
238
+ try {
239
+ this._validateManifestSubmission()
240
+
241
+ let manifest = {}
242
+ manifest.manifestItems = await this._getManifestItems()
243
+
244
+ const response = await client.mutate({
245
+ mutation: gql`
246
+ mutation generateManifest($manifest: NewManifest!) {
247
+ generateManifest(manifest: $manifest)
248
+ }
249
+ `,
250
+ variables: { manifest }
251
+ })
252
+
253
+ if (!response.errors) {
254
+ this._showToast({ message: i18next.t('text.manifest_has_been_generated') })
255
+ this._clearPage()
256
+ navigate('loading_manifest_list')
257
+ }
258
+ } catch (e) {
259
+ this._showToast(e)
260
+ }
261
+ }
262
+
263
+ _focusOnTrackingNoInput() {
264
+ setTimeout(() => this.trackingNoInput.focus(), 50)
265
+ }
266
+
267
+ _getManifestItems() {
268
+ return this.shippingGrist.data.records.map(record => {
269
+ return {
270
+ refNo: record.refNo,
271
+ trackingNo: record.trackingNo,
272
+ transporter: record.transporter
273
+ }
274
+ })
275
+ }
276
+
277
+ _validateManifestSubmission() {
278
+ if (!this.shippingGrist.data.records?.length) {
279
+ this._focusOnTrackingNoInput()
280
+ throw new Error(i18next.t('text.manifest_items_is_empty'))
281
+ }
282
+ }
283
+
284
+ _validateTrackingNo() {
285
+ if (!this.trackingNoInput?.value) {
286
+ this._focusOnTrackingNoInput()
287
+ throw new Error(i18next.t('text.tracking_no_is_empty'))
288
+ }
289
+ }
290
+
291
+ _clearTrackingNoInput() {
292
+ this.trackingNoInput.value = ''
293
+ this._focusOnTrackingNoInput()
294
+ }
295
+
296
+ _clearPage() {
297
+ this._clearTrackingNoInput()
298
+ this.shippingData = { ...this.shippingData, records: [] }
299
+ }
300
+
301
+ _showToast({ type, message }) {
302
+ document.dispatchEvent(
303
+ new CustomEvent('notify', {
304
+ detail: {
305
+ type,
306
+ message,
307
+ option: { timer: 1000 }
308
+ }
309
+ })
310
+ )
311
+ }
312
+ }
313
+
314
+ customElements.define('create-loading-manifest', CreateLoadingManifest)