@things-factory/operato-wms 3.7.14 → 3.8.2

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 (87) hide show
  1. package/client/pages/adjustment/transfer-inventory.js +390 -158
  2. package/client/pages/bulk-operation/bulk-operation.js +316 -0
  3. package/client/pages/bulk-operation/validate-ro-popup.js +445 -0
  4. package/client/pages/components/select-product-popup.js +1 -1
  5. package/client/pages/constants/inventory.js +1 -0
  6. package/client/pages/constants/location.js +33 -6
  7. package/client/pages/constants/worksheet.js +2 -2
  8. package/client/pages/inbound/inbound-worksheet.js +81 -15
  9. package/client/pages/inbound/putaway-product.js +61 -9
  10. package/client/pages/inbound/putaway-worksheet-generate-popup.js +29 -5
  11. package/client/pages/inbound/unload-product.js +80 -19
  12. package/client/pages/inbound/worksheet-putaway-return.js +14 -5
  13. package/client/pages/inbound/worksheet-putaway.js +13 -8
  14. package/client/pages/inbound/worksheet-unloading-return.js +14 -5
  15. package/client/pages/inventory/inventory-adjustment-approval.js +15 -23
  16. package/client/pages/inventory/inventory-adjustment.js +83 -79
  17. package/client/pages/inventory/inventory-by-product-detail.js +1 -1
  18. package/client/pages/inventory/inventory-by-product.js +1 -1
  19. package/client/pages/inventory/inventory-history-by-pallet.js +1 -1
  20. package/client/pages/inventory/inventory-history.js +2 -2
  21. package/client/pages/inventory/onhand-inventory.js +1 -2
  22. package/client/pages/inventory-check/create-cycle-count.js +1 -6
  23. package/client/pages/master/location-list.js +58 -17
  24. package/client/pages/order/arrival-notice/arrival-notice-detail.js +15 -8
  25. package/client/pages/order/arrival-notice/arrival-notice-list.js +87 -6
  26. package/client/pages/order/arrival-notice/arrival-notice-requests.js +83 -6
  27. package/client/pages/order/arrival-notice/create-arrival-notice.js +23 -2
  28. package/client/pages/order/arrival-notice/duplicate-arrival-notice.js +290 -25
  29. package/client/pages/order/arrival-notice/edit-product-popup.js +36 -5
  30. package/client/pages/order/release-order/b2b/b2b-order-requests.js +7 -7
  31. package/client/pages/order/release-order/b2c/b2c-order-requests.js +65 -5
  32. package/client/pages/order/release-order/release-extra-product-popup.js +12 -4
  33. package/client/pages/order/release-order/release-order-detail.js +1 -1
  34. package/client/pages/order/return-order/create-return-order.js +1 -1
  35. package/client/pages/order/return-order/return-order-detail.js +6 -5
  36. package/client/pages/order/transport-order/delivery-order-list.js +4 -1
  37. package/client/pages/outbound/inventory-assign-popup.js +1 -1
  38. package/client/pages/outbound/merged-outbound-worksheet.js +9 -5
  39. package/client/pages/outbound/picking-product.js +202 -162
  40. package/client/pages/outbound/picking-replacement-popup.js +2 -2
  41. package/client/pages/outbound/single-outbound-worksheet.js +47 -1
  42. package/client/pages/outbound/worksheet-loading.js +14 -5
  43. package/client/pages/outbound/worksheet-picking.js +10 -5
  44. package/client/pages/report/custom-elccl/elccl-inventory-report.js +31 -30
  45. package/client/pages/report/custom-elccl/elccl-inventory-summary-report.js +23 -26
  46. package/client/pages/report/inventory-pallet-storage-report.js +11 -10
  47. package/client/pages/report/inventory-report.js +41 -43
  48. package/client/pages/report/inventory-summary-report.js +25 -28
  49. package/client/pages/vas/print-product-label.js +3 -1
  50. package/client/route.js +5 -0
  51. package/dist-server/graphql/resolvers/custom/elccl/elccl-inventory-history-report.js +1 -1
  52. package/dist-server/graphql/resolvers/custom/elccl/elccl-inventory-history-report.js.map +1 -1
  53. package/dist-server/graphql/resolvers/custom/elccl/elccl-inventory-history-summary-report.js +1 -1
  54. package/dist-server/graphql/resolvers/index.js +3 -1
  55. package/dist-server/graphql/resolvers/index.js.map +1 -1
  56. package/dist-server/graphql/resolvers/reports/product-label-report.js +1 -0
  57. package/dist-server/graphql/resolvers/reports/product-label-report.js.map +1 -1
  58. package/dist-server/graphql/resolvers/shipping-provider/index.js +6 -0
  59. package/dist-server/graphql/resolvers/shipping-provider/index.js.map +1 -0
  60. package/dist-server/graphql/resolvers/shipping-provider/shipping-providers.js +20 -0
  61. package/dist-server/graphql/resolvers/shipping-provider/shipping-providers.js.map +1 -0
  62. package/dist-server/graphql/types/custom/elccl/elccl-inventory-report.js +1 -1
  63. package/dist-server/graphql/types/index.js +5 -2
  64. package/dist-server/graphql/types/index.js.map +1 -1
  65. package/dist-server/graphql/types/shipping-provider/index.js +10 -0
  66. package/dist-server/graphql/types/shipping-provider/index.js.map +1 -0
  67. package/dist-server/graphql/types/shipping-provider/shipping-provider-list.js +13 -0
  68. package/dist-server/graphql/types/shipping-provider/shipping-provider-list.js.map +1 -0
  69. package/dist-server/graphql/types/shipping-provider/shipping-provider.js +13 -0
  70. package/dist-server/graphql/types/shipping-provider/shipping-provider.js.map +1 -0
  71. package/package.json +37 -37
  72. package/server/graphql/resolvers/custom/elccl/elccl-inventory-history-report.ts +4 -2
  73. package/server/graphql/resolvers/custom/elccl/elccl-inventory-history-summary-report.ts +1 -1
  74. package/server/graphql/resolvers/index.ts +3 -1
  75. package/server/graphql/resolvers/reports/product-label-report.ts +1 -0
  76. package/server/graphql/resolvers/shipping-provider/index.ts +5 -0
  77. package/server/graphql/resolvers/shipping-provider/shipping-providers.ts +20 -0
  78. package/server/graphql/types/custom/elccl/elccl-inventory-report.ts +1 -1
  79. package/server/graphql/types/index.ts +5 -2
  80. package/server/graphql/types/shipping-provider/index.ts +8 -0
  81. package/server/graphql/types/shipping-provider/shipping-provider-list.ts +7 -0
  82. package/server/graphql/types/shipping-provider/shipping-provider.ts +7 -0
  83. package/things-factory.config.js +6 -0
  84. package/translations/en.json +28 -0
  85. package/translations/ko.json +85 -36
  86. package/translations/ms.json +86 -37
  87. package/translations/zh.json +99 -51
