@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
@@ -0,0 +1,342 @@
1
+ import '@things-factory/grist-ui'
2
+ import '@things-factory/barcode-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 { ScrollbarStyles } from '@things-factory/styles'
11
+ import { isMobileDevice } from '@things-factory/utils'
12
+
13
+ class SerialNumberListPopup extends localize(i18next)(LitElement) {
14
+ static get properties() {
15
+ return {
16
+ serialNumberConfig: Object,
17
+ serialNumberGrist: Object,
18
+ data: Object,
19
+ orderType: String,
20
+ orderId: String,
21
+ _inventoryInfo: String,
22
+ _currentSerialNumber: String,
23
+ _selectedInventoryItemId: Object
24
+ }
25
+ }
26
+
27
+ static get styles() {
28
+ return [
29
+ MultiColumnFormStyles,
30
+ SingleColumnFormStyles,
31
+ ScrollbarStyles,
32
+ css`
33
+ :host {
34
+ display: flex;
35
+ flex-direction: column;
36
+ overflow: hidden;
37
+ background-color: white;
38
+ }
39
+
40
+ .grist {
41
+ display: flex;
42
+ flex-direction: column;
43
+ flex: 1;
44
+ overflow-y: auto;
45
+ }
46
+ .grist-container {
47
+ overflow-y: hidden;
48
+ display: flex;
49
+ flex: 1;
50
+ padding: 10px;
51
+ }
52
+ data-grist {
53
+ overflow-y: hidden;
54
+ flex: 1;
55
+ }
56
+ h2 {
57
+ padding: var(--subtitle-padding);
58
+ font: var(--subtitle-font);
59
+ color: var(--subtitle-text-color);
60
+ border-bottom: var(--subtitle-border-bottom);
61
+ }
62
+ .grist h2 {
63
+ font: var(--grist-title-font);
64
+ }
65
+ .button-container {
66
+ padding: var(--button-container-padding);
67
+ margin: var(--button-container-margin);
68
+ text-align: var(--button-container-align);
69
+ background-color: var(--button-container-background);
70
+ height: var(--button-container-height);
71
+ }
72
+ `
73
+ ]
74
+ }
75
+
76
+ render() {
77
+ return html`
78
+ <form class="multi-column-form">
79
+ <fieldset>
80
+ <legend>${this.data.product.sku}</legend>
81
+ </fieldset>
82
+ </form>
83
+
84
+ <form id="inventory-info-form" class="single-column-form">
85
+ <fieldset>
86
+ <label
87
+ >${i18next.t('field.lot_id')} / ${i18next.t('field.carton_id')} / ${i18next.t('field.serial_number')}</label
88
+ >
89
+ <barcode-scanable-input
90
+ name="inventoryInfo"
91
+ custom-input
92
+ @keypress="${e => {
93
+ if (e.keyCode === 13) {
94
+ e.preventDefault()
95
+ this._inventoryInfo = this.inventoryInfoInput.value
96
+ this.serialNumberGrist.fetch()
97
+ }
98
+ }}"
99
+ ></barcode-scanable-input>
100
+ </fieldset>
101
+ </form>
102
+
103
+ <div class="grist-container">
104
+ <div class="grist">
105
+ <data-grist
106
+ id="serialNumberGrist"
107
+ .mode=${isMobileDevice() ? 'LIST' : 'GRID'}
108
+ .config=${this.serialNumberConfig}
109
+ .fetchHandler=${this.fetchInventoryItems.bind(this)}
110
+ ></data-grist>
111
+ </div>
112
+ </div>
113
+
114
+ <form id="input-form" class="single-column-form">
115
+ <input
116
+ name="selectedSerialNumber"
117
+ placeholder="-- Selected Serial Number --"
118
+ disabled
119
+ readonly
120
+ class="mobile-full-width"
121
+ value="${this._currentSerialNumber}"
122
+ />
123
+ <barcode-scanable-input name="serialNumber" class="mobile-full-width" custom-input></barcode-scanable-input>
124
+
125
+ <mwc-button
126
+ name="updateSerialNumber"
127
+ class="mobile-full-width"
128
+ @click=${async () => {
129
+ await this.updateInventoryItemSerialNumber()
130
+ }}
131
+ raised
132
+ label="${i18next.t('button.update')}"
133
+ ></mwc-button>
134
+ </form>
135
+
136
+ <div class="button-container">
137
+ <mwc-button
138
+ class="mobile-full-width"
139
+ danger
140
+ @click=${() => {
141
+ this.dispatchEvent(new CustomEvent('close-serial-number-list', {}))
142
+ history.back()
143
+ }}
144
+ raised
145
+ label="${i18next.t('button.back')}"
146
+ ></mwc-button>
147
+ </div>
148
+ `
149
+ }
150
+
151
+ get serialNumberGrist() {
152
+ return this.shadowRoot.querySelector('data-grist#serialNumberGrist')
153
+ }
154
+
155
+ get inventoryInfoInput() {
156
+ return this.shadowRoot.querySelector('barcode-scanable-input[name=inventoryInfo]').shadowRoot.querySelector('input')
157
+ }
158
+
159
+ get selectedSerialInput() {
160
+ return this.shadowRoot.querySelector('input[name=selectedSerialNumber]')
161
+ }
162
+
163
+ get serialInput() {
164
+ return this.shadowRoot.querySelector('barcode-scanable-input[name=serialNumber]').shadowRoot.querySelector('input')
165
+ }
166
+
167
+ firstUpdated() {
168
+ this.serialNumberConfig = {
169
+ pagination: { pages: [10, 20, 50, 100] },
170
+ rows: {
171
+ appendable: false,
172
+ handlers: {
173
+ click: async (columns, data, column, record, rowIndex) => {
174
+ try {
175
+ this.serialNumberGrist.showSpinner()
176
+ this._currentSerialNumber = record.serialNumber
177
+ this._selectedInventoryItemId = record.id
178
+ } catch (ex) {
179
+ console.log(ex)
180
+ } finally {
181
+ this.serialNumberGrist.hideSpinner()
182
+ }
183
+ }
184
+ }
185
+ },
186
+ columns: [
187
+ { type: 'gutter', gutterName: 'sequence' },
188
+ { type: 'object', name: 'inventory', hidden: true },
189
+ {
190
+ type: 'gutter',
191
+ gutterName: 'button',
192
+ icon: 'close',
193
+ handlers: {
194
+ click: (columns, data, column, record, rowIndex) => {
195
+ this.undoSerialNumberUnload(record.id)
196
+ }
197
+ }
198
+ },
199
+ {
200
+ type: 'string',
201
+ name: 'serialNumber',
202
+ header: i18next.t('field.serial_number'),
203
+ width: 150
204
+ },
205
+ {
206
+ type: 'string',
207
+ name: 'palletId',
208
+ header: i18next.t('field.lot_id'),
209
+ width: 180
210
+ },
211
+ {
212
+ type: 'string',
213
+ name: 'cartonId',
214
+ header: i18next.t('field.carton_id'),
215
+ width: 180
216
+ }
217
+ ]
218
+ }
219
+ }
220
+
221
+ async fetchInventoryItems({ page, limit, sorters = [{ name: 'serialNumber' }] }) {
222
+ let filters = [
223
+ { name: 'orderType', operator: 'eq', value: this.orderType },
224
+ { name: 'orderId', operator: 'eq', value: this.orderId },
225
+ { name: 'productId', operator: 'eq', value: this.data.product.id }
226
+ ]
227
+
228
+ if (this._inventoryInfo) filters.push({ name: 'inventory_info', operator: 'i_like', value: this._inventoryInfo })
229
+
230
+ const pagination = { page, limit }
231
+ const sortings = sorters
232
+
233
+ const response = await client.query({
234
+ query: gql`
235
+ query inventoryItemsByInventory($filters: [Filter!]!, $pagination: Pagination, $sortings: [Sorting!]!) {
236
+ inventoryItemsByInventory(filters: $filters, pagination: $pagination, sortings: $sortings) {
237
+ items {
238
+ id
239
+ name
240
+ status
241
+ serialNumber
242
+ inventory {
243
+ id
244
+ name
245
+ palletId
246
+ cartonId
247
+ }
248
+ product {
249
+ id
250
+ name
251
+ sku
252
+ }
253
+ }
254
+ total
255
+ }
256
+ }
257
+ `,
258
+ variables: { filters, pagination, sortings }
259
+ })
260
+
261
+ if (!response.errors) {
262
+ return {
263
+ total: response.data.inventoryItemsByInventory.total || 0,
264
+ records:
265
+ response.data.inventoryItemsByInventory.items.map(item => {
266
+ return {
267
+ ...item,
268
+ palletId: item.inventory.palletId,
269
+ cartonId: item.inventory.cartonId
270
+ }
271
+ }) || []
272
+ }
273
+ }
274
+ }
275
+
276
+ async undoSerialNumberUnload(id) {
277
+ try {
278
+ const response = await client.mutate({
279
+ mutation: gql`
280
+ mutation undoSerialNumberUnload($worksheetDetailName: String!, $inventoryItemId: String!) {
281
+ undoSerialNumberUnload(worksheetDetailName: $worksheetDetailName, inventoryItemId: $inventoryItemId)
282
+ }
283
+ `,
284
+ variables: {
285
+ worksheetDetailName: this.data.name,
286
+ inventoryItemId: id
287
+ }
288
+ })
289
+
290
+ if (!response.errors) {
291
+ this.serialNumberGrist.fetch()
292
+ }
293
+ } catch (e) {
294
+ this._showToast(e)
295
+ }
296
+ }
297
+
298
+ async updateInventoryItemSerialNumber() {
299
+ try {
300
+ this.validate()
301
+
302
+ const response = await client.mutate({
303
+ mutation: gql`
304
+ mutation updateInventoryItemSerialNumber($id: String!, $serialNumber: String!) {
305
+ updateInventoryItemSerialNumber(id: $id, serialNumber: $serialNumber)
306
+ }
307
+ `,
308
+ variables: {
309
+ id: this._selectedInventoryItemId,
310
+ serialNumber: this.serialInput.value
311
+ }
312
+ })
313
+
314
+ if (!response.errors) {
315
+ this.serialInput.value = ''
316
+ this.serialNumberGrist.fetch()
317
+ }
318
+ } catch (e) {
319
+ this._showToast(e)
320
+ }
321
+ }
322
+
323
+ validate() {
324
+ // validate for previous picking execution (multiple picking scanning)
325
+ if (this.selectedSerialInput.value == '') throw new Error(i18next.t('text.no_serial_number_selected'))
326
+
327
+ if (this.serialInput.value == '') throw new Error(i18next.t('text.please_key_in_new_serial_number'))
328
+ }
329
+
330
+ _showToast({ type, message }) {
331
+ document.dispatchEvent(
332
+ new CustomEvent('notify', {
333
+ detail: {
334
+ type,
335
+ message
336
+ }
337
+ })
338
+ )
339
+ }
340
+ }
341
+
342
+ window.customElements.define('serial-number-list-popup', SerialNumberListPopup)