@things-factory/operato-wms 3.7.6 → 3.7.10

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 (27) 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/inventory-check/inspecting-product.js +9 -8
  4. package/client/pages/manifest/create-loading-manifest.js +314 -0
  5. package/client/pages/manifest/dispatcher-verification-popup.js +86 -0
  6. package/client/pages/manifest/loading-manifest-detail.js +345 -0
  7. package/client/pages/manifest/loading-manifest-list.js +305 -0
  8. package/client/pages/order/goods-received-note/received-note-list.js +138 -6
  9. package/client/pages/order/release-order/b2b/b2b-order-list.js +1 -1
  10. package/client/pages/order/release-order/b2b/b2b-order-requests.js +1 -1
  11. package/client/pages/order/release-order/b2c/b2c-order-requests.js +111 -14
  12. package/client/pages/order/reverse-kitting-order/reverse-kitting-order-detail.js +115 -50
  13. package/client/pages/order/reverse-kitting-order/reverse-kitting-order-list.js +1 -6
  14. package/client/pages/order/reverse-kitting-order/reverse-kitting-pallet-label-popup.js +239 -0
  15. package/client/pages/order/transport-order/delivery-order-list.js +47 -3
  16. package/client/pages/outbound/picking-product.js +200 -66
  17. package/client/pages/outbound/serial-number-popup.js +280 -0
  18. package/client/pages/vas/reverse-kitting/execute-reverse-kitting.js +32 -12
  19. package/client/pages/vas/reverse-kitting/popup-combination-sets.js +106 -10
  20. package/client/pages/vas/reverse-kitting/popup-reverse-kitting-template.js +130 -19
  21. package/client/route.js +12 -0
  22. package/package.json +10 -10
  23. package/things-factory.config.js +12 -0
  24. package/translations/en.json +42 -6
  25. package/translations/ko.json +35 -1
  26. package/translations/ms.json +36 -1
  27. package/translations/zh.json +35 -1
