@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
@@ -57,22 +57,33 @@ class SerialNumberPopup extends localize(i18next)(LitElement) {
57
57
  orderInventory: Object,
58
58
  config: Object,
59
59
  data: Object,
60
- _currentSerialNumber: String
60
+ orderId: String,
61
+ orderType: String,
62
+ _inventoryItems: Object,
63
+ _selectedSerialNumber: Object
61
64
  }
62
65
  }
63
66
 
64
- get selectedSerialInput() {
65
- return this.shadowRoot.querySelector('input[name=selectedSerialNumber]')
66
- }
67
-
68
67
  get serialInput() {
69
- return this.shadowRoot.querySelector('barcode-scanable-input[name=serialNumber]').shadowRoot.querySelector('input')
68
+ return this.shadowRoot
69
+ ?.querySelector('barcode-scanable-input[name=serialNumber]')
70
+ ?.shadowRoot.querySelector('input')
70
71
  }
71
72
 
72
73
  get dataGrist() {
73
74
  return this.shadowRoot.querySelector('data-grist')
74
75
  }
75
76
 
77
+ get infoForm() {
78
+ return this.shadowRoot.querySelector('form#info-form')
79
+ }
80
+
81
+ _focusOnSerialInput() {
82
+ if (this.serialInput) {
83
+ setTimeout(() => this.serialInput.focus(), 50)
84
+ }
85
+ }
86
+
76
87
  constructor() {
77
88
  super()
78
89
  this.clearView()
@@ -80,9 +91,18 @@ class SerialNumberPopup extends localize(i18next)(LitElement) {
80
91
 
81
92
  render() {
82
93
  return html`
83
- <form class="multi-column-form">
94
+ <form id="info-form" class="multi-column-form">
84
95
  <fieldset>
85
- <legend>${i18next.t('title.serial_number_list')}</legend>
96
+ <legend>${i18next.t('title.product_sku_x', { x: this?.data?.product.sku })}</legend>
97
+
98
+ <label>${i18next.t('label.carton_id')}</label>
99
+ <input name="cartonId" ${this?.data.cartonId} disabled />
100
+
101
+ <label>${i18next.t('label.lot_id')}</label>
102
+ <input name="palletId" ${this?.data.palletId} disabled />
103
+
104
+ <label>${i18next.t('label.location')}</label>
105
+ <input name="locationName" ${this?.data.locationName} disabled />
86
106
  </fieldset>
87
107
  </form>
88
108
 
@@ -90,19 +110,20 @@ class SerialNumberPopup extends localize(i18next)(LitElement) {
90
110
  <data-grist
91
111
  .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
92
112
  .config=${this.config}
93
- .data="${this.data}"
113
+ .data=${this._inventoryItems}
94
114
  ></data-grist>
95
115
  </div>
96
116
 
97
- <form id="input-form" class="single-column-form">
117
+ <form id="input-form" class="single-column-form" @keypress="${this.updateSerialNumber.bind(this)}">
98
118
  <input
99
119
  name="selectedSerialNumber"
100
120
  placeholder="-- Selected Serial Number --"
101
121
  disabled
102
122
  readonly
103
123
  class="mobile-full-width"
104
- value="${this._currentSerialNumber}"
124
+ value="${this._selectedSerialNumber.serialNumber}"
105
125
  />
126
+
106
127
  <barcode-scanable-input name="serialNumber" class="mobile-full-width" custom-input></barcode-scanable-input>
107
128
 
108
129
  <mwc-button
@@ -118,6 +139,7 @@ class SerialNumberPopup extends localize(i18next)(LitElement) {
118
139
  <mwc-button
119
140
  danger
120
141
  @click=${() => {
142
+ this.dispatchEvent(new CustomEvent('close-serial-number-popup', {}))
121
143
  history.back()
122
144
  }}
123
145
  raised
@@ -142,8 +164,11 @@ class SerialNumberPopup extends localize(i18next)(LitElement) {
142
164
  click: async (columns, data, column, record, rowIndex) => {
143
165
  try {
144
166
  this.dataGrist.showSpinner()
145
- this._currentSerialNumber = record.serialNumber
146
- // this.selectedSerialInput.value = record.serialNumber
167
+ if (data.records.length && record) {
168
+ this._selectedSerialNumber = record
169
+ delete this._selectedSerialNumber.__seq__
170
+ delete this._selectedSerialNumber.__origin__
171
+ }
147
172
  } catch (ex) {
148
173
  console.log(ex)
149
174
  } finally {
@@ -158,18 +183,31 @@ class SerialNumberPopup extends localize(i18next)(LitElement) {
158
183
  },
159
184
  columns: [
160
185
  { type: 'gutter', gutterName: 'sequence' },
186
+ {
187
+ type: 'gutter',
188
+ gutterName: 'button',
189
+ icon: 'close',
190
+ handlers: {
191
+ click: (columns, data, column, record, rowIndex) => {
192
+ try {
193
+ const newData = data.records.filter((_, idx) => idx !== rowIndex)
194
+ this._inventoryItems = { ...this._inventoryItems, records: newData }
195
+ this.undoSerialNumberPicking(record.id)
196
+ } catch (e) {}
197
+ }
198
+ }
199
+ },
161
200
  {
162
201
  type: 'string',
163
202
  name: 'serialNumber',
164
203
  header: i18next.t('field.serial_number'),
165
- width: 140
204
+ width: 150
166
205
  }
167
206
  ]
168
207
  }
169
- await this.fetchOrderInventory()
170
- console.log()
171
-
172
- // await this.getPalletInfo(this.replacePalletId)
208
+ if (this.data) this._fillUpForm(this.infoForm, this.data)
209
+ await this.fetchInventoryItems()
210
+ this._focusOnSerialInput()
173
211
  }
174
212
 
175
213
  // async pageUpdated(changes, lifecycle) {
@@ -180,61 +218,67 @@ class SerialNumberPopup extends localize(i18next)(LitElement) {
180
218
  // }
181
219
 
182
220
  clearView() {
183
- this.targetInventory = null
184
- this.data = { records: [] }
185
- this._currentSerialNumber = ''
186
- if (this.serialNumber) this.serialInput.value = ''
221
+ this._selectedSerialNumber = {}
222
+ if (this.serialInput) this.serialInput.value = ''
187
223
  }
188
224
 
189
- async fetchOrderInventory() {
190
- try {
191
- this.dataGrist.showSpinner()
192
- if (this?.orderInventory?.id) {
193
- const response = await client.query({
194
- query: gql`
195
- query orderInventory($id: String!) {
196
- orderInventory(id: $id) {
225
+ async fetchInventoryItems() {
226
+ let filters = [
227
+ { name: 'orderType', operator: 'eq', value: this.orderType },
228
+ { name: 'orderId', operator: 'eq', value: this.orderId },
229
+ { name: 'productId', operator: 'eq', value: this.data.product.id },
230
+ { name: 'inventory_info', operator: 'i_like', value: `%${this.data.palletId}%` }
231
+ ]
232
+
233
+ const pagination = { page: 1, limit: 9999999 }
234
+ const sortings = []
235
+
236
+ const response = await client.query({
237
+ query: gql`
238
+ query inventoryItemsByInventory($filters: [Filter!]!, $pagination: Pagination, $sortings: [Sorting!]!) {
239
+ inventoryItemsByInventory(filters: $filters, pagination: $pagination, sortings: $sortings) {
240
+ items {
241
+ id
242
+ name
243
+ status
244
+ serialNumber
245
+ outboundOrderId
246
+ inventory {
247
+ id
248
+ name
249
+ }
250
+ product {
197
251
  id
198
252
  name
199
- serialNumber
200
253
  }
201
254
  }
202
- `,
203
- variables: { id: this.orderInventory.id }
204
- })
205
-
206
- if (!response.errors) {
207
- this.orderInventory = response.data.orderInventory
208
- this.data = {
209
- records: (JSON.parse(response.data.orderInventory.serialNumber) || []).map(x => {
210
- return { serialNumber: x }
211
- })
255
+ total
212
256
  }
213
257
  }
214
- }
215
- } catch (error) {
216
- throw error
217
- } finally {
218
- this.dataGrist.hideSpinner()
258
+ `,
259
+ variables: { filters, pagination, sortings }
260
+ })
261
+
262
+ if (!response.errors) {
263
+ return (this._inventoryItems = {
264
+ records: response.data.inventoryItemsByInventory.items || []
265
+ })
219
266
  }
220
267
  }
221
268
 
222
- async updateSerialNumber() {
223
- try {
224
- this.validate()
225
-
226
- let orderInventory = this.orderInventory
227
- let serialNumber = JSON.parse(orderInventory.serialNumber)
228
- let index = serialNumber.indexOf(this.selectedSerialInput.value)
229
-
230
- if (index >= 0) {
231
- serialNumber.splice(index, 1, this.serialInput.value)
232
- orderInventory.serialNumber = JSON.stringify(serialNumber)
269
+ async updateSerialNumber(e) {
270
+ if (e.keyCode === 13 || e.type == 'click') {
271
+ e.preventDefault()
272
+ try {
273
+ this.validate()
233
274
 
234
275
  const response = await client.mutate({
235
276
  mutation: gql`
236
- mutation updateOrderInventorySerialNumber($orderInventory: OrderInventoryPatch!) {
237
- updateOrderInventorySerialNumber(orderInventory: $orderInventory) {
277
+ mutation replacePickedInventoryItem($selectedSerialNumber: InventoryItemPatch!, $newSerialNumber: String!) {
278
+ replacePickedInventoryItem(
279
+ selectedSerialNumber: $selectedSerialNumber
280
+ newSerialNumber: $newSerialNumber
281
+ ) {
238
282
  id
239
283
  name
240
284
  serialNumber
@@ -242,16 +286,38 @@ class SerialNumberPopup extends localize(i18next)(LitElement) {
242
286
  }
243
287
  `,
244
288
  variables: {
245
- orderInventory
289
+ selectedSerialNumber: this._selectedSerialNumber,
290
+ newSerialNumber: this.serialInput.value.trim()
246
291
  }
247
292
  })
248
293
 
249
294
  if (!response.errors) {
250
- this._currentSerialNumber = ''
251
- this.serialInput.value = ''
295
+ this.clearView()
296
+ await this.fetchInventoryItems()
297
+ this._focusOnSerialInput()
298
+ }
299
+ } catch (e) {
300
+ this._showToast(e)
301
+ }
302
+ }
303
+ }
252
304
 
253
- this.fetchOrderInventory()
305
+ async undoSerialNumberPicking(id) {
306
+ try {
307
+ const response = await client.mutate({
308
+ mutation: gql`
309
+ mutation undoSerialNumberPicking($worksheetDetailName: String!, $inventoryItemId: String!) {
310
+ undoSerialNumberPicking(worksheetDetailName: $worksheetDetailName, inventoryItemId: $inventoryItemId)
311
+ }
312
+ `,
313
+ variables: {
314
+ worksheetDetailName: this.data.name,
315
+ inventoryItemId: id
254
316
  }
317
+ })
318
+
319
+ if (!response.errors) {
320
+ this.dataGrist.fetch()
255
321
  }
256
322
  } catch (e) {
257
323
  this._showToast(e)
@@ -260,11 +326,31 @@ class SerialNumberPopup extends localize(i18next)(LitElement) {
260
326
 
261
327
  validate() {
262
328
  // validate for previous picking execution (multiple picking scanning)
263
- if (this.selectedSerialInput.value == '') throw new Error(i18next.t('text.no_serial_number_selected'))
329
+ let foundSerialNumber = this.dataGrist.data.records.filter(itm => itm.serialNumber == this.serialInput.value.trim())
330
+ if (foundSerialNumber.length > 0) {
331
+ throw new Error(i18next.t('text.serial_number_has_been_scanned'))
332
+ }
333
+
334
+ if (!this._selectedSerialNumber.id) throw new Error(i18next.t('text.no_serial_number_selected'))
264
335
 
265
336
  if (this.serialInput.value == '') throw new Error(i18next.t('text.please_key_in_new_serial_number'))
266
337
  }
267
338
 
339
+ _fillUpForm(form, data) {
340
+ for (let key in data) {
341
+ Array.from(form.querySelectorAll('input')).forEach(field => {
342
+ if (field.name === key) {
343
+ if (data[key] instanceof Object) {
344
+ const objectData = data[key]
345
+ field.value = `${objectData.name} ${objectData.description ? `(${objectData.description})` : ''}`
346
+ } else {
347
+ field.value = data[key]
348
+ }
349
+ }
350
+ })
351
+ }
352
+ }
353
+
268
354
  _showToast({ type, message }) {
269
355
  document.dispatchEvent(
270
356
  new CustomEvent('notify', {