@@ -9,18 +9,20 @@ import { isMobileDevice } from '@things-factory/utils'
9
9
  import gql from 'graphql-tag'
10
10
  import { css, html } from 'lit-element'
11
11
  import { connect } from 'pwa-helpers/connect-mixin.js'
12
- import { CARTON, PALLET } from '../constants'
12
+ import { CARTON, LOT } from '../constants'
13
13
  import '../inbound/select-location-popup'
14
14
 
15
- const INVENTORY_TYPES = { PALLET, CARTON }
15
+ const INVENTORY_TYPES = { LOT, CARTON }
16
16
  class TransferInventory extends connect(store)(localize(i18next)(PageView)) {
17
17
  static get properties() {
18
18
  return {
19
19
  _palletId: String,
20
20
  _cartonId: String,
21
+ _requireNewId: Boolean,
22
+ _selectedInventory: Object,
21
23
  refInventoryType: String,
22
- config: Object,
23
- data: Object
24
+ _data: Object,
25
+ _gristConfig: Object
24
26
  }
25
27
  }
26
28
 
@@ -32,14 +34,28 @@ class TransferInventory extends connect(store)(localize(i18next)(PageView)) {
32
34
  :host {
33
35
  display: flex;
34
36
  flex-direction: column;
35
- overflow: hidden;
37
+ overflow: auto;
36
38
  }
37
39
 
38
- data-grist {
40
+ .grist {
41
+ min-height: 180px;
42
+ background-color: var(--main-section-background-color);
43
+ display: flex;
44
+ flex: 1;
39
45
  overflow: auto;
46
+ }
47
+
48
+ data-grist {
40
49
  flex: 1;
41
50
  }
42
51
 
52
+ h2 {
53
+ padding: var(--subtitle-padding);
54
+ font: var(--subtitle-font);
55
+ color: var(--subtitle-text-color);
56
+ border-bottom: var(--subtitle-border-bottom);
57
+ }
58
+
43
59
  .grist h2 {
44
60
  margin: var(--grist-title-margin);
45
61
  border: var(--grist-title-border);
@@ -57,6 +73,50 @@ class TransferInventory extends connect(store)(localize(i18next)(PageView)) {
57
73
  h2 + data-grist {
58
74
  padding-top: var(--grist-title-with-grid-padding);
59
75
  }
76
+
77
+ .button-container {
78
+ grid-column: span 12 / auto;
79
+ text-align: center;
80
+ }
81
+
82
+ .button-container > button {
83
+ background-color: var(--button-background-color);
84
+ border: var(--button-border);
85
+ border-radius: var(--button-border-radius);
86
+ padding: var(--button-padding);
87
+ color: var(--button-color);
88
+ font: var(--button-font);
89
+ text-transform: var(--button-text-transform);
90
+ }
91
+
92
+ .input-section {
93
+ flex: 1;
94
+ display: flex;
95
+ }
96
+
97
+ .left-column {
98
+ flex: 1;
99
+ display: flex;
100
+ flex-direction: column;
101
+ }
102
+
103
+ .right-column {
104
+ flex: 1;
105
+ display: flex;
106
+ flex-direction: column;
107
+ }
108
+
109
+ .content-title {
110
+ font-size: var(--fontsize-medium) !important;
111
+ color: var(--title-text-color) !important;
112
+ }
113
+
114
+ .content {
115
+ font-size: 14px !important;
116
+ font-weight: bold !important;
117
+ color: var(--primary-color) !important;
118
+ margin-botton: 5px;
119
+ }
60
120
  `
61
121
  ]
62
122
  }
@@ -65,11 +125,13 @@ class TransferInventory extends connect(store)(localize(i18next)(PageView)) {
65
125
  var actions = []
66
126
 
67
127
  if (this._palletId || this._cartonId) {
68
- actions.push({
69
- title: i18next.t('button.transfer'),
70
- action: this._transferInventory.bind(this),
71
- ...CommonButtonStyles.transfer
72
- })
128
+ actions = [
129
+ ...actions,
130
+ {
131
+ title: i18next.t('button.done'),
132
+ action: this.done.bind(this)
133
+ }
134
+ ]
73
135
  }
74
136
 
75
137
  return {
@@ -87,22 +149,54 @@ class TransferInventory extends connect(store)(localize(i18next)(PageView)) {
87
149
  return this.shadowRoot.querySelector('form#input-form')
88
150
  }
89
151
 
152
+ get qtyInput() {
153
+ return this.shadowRoot.querySelector('input[name=qty]')
154
+ }
155
+
90
156
  get palletInput() {
91
- return this.shadowRoot.querySelector('barcode-scanable-input[name=palletId]').shadowRoot.querySelector('input')
157
+ return this.shadowRoot.querySelector('barcode-scanable-input[name=palletId]')?.shadowRoot.querySelector('input')
92
158
  }
93
159
 
94
160
  get cartonInput() {
95
- return this.shadowRoot.querySelector('barcode-scanable-input[name=cartonId]').shadowRoot.querySelector('input')
161
+ return this.shadowRoot.querySelector('barcode-scanable-input[name=cartonId]')?.shadowRoot.querySelector('input')
162
+ }
163
+
164
+ get newLotInput() {
165
+ return this.shadowRoot?.querySelector('barcode-scanable-input[name=newLotId]')?.shadowRoot.querySelector('input')
96
166
  }
97
167
 
98
- get fromLocationNameInput() {
99
- return this.shadowRoot.querySelector('input[name=fromLocationName]')
168
+ get newCartonInput() {
169
+ return this.shadowRoot?.querySelector('barcode-scanable-input[name=newCartonId]')?.shadowRoot.querySelector('input')
100
170
  }
101
171
 
172
+ // get fromLocationNameInput() {
173
+ // return this.shadowRoot.querySelector('input[name=fromLocationName]')
174
+ // }
175
+
102
176
  get toLocationNameInput() {
103
177
  return this.shadowRoot
104
178
  .querySelector('barcode-scanable-input[name=toLocationName]')
105
- .shadowRoot.querySelector('input')
179
+ ?.shadowRoot.querySelector('input')
180
+ }
181
+
182
+ focusOnPalletInput() {
183
+ setTimeout(() => this.palletInput.focus(), 100)
184
+ }
185
+
186
+ focusOnCartonInput() {
187
+ setTimeout(() => this.cartonInput.focus(), 100)
188
+ }
189
+
190
+ focusOnToLocationInput() {
191
+ setTimeout(() => this.toLocationNameInput.focus(), 100)
192
+ }
193
+
194
+ focusOnNewLotInput() {
195
+ if (this.newLotInput) setTimeout(() => this.newLotInput.focus(), 100)
196
+ }
197
+
198
+ focusOnNewCartonInput() {
199
+ if (this.newCartonInput) setTimeout(() => this.newCartonInput.focus(), 100)
106
200
  }
107
201
 
108
202
  render() {
@@ -126,9 +220,8 @@ class TransferInventory extends connect(store)(localize(i18next)(PageView)) {
126
220
  )}
127
221
  </select>
128
222
 
129
- ${this.refInventoryType === INVENTORY_TYPES.PALLET.value
223
+ ${this.refInventoryType === INVENTORY_TYPES.LOT.value
130
224
  ? html`
131
- <label>${i18next.t('label.lot_id')}</label>
132
225
  <barcode-scanable-input
133
226
  name="palletId"
134
227
  custom-input
@@ -137,107 +230,214 @@ class TransferInventory extends connect(store)(localize(i18next)(PageView)) {
137
230
  e.preventDefault()
138
231
  if (this.palletInput.value) {
139
232
  this._palletId = this.palletInput.value
140
- this._fetchInventory(this.palletInput.value)
233
+ this.fetchInventory(this.palletInput.value)
141
234
  }
142
235
  }
143
236
  }}"
144
237
  ></barcode-scanable-input>
145
238
  `
146
- : html` <label>${i18next.t('label.carton_id')}</label>
147
- <barcode-scanable-input
148
- name="cartonId"
149
- custom-input
150
- @keypress="${e => {
151
- if (e.keyCode === 13) {
152
- e.preventDefault()
153
- if (this.cartonInput.value) {
154
- this._cartonId = this.cartonInput.value
155
- this._fetchInventory(this.cartonInput.value)
156
- }
239
+ : html` <barcode-scanable-input
240
+ name="cartonId"
241
+ custom-input
242
+ @keypress="${e => {
243
+ if (e.keyCode === 13) {
244
+ e.preventDefault()
245
+ if (this.cartonInput.value) {
246
+ this._cartonId = this.cartonInput.value
247
+ this.fetchInventory(this.cartonInput.value)
157
248
  }
158
- }}"
159
- ></barcode-scanable-input>`}
160
- </fieldset>
161
- </form>
162
-
163
- <form id="input-form" class="multi-column-form">
164
- <fieldset>
165
- <label>${i18next.t('label.from_location')}</label>
166
- <input
167
- name="fromLocationName"
168
- @keypress="${e => {
169
- if (e.keyCode === 13) {
170
- e.preventDefault()
171
- if (this.fromLocationNameInput.value) {
172
- this._transferInventory()
173
- }
174
- }
175
- }}"
176
- readonly
177
- />
178
-
179
- <label>${i18next.t('label.to_location')}</label>
180
- <barcode-scanable-input
181
- name="toLocationName"
182
- custom-input
183
- @keypress="${e => {
184
- if (e.keyCode === 13) {
185
- e.preventDefault()
186
- if (this.toLocationNameInput.value) {
187
- this._transferInventory()
188
- }
189
- }
190
- }}"
191
- ></barcode-scanable-input>
249
+ }
250
+ }}"
251
+ ></barcode-scanable-input>`}
192
252
  </fieldset>
193
253
  </form>
194
254
 
195
255
  <div class="grist">
196
- <h2><mwc-icon>list_alt</mwc-icon>${i18next.t('title.inventory')}</h2>
197
- <data-grist .mode=${isMobileDevice() ? 'LIST' : 'GRID'} .config=${this.config} .data=${this.data}></data-grist>
256
+ <data-grist
257
+ .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
258
+ .config=${this._gristConfig}
259
+ .data=${this._data}
260
+ ></data-grist>
198
261
  </div>
199
- `
200
- }
201
262
 