@@ -0,0 +1,280 @@
1
+ import '@things-factory/barcode-ui'
2
+ import '@things-factory/grist-ui'
3
+
4
+ import gql from 'graphql-tag'
5
+ import { css, html, LitElement } from 'lit-element'
6
+
7
+ import { MultiColumnFormStyles, SingleColumnFormStyles } from '@things-factory/form-ui'
8
+ import { i18next, localize } from '@things-factory/i18n-base'
9
+ import { client } from '@things-factory/shell'
10
+ import { isMobileDevice } from '@things-factory/utils'
11
+
12
+ class SerialNumberPopup extends localize(i18next)(LitElement) {
13
+ static get styles() {
14
+ return [
15
+ MultiColumnFormStyles,
16
+ SingleColumnFormStyles,
17
+ css`
18
+ :host {
19
+ padding: 10px;
20
+ display: flex;
21
+ flex-direction: column;
22
+ overflow-x: overlay;
23
+ background-color: var(--main-section-background-color);
24
+ }
25
+ .grist {
26
+ background-color: var(--main-section-background-color);
27
+ display: flex;
28
+ flex-direction: column;
29
+ flex: 1;
30
+ overflow-y: auto;
31
+ }
32
+ data-grist {
33
+ overflow-y: hidden;
34
+ flex: 1;
35
+ }
36
+ .button-container {
37
+ padding: 10px 0 12px 0;
38
+ text-align: center;
39
+ display: flex;
40
+ flex-direction: column;
41
+ }
42
+
43
+ @media (max-width: 460px) {
44
+ .single-column-form {
45
+ max-width: 100%;
46
+ }
47
+ .mobile-full-width {
48
+ grid-column: span 12 / auto;
49
+ }
50
+ }
51
+ `
52
+ ]
53
+ }
54
+
55
+ static get properties() {
56
+ return {
57
+ orderInventory: Object,
58
+ config: Object,
59
+ data: Object,
60
+ _currentSerialNumber: String
61
+ }
62
+ }
63
+
64
+ get selectedSerialInput() {
65
+ return this.shadowRoot.querySelector('input[name=selectedSerialNumber]')
66
+ }
67
+
68
+ get serialInput() {
69
+ return this.shadowRoot.querySelector('barcode-scanable-input[name=serialNumber]').shadowRoot.querySelector('input')
70
+ }
71
+
72
+ get dataGrist() {
73
+ return this.shadowRoot.querySelector('data-grist')
74
+ }
75
+
76
+ constructor() {
77
+ super()
78
+ this.clearView()
79
+ }
80
+
81
+ render() {
82
+ return html`
83
+ <form class="multi-column-form">
84
+ <fieldset>
85
+ <legend>${i18next.t('title.serial_number_list')}</legend>
86
+ </fieldset>
87
+ </form>
88
+
89
+ <div class="grist">
90
+ <data-grist
91
+ .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
92
+ .config=${this.config}
93
+ .data="${this.data}"
94
+ ></data-grist>
95
+ </div>
96
+
97
+ <form id="input-form" class="single-column-form">
98
+ <input
99
+ name="selectedSerialNumber"
100
+ placeholder="-- Selected Serial Number --"
101
+ disabled
102
+ readonly
103
+ class="mobile-full-width"
104
+ value="${this._currentSerialNumber}"
105
+ />
106
+ <barcode-scanable-input name="serialNumber" class="mobile-full-width" custom-input></barcode-scanable-input>
107
+
108
+ <mwc-button
109
+ name="setSerialNumber"
110
+ class="mobile-full-width"
111
+ raised
112
+ @click=${this.updateSerialNumber.bind(this)}
113
+ label="${i18next.t('button.update')}"
114
+ ></mwc-button>
115
+ </form>
116
+
117
+ <div class="button-container">
118
+ <mwc-button
119
+ danger
120
+ @click=${() => {
121
+ history.back()
122
+ }}
123
+ raised
124
+ label="${i18next.t('button.back')}"
125
+ ></mwc-button>
126
+ </div>
127
+ `
128
+ }
129
+
130
+ async firstUpdated() {
131
+ this.clearView()
132
+
133
+ this.config = {
134
+ rows: {
135
+ appendable: false,
136
+ classifier: (record, rowIndex) => {
137
+ return {
138
+ emphasized: record.completed == true
139
+ }
140
+ },
141
+ handlers: {
142
+ click: async (columns, data, column, record, rowIndex) => {
143
+ try {
144
+ this.dataGrist.showSpinner()
145
+ this._currentSerialNumber = record.serialNumber
146
+ // this.selectedSerialInput.value = record.serialNumber
147
+ } catch (ex) {
148
+ console.log(ex)
149
+ } finally {
150
+ this.dataGrist.hideSpinner()
151
+ }
152
+ }
153
+ }
154
+ },
155
+ pagination: { infinite: true },
156
+ list: {
157
+ fields: ['serialNumber']
158
+ },
159
+ columns: [
160
+ { type: 'gutter', gutterName: 'sequence' },
161
+ {
162
+ type: 'string',
163
+ name: 'serialNumber',
164
+ header: i18next.t('field.serial_number'),
165
+ width: 140
166
+ }
167
+ ]
168
+ }
169
+ await this.fetchOrderInventory()
170
+ console.log()
171
+
172
+ // await this.getPalletInfo(this.replacePalletId)
173
+ }
174
+
175
+ // async pageUpdated(changes, lifecycle) {
176
+ // if (this.active) {
177
+ // await this.fetchOrderInventory()
178
+ // console.log()
179
+ // }
180
+ // }
181
+
182
+ clearView() {
183
+ this.targetInventory = null
184
+ this.data = { records: [] }
185
+ this._currentSerialNumber = ''
186
+ if (this.serialNumber) this.serialInput.value = ''
187
+ }
188
+
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) {
197
+ id
198
+ name
199
+ serialNumber
200
+ }
201
+ }
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
+ })
212
+ }
213
+ }
214
+ }
215
+ } catch (error) {
216
+ throw error
217
+ } finally {
218
+ this.dataGrist.hideSpinner()
219
+ }
220
+ }
221
+
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)
233
+
234
+ const response = await client.mutate({
235
+ mutation: gql`
236
+ mutation updateOrderInventorySerialNumber($orderInventory: OrderInventoryPatch!) {
237
+ updateOrderInventorySerialNumber(orderInventory: $orderInventory) {
238
+ id
239
+ name
240
+ serialNumber
241
+ }
242
+ }
243
+ `,
244
+ variables: {
245
+ orderInventory
246
+ }
247
+ })
248
+
249
+ if (!response.errors) {
250
+ this._currentSerialNumber = ''
251
+ this.serialInput.value = ''
252
+
253
+ this.fetchOrderInventory()
254
+ }
255
+ }
256
+ } catch (e) {
257
+ this._showToast(e)
258
+ }
259
+ }
260
+
261
+ validate() {
262
+ // validate for previous picking execution (multiple picking scanning)
263
+ if (this.selectedSerialInput.value == '') throw new Error(i18next.t('text.no_serial_number_selected'))
264
+
265
+ if (this.serialInput.value == '') throw new Error(i18next.t('text.please_key_in_new_serial_number'))
266
+ }
267
+
268
+ _showToast({ type, message }) {
269
+ document.dispatchEvent(
270
+ new CustomEvent('notify', {
271
+ detail: {
272
+ type,
273
+ message
274
+ }
275
+ })
276
+ )
277
+ }
278
+ }
279
+
280
+ window.customElements.define('serial-number-popup', SerialNumberPopup)
@@ -72,9 +72,6 @@ class ExecuteReverseKitting extends connect(store)(localize(i18next)(PageView))
72
72
  ? html`<form class="multi-column-form" id="info-form">
73
73
  <fieldset>
74
74
  <legend>${`${i18next.t('title.order_no')}: ${this._orderNo}`}</legend>
75
-
76
- <!-- <label>${i18next.t('label.company')}</label>
77
- <input name="bizplaceName" readonly /> -->
78
75
  </fieldset>
79
76
  </form>
80
77
 
@@ -109,8 +106,11 @@ class ExecuteReverseKitting extends connect(store)(localize(i18next)(PageView))
109
106
 
110
107
  get completable() {
111
108
  let completable = false
112
- if (this.orderData.records.length > 0) {
113
- completable = this.orderData.records.every(item => item.completed)
109
+ const orderDataWithIssues = this.orderData.records.filter(orderReverseKitting => !orderReverseKitting.completed)
110
+ if (!orderDataWithIssues?.length) {
111
+ completable = this.orderData.records.every(record => record.completed)
112
+ } else {
113
+ completable = orderDataWithIssues.every(record => record.issue)
114
114
  }
115
115
 
116
116
  return completable
@@ -131,7 +131,7 @@ class ExecuteReverseKitting extends connect(store)(localize(i18next)(PageView))
131
131
  pageInitialized() {
132
132
  this.orderGristConfig = {
133
133
  pagination: { infinite: true },
134
- list: { fields: ['completed', 'batchId', 'palletId', 'product', 'qty'] },
134
+ list: { fields: ['completed', 'batchId', 'palletId', 'product', 'qty', 'issue'] },
135
135
  rows: {
136
136
  appendable: false,
137
137
  handlers: {
@@ -179,6 +179,13 @@ class ExecuteReverseKitting extends connect(store)(localize(i18next)(PageView))
179
179
  header: i18next.t('field.uom_value'),
180
180
  label: true,
181
181
  width: 60
182
+ },
183
+ {
184
+ type: 'string',
185
+ name: 'issue',
186
+ header: i18next.t('field.issue'),
187
+ label: true,
188
+ width: 200
182
189
  }
183
190
  ]
184
191
  }
@@ -236,6 +243,7 @@ class ExecuteReverseKitting extends connect(store)(localize(i18next)(PageView))
236
243
  otherTarget
237
244
  operationGuide
238
245
  status
246
+ issue
239
247
  description
240
248
  remark
241
249
  }
@@ -336,7 +344,6 @@ class ExecuteReverseKitting extends connect(store)(localize(i18next)(PageView))
336
344
 
337
345
  _clearView() {
338
346
  this.orderData = { records: [] }
339
- this.inputForm.reset()
340
347
  this._selectedParentInventory = null
341
348
  this.updateContext()
342
349
  }
@@ -346,11 +353,24 @@ class ExecuteReverseKitting extends connect(store)(localize(i18next)(PageView))
346
353
  }
347
354
 
348
355
  _openPopupCombinationSets(record) {
349
- openPopup(html` <popup-combination-sets .orderNo="${this._orderNo}" .data="${record}"></popup-combination-sets> `, {
350
- backdrop: true,
351
- size: 'large',
352
- title: record.palletId
353
- })
356
+ openPopup(
357
+ html`
358
+ <popup-combination-sets
359
+ .orderNo="${this._orderNo}"
360
+ .data="${record}"
361
+ @order-reverse-kitting-data="${e => {
362
+ this.fetchReverseKittingOrder(this._orderNo)
363
+ }}"
364
+ ></popup-combination-sets>
365
+ `,
366
+ {
367
+ backdrop: true,
368
+ escapable: false,
369
+ closable: false,
370
+ size: 'large',
371
+ title: record.palletId
372
+ }
373
+ )
354
374
  }
355
375
 
356
376
  _showToast({ type, message }) {
@@ -1,10 +1,13 @@
1
1
  import '../../vas/reverse-kitting/popup-reverse-kitting-template'
2
+ import '../../components/popup-note'
2
3
 
4
+ import gql from 'graphql-tag'
3
5
  import { css, html, LitElement } from 'lit-element'
4
6
 
5
7
  import { MultiColumnFormStyles } from '@things-factory/form-ui'
6
8
  import { i18next, localize } from '@things-factory/i18n-base'
7
9
  import { openPopup } from '@things-factory/layout-base'
10
+ import { client } from '@things-factory/shell'
8
11
  import { isMobileDevice } from '@things-factory/utils'
9
12
 
10
13
  class PopupCombinationSets extends localize(i18next)(LitElement) {
@@ -53,12 +56,15 @@ class PopupCombinationSets extends localize(i18next)(LitElement) {
53
56
  font-size: var(--grist-title-icon-size);
54
57
  color: var(--grist-title-icon-color);
55
58
  }
59
+ .grist {
60
+ display: flex;
61
+ flex-direction: column;
62
+ flex: 1;
63
+ overflow-y: auto;
64
+ }
56
65
  .button-container {
57
- padding: var(--button-container-padding);
58
- margin: var(--button-container-margin);
59
- text-align: var(--button-container-align);
60
- background-color: var(--button-container-background);
61
- height: var(--button-container-height);
66
+ padding: 10px 0 12px 0;
67
+ text-align: center;
62
68
  }
63
69
  `