202
- constructor() {
203
- super()
204
- this._palletId = ''
205
- this._cartonId = ''
206
- this.refInventoryType = INVENTORY_TYPES.PALLET.value
263
+ <div class="input-section">
264
+ <div class="left-column">
265
+ <div class="single-column-form">
266
+ <fieldset>
267
+ <label class="content-title">${i18next.t('label.lot_id')}</label>
268
+ <label class="content">${this?._selectedInventory?.palletId || '-'}</label>
269
+
270
+ <label class="content-title">${i18next.t('label.from_location')}</label>
271
+ <label class="content">${this?._selectedInventory?.location?.name || '-'}</label>
272
+
273
+ <label class="content-title">${i18next.t('label.product')}</label>
274
+ <label class="content"
275
+ >${this?._selectedInventory?.product
276
+ ? '(' + this._selectedInventory.product.sku + ') ' + this?._selectedInventory?.product?.name
277
+ : '-'}</label
278
+ >
279
+ <label class="content-title">${i18next.t('label.packing_type')}</label>
280
+ <label class="content">${this?._selectedInventory?.packingType || '-'}</label>
281
+
282
+ <label class="content-title">${i18next.t('label.qty')}</label>
283
+ <label class="content">${(this?._selectedInventory?.qty || 0).toString()}</label>
284
+
285
+ <label class="content-title">${i18next.t('label.reserve_qty')}</label>
286
+ <label class="content">${(this?._selectedInventory?.lockedQty || 0).toString()}</label>
287
+
288
+ <label class="content-title">${i18next.t('label.available_qty')}</label>
289
+ <label class="content">${(this?._selectedInventory?.availableQty || 0).toString()}</label>
290
+
291
+ <!-- <input name="fromLocationName" readonly /> -->
292
+ </fieldset>
293
+ </div>
294
+ </div>
295
+ <div class="right-column">
296
+ <form id="input-form" class="single-column-form">
297
+ <fieldset>
298
+ <label class="content-title">${i18next.t('label.transfer_qty')}</label>
299
+ <input
300
+ type="number"
301
+ name="qty"
302
+ min="0"
303
+ @change="${e => {
304
+ if (parseInt(this.qtyInput.value) < 0) {
305
+ this.qtyInput.value = 0
306
+ }
307
+ if (this._selectedInventory) {
308
+ if (this._selectedInventory.availableQty > parseInt(this.qtyInput.value)) {
309
+ this._requireNewId = true
310
+ } else {
311
+ if (parseInt(this.qtyInput.value) > this._selectedInventory.availableQty) {
312
+ this.qtyInput.value = this._selectedInventory.availableQty
313
+ }
314
+ this._requireNewId = false
315
+ }
316
+ }
317
+ }}"
318
+ @keypress="${e => {
319
+ if (e.keyCode === 13) {
320
+ e.preventDefault()
321
+ if (parseInt(this.qtyInput.value) < 0) {
322
+ this.qtyInput.value = 0
323
+ } else if (this.qtyInput.value && this.toLocationNameInput.value === '') {
324
+ this.focusOnToLocationInput()
325
+ }
326
+ }
327
+ }}"
328
+ />
329
+
330
+ <label class="content-title">${i18next.t('label.to_location')}</label>
331
+ <barcode-scanable-input
332
+ name="toLocationName"
333
+ custom-input
334
+ @keypress="${e => {
335
+ if (e.keyCode === 13) {
336
+ e.preventDefault()
337
+ if (this.toLocationNameInput.value) {
338
+ if (this.refInventoryType === INVENTORY_TYPES.LOT.value) {
339
+ if (this._requireNewId) {
340
+ this.focusOnNewLotInput()
341
+ } else {
342
+ this.transferInventory(e)
343
+ }
344
+ } else {
345
+ this.focusOnNewCartonInput()
346
+ }
347
+ // this.transferInventory(e)
348
+ }
349
+ }
350
+ }}"
351
+ ></barcode-scanable-input>
352
+
353
+ ${this.refInventoryType === INVENTORY_TYPES.LOT.value
354
+ ? this._requireNewId
355
+ ? html` <label class="content-title">${i18next.t('label.new_lot_id')}</label>
356
+ <barcode-scanable-input
357
+ name="newLotId"
358
+ custom-input
359
+ @keypress="${e => {
360
+ if (e.keyCode === 13) {
361
+ e.preventDefault()
362
+ this.transferInventory(e)
363
+ }
364
+ }}"
365
+ ></barcode-scanable-input>`
366
+ : ``
367
+ : html`
368
+ <label class="content-title">${i18next.t('label.carton_id')}</label>
369
+ <barcode-scanable-input
370
+ name="newCartonId"
371
+ custom-input
372
+ @keypress="${e => {
373
+ if (e.keyCode === 13) {
374
+ e.preventDefault()
375
+ this.transferInventory(e)
376
+ }
377
+ }}"
378
+ ></barcode-scanable-input>
379
+ `}
380
+
381
+ <div class="button-container">
382
+ <button @click=${this.transferInventory.bind(this)}>${i18next.t('button.transfer')}</button>
383
+ </div>
384
+ </fieldset>
385
+ </form>
386
+ </div>
387
+ </div>
388
+ `
207
389
  }
208
390
 
209
391
  pageInitialized() {
210
- this.config = {
211
- rows: { appendable: false },
212
- pagination: { infinite: true },
392
+ this.refInventoryType = INVENTORY_TYPES.LOT.value
393
+ this._gristConfig = {
213
394
  list: {
214
395
  fields: [
215
- 'batchId',
216
- 'palletId',
217
- 'cartonId',
218
396
  'sku',
219
397
  'product',
398
+ 'cartonId',
399
+ 'palletId',
400
+ 'location',
401
+ 'batchId',
220
402
  'packingType',
221
403
  'packingSize',
222
404
  'qty',
405
+ 'lockedQty',
406
+ 'availableQty',
223
407
  'expirationDate'
224
408
  ]
225
409
  },
410
+ pagination: { infinite: true },
411
+ rows: {
412
+ appendable: false,
413
+ handlers: {
414
+ click: async (columns, data, column, record, rowIndex) => {
415
+ try {
416
+ if (this.refInventoryType !== INVENTORY_TYPES.LOT.value) {
417
+ this._selectedInventory = record
418
+ }
419
+ } catch (ex) {
420
+ console.log(ex)
421
+ } finally {
422
+ }
423
+ }
424
+ }
425
+ },
226
426
  columns: [
227
427
  { type: 'gutter', gutterName: 'sequence' },
228
428
  {
229
429
  type: 'string',
230
- name: 'batchId',
430
+ name: 'sku',
231
431
  label: true,
232
- header: i18next.t('field.batch_id'),
432
+ header: i18next.t('field.sku'),
233
433
  width: 150
234
434
  },
235
435
  {
236
- type: 'string',
237
- name: 'palletId',
436
+ type: 'object',
437
+ name: 'product',
238
438
  label: true,
239
- header: i18next.t('field.lot_id'),
240
- width: 150
439
+ header: i18next.t('field.product'),
440
+ width: 200
241
441
  },
242
442
  {
243
443
  type: 'string',
@@ -248,30 +448,37 @@ class TransferInventory extends connect(store)(localize(i18next)(PageView)) {
248
448
  },
249
449
  {
250
450
  type: 'string',
251
- name: 'sku',
451
+ name: 'palletId',
252
452
  label: true,
253
- header: i18next.t('field.sku'),
453
+ header: i18next.t('field.lot_id'),
254
454
  width: 150
255
455
  },
256
456
  {
257
457
  type: 'object',
258
- name: 'product',
458
+ name: 'location',
259
459
  label: true,
260
- header: i18next.t('field.product'),
460
+ header: i18next.t('field.location'),
261
461
  width: 200
262
462
  },
463
+ {
464
+ type: 'string',
465
+ name: 'batchId',
466
+ label: true,
467
+ header: i18next.t('field.batch_id'),
468
+ width: 150
469
+ },
263
470
  {
264
471
  type: 'string',
265
472
  name: 'packingType',
266
473
  label: true,
267
- header: i18next.t('field.packing_type'),
474
+ header: i18next.t('field.packing'),
268
475
  width: 150
269
476
  },
270
477
  {
271
478
  type: 'number',
272
479
  name: 'packingSize',
273
480
  label: true,
274
- header: i18next.t('field.packing_size'),
481
+ header: i18next.t('field.size'),
275
482
  width: 80
276
483
  },
277
484
  {
@@ -281,6 +488,20 @@ class TransferInventory extends connect(store)(localize(i18next)(PageView)) {
281
488
  header: i18next.t('field.qty'),
282
489
  width: 60
283
490
  },
491
+ {
492
+ type: 'integer',
493
+ name: 'lockedQty',
494
+ label: true,
495
+ header: i18next.t('field.reserve_qty'),
496
+ width: 60
497
+ },
498
+ {
499
+ type: 'integer',
500
+ name: 'availableQty',
501
+ label: true,
502
+ header: i18next.t('field.available_qty'),
503
+ width: 60
504
+ },
284
505
  {
285
506
  type: 'date',
286
507
  name: 'expirationDate',
@@ -290,19 +511,23 @@ class TransferInventory extends connect(store)(localize(i18next)(PageView)) {
290
511
  }
291
512
  ]
292
513
  }
514
+
515
+ this.clearView()
293
516
  }
294
517
 
295
518
  inventoryTypeChangeHandler(currentType) {
519
+ this.clearView()
520
+
296
521
  this.refInventoryType = currentType
297
522
 
298
- if (this.refInventoryType === INVENTORY_TYPES.PALLET.value) this._focusOnPalletInput()
299
- else this._focusOnCartonInput()
523
+ if (this.refInventoryType === INVENTORY_TYPES.LOT.value) this.focusOnPalletInput()
524
+ else this.focusOnCartonInput()
300
525
  }
301
526
 
302
- async _fetchInventory(inventoryRefId) {
527
+ async fetchInventory(inventoryRefId) {
303
528
  try {
304
529
  let filters = []
305
- if (this.refInventoryType === INVENTORY_TYPES.PALLET.value) {
530
+ if (this.refInventoryType === INVENTORY_TYPES.LOT.value) {
306
531
  filters.push({
307
532
  name: 'palletId',
308
533
  operator: 'eq',
@@ -318,7 +543,7 @@ class TransferInventory extends connect(store)(localize(i18next)(PageView)) {
318
543
 
319
544
  const response = await client.query({
320
545
  query: gql`
321
- query inventories($filters: [Filter]) {
546
+ query inventories($filters: [Filter!]) {
322
547
  inventories(filters: $filters) {
323
548
  items {
324
549
  id
@@ -335,6 +560,7 @@ class TransferInventory extends connect(store)(localize(i18next)(PageView)) {
335
560
  description
336
561
  }
337
562
  qty
563
+ lockedQty
338
564
  location {
339
565
  id
340
566
  name
@@ -354,55 +580,41 @@ class TransferInventory extends connect(store)(localize(i18next)(PageView)) {
354
580
 
355
581
  if (!response.errors) {
356
582
  if (response.data.inventories.total == 0) {
357
- if (this.refInventoryType === INVENTORY_TYPES.PALLET.value) this._focusOnPalletInput()
358
- else this._focusOnCartonInput()
583
+ if (this.refInventoryType === INVENTORY_TYPES.LOT.value) this.focusOnPalletInput()
584
+ else this.focusOnCartonInput()
359
585
  throw new Error(i18next.t('text.wrong_lot_id'))
360
586
  }
361
587
 
362
- this.data = {
588
+ this._data = {
363
589
  records: response.data.inventories.items.map(record => {
364
590
  return {
365
591
  ...record,
366
- sku: record.product.sku
592
+ sku: record.product.sku,
593
+ availableQty: record.qty - (record.lockedQty > 0 ? record.lockedQty : 0)
367
594
  }
368
595
  })
369
596
  }
370
- const locations = [...new Set(this.data.records.map(record => record.location.name))]
371
- if (locations.length > 1) this._selectLocationPopup(this.data.records.map(record => record.location))
372
- else this.fromLocationNameInput.value = locations[0]
373
597
 
374
- this._focusOnToLocationInput()
598
+ if (this.refInventoryType === INVENTORY_TYPES.LOT.value) {
599
+ this._selectedInventory = this._data.records[0]
600
+ }
601
+
375
602
  this.updateContext()
376
603
  }
377
604
  } catch (e) {
378
- this._clearView()
379
- if (this.refInventoryType === INVENTORY_TYPES.PALLET.value) this._focusOnPalletInput()
380
- else this._focusOnCartonInput()
381
- this._showToast(e)
605
+ this.clearView()
606
+ if (this.refInventoryType === INVENTORY_TYPES.LOT.value) this.focusOnPalletInput()
607
+ else this.focusOnCartonInput()
608
+ this.showToast(e)
382
609
  }
383
610
  }
384
611
 
385
- _selectLocationPopup(locations) {
386
- openPopup(
387
- html`
388
- <select-location-popup
389
- .locations="${locations}"
390
- @location-selected="${e => {
391
- this.fromLocationNameInput.value = e.detail.location.name
392
- }}"
393
- ></select-location-popup>
394
- `,
395
- {
396
- backdrop: true,
397
- size: 'medium',
398
- title: i18next.t('title.select_location')
399
- }
400
- )
401
- }
612
+ async transferInventory(e) {
613
+ e.stopPropagation()
614
+ e.preventDefault()
402
615
 
403
- async _transferInventory() {
404
616
  try {
405
- this._validateLocation()
617
+ this._validate()
406
618
 
407
619
  const result = await CustomAlert({
408
620
  title: i18next.t('title.are_you_sure'),
@@ -415,80 +627,100 @@ class TransferInventory extends connect(store)(localize(i18next)(PageView)) {
415
627
  return
416
628
  }
417
629
 
630
+ let variables = {
631
+ originPalletId: this._selectedInventory.palletId,
632
+ palletId: this.refInventoryType === INVENTORY_TYPES.LOT.value ? this.newLotInput?.value : null,
633
+ cartonId: this.refInventoryType === INVENTORY_TYPES.CARTON.value ? this.newCartonInput?.value : null,
634
+ fromLocationName: this._selectedInventory.location.name,
635
+ toLocationName: this.toLocationNameInput.value,
636
+ qty: parseInt(this.qtyInput.value)
637
+ }
638
+
418
639
  const response = await client.mutate({
419
640
  mutation: gql`
420
641
  mutation inventoryTransfer(
642
+ $originPalletId: String!
421
643
  $palletId: String
422
644
  $cartonId: String
423
645
  $fromLocationName: String!
424
646
  $toLocationName: String!
647
+ $qty: Float!
425
648
  ) {
426
649
  inventoryTransfer(
650
+ originPalletId: $originPalletId
427
651
  palletId: $palletId
428
652
  cartonId: $cartonId
429
653
  fromLocationName: $fromLocationName
430
654
  toLocationName: $toLocationName
655
+ qty: $qty
431
656
  )
432
657
  }
433
658
  `,
434
- variables: {
435
- palletId: this.refInventoryType === INVENTORY_TYPES.PALLET.value ? this.palletInput.value : null,
436
- cartonId: this.refInventoryType === INVENTORY_TYPES.CARTON.value ? this.cartonInput.value : null,
437
- fromLocationName: this.fromLocationNameInput.value,
438
- toLocationName: this.toLocationNameInput.value
439
- }
659
+ variables
440
660
  })
441
661
 
442
662
  if (!response.errors) {
443
- this._showToast({ message: i18next.t('text.transfer_location_completed') })
444
- this._clearView()
445
- if (this.refInventoryType === INVENTORY_TYPES.PALLET) this._focusOnPalletInput()
446
- else this._focusOnCartonInput()
663
+ let id = this.refInventoryType === INVENTORY_TYPES.LOT.value ? this._palletId : this._cartonId
664
+ this.showToast({ message: i18next.t('text.transfer_location_completed') })
665
+ this.clearView()
666
+ this.fetchInventory(id)
447
667
  this.updateContext()
448
668
  }
449
669
  } catch (e) {
450
- this._showToast(e)
670
+ this.showToast(e)
451
671
  }
452
672
  }
453
673
 
454
- _validateLocation() {
674
+ _validate() {
675
+ if (!this._selectedInventory) {
676
+ throw new Error(i18next.t('text.please_select_an_inventory'))
677
+ }
678
+
679
+ if (!(this._selectedInventory.availableQty > 0)) {
680
+ throw new Error(i18next.t('text.not_enough_available_qty'))
681
+ }
682
+
683
+ if (!parseInt(this.qtyInput?.value || 0) > 0) {
684
+ throw new Error(i18next.t('text.please_enter_transfer_qty'))
685
+ }
686
+
455
687
  if (!this.toLocationNameInput.value) {
456
- this._focusOnToLocationInput()
688
+ this.focusOnToLocationInput()
457
689
  throw new Error(i18next.t('text.there_is_no_to_location'))
458
690
  }
459
691
 
460
- if (this.fromLocationNameInput.value == this.toLocationNameInput.value) {
692
+ if (this._selectedInventory?.location?.name == this.toLocationNameInput.value) {
461
693
  throw new Error(i18next.t('text.from_location_is_same_as_to_location'))
462
694
  }
463
- }
464
695
 
465
- _focusOnPalletInput() {
466
- setTimeout(() => this.palletInput.focus(), 100)
467
- }
468
-
469
- _focusOnCartonInput() {
470
- setTimeout(() => this.cartonInput.focus(), 100)
471
- }
472
-
473
- _focusOnToLocationInput() {
474
- setTimeout(() => this.toLocationNameInput.focus(), 100)
696
+ if (this.refInventoryType === INVENTORY_TYPES.CARTON.value && this?.cartonInput?.value.trim() == '') {
697
+ throw new Error(i18next.t('text.required_carton_id'))
698
+ }
475
699
  }
476
700
 
477
- _clearView() {
478
- this.inputForm.reset()
479
- this.data = { records: [] }
480
- this.toLocationNameInput.value = ''
481
- if (this.refInventoryType === INVENTORY_TYPES.PALLET.value) {
701
+ done() {
702
+ this.clearView()
703
+ if (this.refInventoryType === INVENTORY_TYPES.LOT.value) {
482
704
  this.palletInput.value = ''
483
705
  this._palletId = ''
484
706
  } else {
485
707
  this.cartonInput.value = ''
486
708
  this.cartonId = ''
487
709
  }
710
+ }
711
+
712
+ clearView() {
713
+ this.inputForm?.reset()
714
+ this._selectedInventory = null
715
+ this._requireNewId = false
716
+ this._data = { records: [] }
717
+ if (this?.toLocationNameInput) this.toLocationNameInput.value = ''
718
+ if (this?.newCartonInput) this.newCartonInput.value = ''
719
+ if (this?.newLotInput) this.newLotInput.value = ''
488
720
  this.updateContext()
489
721
  }
490
722
 
491
- _showToast({ type, message }) {
723
+ showToast({ type, message }) {
492
724
  document.dispatchEvent(
493
725
  new CustomEvent('notify', {
494
726
  detail: {