64
70
  ]
@@ -129,11 +135,23 @@ class PopupCombinationSets extends localize(i18next)(LitElement) {
129
135
  ></data-grist>
130
136
  </div>`
131
137
  : ''}
138
+ ${this.data
139
+ ? html`<div class="button-container">
140
+ <mwc-button
141
+ raised
142
+ @click=${this._openIssueNote.bind(this)}
143
+ label="${i18next.t('button.issue')}"
144
+ ></mwc-button>
145
+ <mwc-button raised @click=${this._closePopup.bind(this)} label="${i18next.t('button.back')}"></mwc-button>
146
+ </div>`
147
+ : html`<div class="button-container">
148
+ <mwc-button raised @click=${this._closePopup.bind(this)} label="${i18next.t('button.back')}"></mwc-button>
149
+ </div>`}
132
150
  `
133
151
  }
134
152
 
135
153
  async fetchReverseKittingOrder() {
136
- if (!this._orderNo) return
154
+ if (!this.orderNo) return
137
155
  const response = await client.query({
138
156
  query: gql`
139
157
  query executingReverseKittingOrder($name: String!) {
@@ -190,15 +208,30 @@ class PopupCombinationSets extends localize(i18next)(LitElement) {
190
208
  }
191
209
  }
192
210
  `,
193
- variables: { name: this._orderNo }
211
+ variables: { name: this.orderNo }
194
212
  })
195
213
 
196
214
  if (!response.errors) {
197
215
  const reverseKittingOrder = response.data.executingReverseKittingOrder
198
216
  const orderReverseKittings = reverseKittingOrder.orderReverseKittings
199
217
 
200
- this.data = {
201
- records: orderReverseKittings.map(orderReverseKitting => {
218
+ // this.data = {
219
+ // records: orderReverseKittings.map(orderReverseKitting => {
220
+ // const inventory = orderReverseKitting.inventory
221
+ // return {
222
+ // ...orderReverseKitting,
223
+ // batchId: inventory.batchId,
224
+ // palletId: inventory.palletId,
225
+ // location: inventory.location,
226
+ // product: inventory.product
227
+ // }
228
+ // })
229
+ // }
230
+
231
+ const previousOrderReverseKittingName = this.data.name
232
+ const matchedOrderReverseKitting = orderReverseKittings
233
+ .filter(item => item.name === previousOrderReverseKittingName)
234
+ .map(orderReverseKitting => {
202
235
  const inventory = orderReverseKitting.inventory
203
236
  return {
204
237
  ...orderReverseKitting,
@@ -208,12 +241,38 @@ class PopupCombinationSets extends localize(i18next)(LitElement) {
208
241
  product: inventory.product
209
242
  }
210
243
  })
211
- }
244
+
245
+ this.data = { ...matchedOrderReverseKitting[0] }
212
246
 
213
247
  this.getProductCombination()
214
248
  }
215
249
  }
216
250
 
251
+ async updateReverseKittingIssue(orderReverseKitting, issue) {
252
+ try {
253
+ if (!issue) return
254
+ const response = await client.mutate({
255
+ mutation: gql`
256
+ mutation updateOrderReverseKitting($id: String!, $patch: OrderReverseKittingPatch!) {
257
+ updateOrderReverseKitting(id: $id, patch: $patch) {
258
+ id
259
+ name
260
+ }
261
+ }
262
+ `,
263
+ variables: { id: orderReverseKitting.id, patch: { issue } }
264
+ })
265
+
266
+ if (!response.errors) {
267
+ this._showToast({ message: i18next.t('text.issue_updated') })
268
+ this.dispatchEvent(new CustomEvent('order-reverse-kitting-data', { detail: this.data }))
269
+ history.back()
270
+ }
271
+ } catch (e) {
272
+ this._showToast(e)
273
+ }
274
+ }
275
+
217
276
  getProductCombination() {
218
277
  let operationGuide = JSON.parse(this.data.operationGuide)
219
278
  this.productCombinationSets = {
@@ -229,6 +288,25 @@ class PopupCombinationSets extends localize(i18next)(LitElement) {
229
288
  }
230
289
  }
231
290
 
291
+ _openIssueNote() {
292
+ openPopup(
293
+ html`
294
+ <popup-note
295
+ .title="${i18next.t('title.issue')}"
296
+ .value="${this.data.issue}"
297
+ @submit="${async e => {
298
+ await this.updateReverseKittingIssue(this.data, e.detail.value)
299
+ }}"
300
+ ></popup-note>
301
+ `,
302
+ {
303
+ backdrop: true,
304
+ size: 'medium',
305
+ title: i18next.t('title.issue')
306
+ }
307
+ )
308
+ }
309
+
232
310
  _openPopupReverseKittingTemplate(record) {
233
311
  openPopup(
234
312
  html`
@@ -242,11 +320,29 @@ class PopupCombinationSets extends localize(i18next)(LitElement) {
242
320
  `,
243
321
  {
244
322
  backdrop: true,
323
+ escapable: false,
324
+ closable: false,
245
325
  size: 'large',
246
326
  title: i18next.t('title.reverse_kitting')
247
327
  }
248
328
  )
249
329
  }
330
+
331
+ _closePopup() {
332
+ this.dispatchEvent(new CustomEvent('order-reverse-kitting-data', { detail: {} }))
333
+ history.back()
334
+ }
335
+
336
+ _showToast({ type, message }) {
337
+ document.dispatchEvent(
338
+ new CustomEvent('notify', {
339
+ detail: {
340
+ type,
341
+ message
342
+ }
343
+ })
344
+ )
345
+ }
250
346
  }
251
347
 
252
348
  window.customElements.define('popup-combination-sets', PopupCombinationSets)