@things-factory/operato-wms 4.3.769 → 4.3.770

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 (42) hide show
  1. package/client/pages/components/list-view/product-list-view.js +28 -3
  2. package/client/pages/components/mobile-condition-of-goods-listing.js +342 -0
  3. package/client/pages/components/unloading-worksheet-information-popup.js +299 -0
  4. package/client/pages/constants/order.js +7 -0
  5. package/client/pages/inbound/condition-of-goods-popup.js +646 -0
  6. package/client/pages/inbound/putaway/putaway-product.js +35 -6
  7. package/client/pages/inbound/unload-product-landing-page.js +282 -0
  8. package/client/pages/inbound/unload-product.js +707 -175
  9. package/client/pages/inbound/unloaded-inventories-popup.js +3 -0
  10. package/client/pages/inventory/inventory-adjustment-approval.js +28 -1
  11. package/client/pages/inventory/inventory-adjustment.js +31 -1
  12. package/client/pages/inventory/inventory-by-product-detail.js +15 -0
  13. package/client/pages/inventory/inventory-history.js +18 -0
  14. package/client/pages/inventory/onhand-inventory.js +14 -0
  15. package/client/pages/order/release-order/b2b/b2b-order-list.js +99 -0
  16. package/client/pages/order/release-order/packing-label-history-popup.js +378 -0
  17. package/client/pages/order/release-order/preview-print-packing-list.js +533 -0
  18. package/client/pages/order/release-order/print-quantity-popup.js +118 -0
  19. package/client/pages/outbound/loading-v2/loading-execution-base.js +29 -0
  20. package/client/pages/outbound/loading-v2/loading-execution.js +579 -2
  21. package/client/pages/outbound/loading-v2/loading-package-info-popup.js +182 -0
  22. package/client/pages/outbound/loading-v2/loading.js +18 -0
  23. package/client/pages/report/inbound-order-details-report.js +26 -1
  24. package/client/route.js +17 -0
  25. package/dist-server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.js +9 -1
  26. package/dist-server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.js.map +1 -1
  27. package/dist-server/graphql/resolvers/outbound/loading-worksheet-v2.js +11 -5
  28. package/dist-server/graphql/resolvers/outbound/loading-worksheet-v2.js.map +1 -1
  29. package/dist-server/graphql/resolvers/reports/inbound-order-details-report.js +2 -1
  30. package/dist-server/graphql/resolvers/reports/inbound-order-details-report.js.map +1 -1
  31. package/dist-server/graphql/types/reports/inbound-order-details-report.js +1 -0
  32. package/dist-server/graphql/types/reports/inbound-order-details-report.js.map +1 -1
  33. package/package.json +15 -15
  34. package/server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.ts +9 -1
  35. package/server/graphql/resolvers/outbound/loading-worksheet-v2.ts +13 -1
  36. package/server/graphql/resolvers/reports/inbound-order-details-report.ts +2 -1
  37. package/server/graphql/types/reports/inbound-order-details-report.ts +1 -0
  38. package/things-factory.config.js +8 -0
  39. package/translations/en.json +45 -1
  40. package/translations/ko.json +40 -0
  41. package/translations/ms.json +40 -0
  42. package/translations/zh.json +40 -0
@@ -29,6 +29,8 @@ class UnloadedInventoriesPopup extends connect(store)(localize(i18next)(LitEleme
29
29
  flex-direction: column;
30
30
  flex: 1;
31
31
  overflow-y: auto;
32
+ --grid-record-odd-background-color: var(--theme-white-color);
33
+ --data-list-background-color: var(--theme-white-color);
32
34
  }
33
35
  :host {
34
36
  padding: 10px;
@@ -36,6 +38,7 @@ class UnloadedInventoriesPopup extends connect(store)(localize(i18next)(LitEleme
36
38
  flex-direction: column;
37
39
  overflow-x: overlay;
38
40
  background-color: var(--main-section-background-color);
41
+ --data-list-label-text-transform: capitalize;
39
42
  }
40
43
  `
41
44
  ]
@@ -8,6 +8,7 @@ import { connect } from 'pwa-helpers/connect-mixin'
8
8
 
9
9
  import { getCodeByName } from '@things-factory/code-base'
10
10
  import { i18next, localize } from '@things-factory/i18n-base'
11
+ import { CONDITION_OF_GOODS } from '../constants'
11
12
  import { client, PageView, store, gqlContext } from '@things-factory/shell'
12
13
  import { CommonButtonStyles, ScrollbarStyles } from '@things-factory/styles'
13
14
  import { isMobileDevice } from '@things-factory/utils'
@@ -147,6 +148,7 @@ class InventoryAdjustmentApproval extends connect(store)(localize(i18next)(PageV
147
148
  { column: 'qty', name: 'Quantity' },
148
149
  { column: 'uom', name: 'Uom' },
149
150
  { column: 'uomValue', name: 'UomValue' },
151
+ { column: 'conditionOfGoods', name: 'Inventory Quality' },
150
152
  { column: 'expirationDate', name: 'Exp. Date' },
151
153
  { column: 'manufactureDate', name: 'Mfg. Date' },
152
154
  { column: 'unitCost', name: 'Unit Cost' },
@@ -198,10 +200,18 @@ class InventoryAdjustmentApproval extends connect(store)(localize(i18next)(PageV
198
200
  if (compareData == null) {
199
201
  this._compareColumn.map(item => {
200
202
  if (record[item.column]) {
203
+ let updateVal =
204
+ typeof record[item.column] === 'object' ? record[item.column].name : record[item.column]
205
+
206
+ // Translate conditionOfGoods value
207
+ if (item.column === 'conditionOfGoods' && updateVal) {
208
+ updateVal = this._getConditionOfGoodsLabel(updateVal)
209
+ }
210
+
201
211
  recordDiff.push({
202
212
  column: item.name,
203
213
  current: '[N/A]',
204
- update: typeof record[item.column] === 'object' ? record[item.column].name : record[item.column]
214
+ update: updateVal
205
215
  })
206
216
  }
207
217
  })
@@ -220,6 +230,16 @@ class InventoryAdjustmentApproval extends connect(store)(localize(i18next)(PageV
220
230
  updatedVal = record[item.column]?.name || record[item.column] || '[N/A]'
221
231
  }
222
232
 
233
+ // Translate conditionOfGoods values
234
+ if (item.column === 'conditionOfGoods') {
235
+ if (currentVal && currentVal !== '[N/A]') {
236
+ currentVal = this._getConditionOfGoodsLabel(currentVal)
237
+ }
238
+ if (updatedVal && updatedVal !== '[N/A]') {
239
+ updatedVal = this._getConditionOfGoodsLabel(updatedVal)
240
+ }
241
+ }
242
+
223
243
  recordDiff.push({
224
244
  column: item.name,
225
245
  current: currentVal || '[N/A]',
@@ -446,6 +466,7 @@ class InventoryAdjustmentApproval extends connect(store)(localize(i18next)(PageV
446
466
  unitCost
447
467
  adjustmentCode
448
468
  adjustmentNote
469
+ conditionOfGoods
449
470
  sku
450
471
  bizplace {
451
472
  id
@@ -496,6 +517,7 @@ class InventoryAdjustmentApproval extends connect(store)(localize(i18next)(PageV
496
517
  unitCost
497
518
  adjustmentCode
498
519
  adjustmentNote
520
+ conditionOfGoods
499
521
  }
500
522
  lastInventoryHistory {
501
523
  batchId
@@ -762,6 +784,11 @@ class InventoryAdjustmentApproval extends connect(store)(localize(i18next)(PageV
762
784
  _getDateString(date) {
763
785
  return `${date.getDate()} ${date.toLocaleString('default', { month: 'short' })} ${date.getFullYear()}`
764
786
  }
787
+
788
+ _getConditionOfGoodsLabel(value) {
789
+ const condition = Object.values(CONDITION_OF_GOODS).find(c => c.value === value)
790
+ return condition ? i18next.t(`label.${condition.name}`) : value || ''
791
+ }
765
792
  }
766
793
 
767
794
  window.customElements.define('inventory-adjustment-approval', InventoryAdjustmentApproval)
@@ -22,6 +22,7 @@ import { fetchPageSettings } from '../../util/index'
22
22
  import {
23
23
  ADJUSTMENT_CODE,
24
24
  CARTON_LABEL_SETTING_KEY,
25
+ CONDITION_OF_GOODS,
25
26
  INVENTORY_ITEM_CHANGE_TYPE,
26
27
  PALLET_LABEL_SETTING_KEY
27
28
  } from '../constants'
@@ -85,7 +86,8 @@ const INVENTORY_PATCH_KEYS = new Set([
85
86
  'cuFlag',
86
87
  'transferQty',
87
88
  'transferUomValue',
88
- 'obsolete'
89
+ 'obsolete',
90
+ 'conditionOfGoods'
89
91
  ])
90
92
 
91
93
  const toCamelKey = key =>
@@ -649,6 +651,32 @@ class InventoryAdjustment extends connect(store)(localize(i18next)(PageView)) {
649
651
  sortable: true,
650
652
  width: 120
651
653
  },
654
+ {
655
+ type: 'select',
656
+ name: 'conditionOfGoods',
657
+ header: i18next.t('field.inventory_quality'),
658
+ record: {
659
+ editable: true,
660
+ options: [
661
+ { display: '', value: '' },
662
+ ...Object.values(CONDITION_OF_GOODS).map(c => ({
663
+ display: i18next.t(`label.${c.name}`),
664
+ value: c.value
665
+ }))
666
+ ]
667
+ },
668
+ imex: {
669
+ header: i18next.t('field.inventory_quality'),
670
+ key: 'conditionOfGoods',
671
+ width: 20,
672
+ type: 'array',
673
+ arrData: Object.values(CONDITION_OF_GOODS).map(c => {
674
+ return { name: c.value }
675
+ })
676
+ },
677
+ sortable: true,
678
+ width: 120
679
+ },
652
680
  {
653
681
  type: 'boolean',
654
682
  name: 'obsolete',
@@ -849,6 +877,7 @@ class InventoryAdjustment extends connect(store)(localize(i18next)(PageView)) {
849
877
  arrivalNoticeNo
850
878
  adjustmentCode
851
879
  adjustmentNote
880
+ conditionOfGoods
852
881
  }
853
882
  total
854
883
  }
@@ -881,6 +910,7 @@ class InventoryAdjustment extends connect(store)(localize(i18next)(PageView)) {
881
910
  adjustmentNote
882
911
  serialNumbers
883
912
  obsolete
913
+ conditionOfGoods
884
914
  refOrderId
885
915
  arrivalNoticeRefNo
886
916
  partnerDomain {
@@ -5,6 +5,7 @@ import './inventory-history-by-pallet'
5
5
  import gql from 'graphql-tag'
6
6
  import { css, html, LitElement } from 'lit-element'
7
7
 
8
+ import { CONDITION_OF_GOODS } from '../constants'
8
9
  import { i18next, localize } from '@things-factory/i18n-base'
9
10
  import { openPopup } from '@things-factory/layout-base'
10
11
  import { client } from '@things-factory/shell'
@@ -148,6 +149,19 @@ class InventoryByProductDetail extends localize(i18next)(LitElement) {
148
149
  sortable: true,
149
150
  width: 200
150
151
  },
152
+ {
153
+ type: 'string',
154
+ name: 'conditionOfGoods',
155
+ header: i18next.t('field.inventory_quality'),
156
+ sortable: true,
157
+ width: 120,
158
+ record: {
159
+ renderer: (value, column, record, rowIndex, field) => {
160
+ const condition = Object.values(CONDITION_OF_GOODS).find(c => c.value === value)
161
+ return condition ? i18next.t(`label.${condition.name}`) : value || ''
162
+ }
163
+ }
164
+ },
151
165
  {
152
166
  type: 'number',
153
167
  name: 'lockedQty',
@@ -229,6 +243,7 @@ class InventoryByProductDetail extends localize(i18next)(LitElement) {
229
243
  name
230
244
  description
231
245
  }
246
+ conditionOfGoods
232
247
  uom
233
248
  lockedQty
234
249
  qty
@@ -9,6 +9,8 @@ import { client, PageView } from '@things-factory/shell'
9
9
  import { ScrollbarStyles } from '@things-factory/styles'
10
10
  import { isMobileDevice } from '@things-factory/utils'
11
11
 
12
+ import { CONDITION_OF_GOODS } from '../constants/order'
13
+
12
14
  class InventoryHistory extends localize(i18next)(PageView) {
13
15
  static get styles() {
14
16
  return [
@@ -311,6 +313,19 @@ class InventoryHistory extends localize(i18next)(PageView) {
311
313
  sortable: true,
312
314
  width: 150
313
315
  },
316
+ {
317
+ type: 'string',
318
+ name: 'conditionOfGoods',
319
+ header: i18next.t('field.inventory_quality'),
320
+ sortable: true,
321
+ width: 150,
322
+ record: {
323
+ renderer: (value, column, record, rowIndex, field) => {
324
+ const condition = Object.values(CONDITION_OF_GOODS).find(c => c.value === value)
325
+ return condition ? i18next.t(`label.${condition.name}`) : value || ''
326
+ }
327
+ }
328
+ },
314
329
  {
315
330
  type: 'string',
316
331
  name: 'batchIdRef',
@@ -497,6 +512,7 @@ class InventoryHistory extends localize(i18next)(PageView) {
497
512
  name
498
513
  description
499
514
  }
515
+ conditionOfGoods
500
516
  status
501
517
  transactionType
502
518
  createdAt
@@ -591,6 +607,7 @@ class InventoryHistory extends localize(i18next)(PageView) {
591
607
  zone
592
608
  orderNo
593
609
  refNo
610
+ conditionOfGoods
594
611
  status
595
612
  transactionType
596
613
  bizplace
@@ -678,6 +695,7 @@ class InventoryHistory extends localize(i18next)(PageView) {
678
695
  { header: i18next.t('field.uom_value'), key: 'uomValue', width: 75, type: 'number' },
679
696
  { header: i18next.t('field.uom'), key: 'uom', width: 75, type: 'string' },
680
697
  { header: i18next.t('field.location'), key: 'location', width: 75, type: 'string' },
698
+ { header: i18next.t('field.inventory_quality'), key: 'conditionOfGoods', width: 75, type: 'string' },
681
699
  { header: i18next.t('field.batch_id'), key: 'batchId', width: 75, type: 'string' },
682
700
  { header: i18next.t('field.batch_no_ref'), key: 'batchIdRef', width: 75, type: 'string' },
683
701
  { header: i18next.t('field.order_no'), key: 'orderNo', width: 75, type: 'string' },
@@ -6,6 +6,7 @@ import { css, html } from 'lit-element'
6
6
  import { connect } from 'pwa-helpers/connect-mixin'
7
7
 
8
8
  import { getCodeByName } from '@things-factory/code-base'
9
+ import { CONDITION_OF_GOODS } from '../constants'
9
10
  import { i18next, localize } from '@things-factory/i18n-base'
10
11
  import { client, PageView, store } from '@things-factory/shell'
11
12
  import { ScrollbarStyles } from '@things-factory/styles'
@@ -264,6 +265,18 @@ class OnhandInventory extends connect(store)(localize(i18next)(PageView)) {
264
265
  sortable: true,
265
266
  width: 80
266
267
  },
268
+ {
269
+ type: 'string',
270
+ name: 'conditionOfGoods',
271
+ header: i18next.t('field.inventory_quality'),
272
+ width: 120,
273
+ record: {
274
+ renderer: (value, column, record, rowIndex, field) => {
275
+ const condition = Object.values(CONDITION_OF_GOODS).find(c => c.value === value)
276
+ return condition ? i18next.t(`label.${condition.name}`) : value || ''
277
+ }
278
+ }
279
+ },
267
280
  {
268
281
  type: 'string',
269
282
  name: 'condition',
@@ -531,6 +544,7 @@ class OnhandInventory extends connect(store)(localize(i18next)(PageView)) {
531
544
  manufactureDate
532
545
  remark
533
546
  unitCost
547
+ conditionOfGoods
534
548
  adjustmentNote
535
549
  condition
536
550
  }
@@ -2,6 +2,7 @@ import '@things-factory/form-ui'
2
2
  import '@things-factory/grist-ui'
3
3
  import '@things-factory/worksheet-ui'
4
4
  import '../batch-picking-popup'
5
+ import '../packing-label-history-popup'
5
6
  import '../../../outbound/generate-worksheet-popup'
6
7
  import '../../../outbound/select-operator-popup'
7
8
 
@@ -58,6 +59,11 @@ class B2bOrderList extends localize(i18next)(PageView) {
58
59
  }
59
60
  }
60
61
 
62
+ constructor() {
63
+ super()
64
+ this._hasSelectionListener = false
65
+ }
66
+
61
67
  render() {
62
68
  return html`
63
69
  <search-form id="search-form" .fields=${this._searchFields} @submit=${e => this.dataGrist.fetch()}></search-form>
@@ -73,6 +79,32 @@ class B2bOrderList extends localize(i18next)(PageView) {
73
79
  get context() {
74
80
  var actions = []
75
81
 
82
+ actions.push({
83
+ title: i18next.t('title.packing_label_history'),
84
+ action: this._openPackingLabelHistory.bind(this),
85
+ icon: 'history',
86
+ emphasis: {
87
+ raised: false,
88
+ outlined: true,
89
+ dense: false,
90
+ danger: false
91
+ }
92
+ })
93
+
94
+ if (this._shouldShowButtonForSelection()) {
95
+ actions.push({
96
+ title: i18next.t('title.print_packing_label'),
97
+ action: this._openPrintPackingList.bind(this),
98
+ icon: 'print',
99
+ emphasis: {
100
+ raised: false,
101
+ outlined: true,
102
+ dense: false,
103
+ danger: false
104
+ }
105
+ })
106
+ }
107
+
76
108
  if (this.isUserBelongsDomain) {
77
109
  if (this._betaSetting) {
78
110
  actions.push({
@@ -96,6 +128,7 @@ class B2bOrderList extends localize(i18next)(PageView) {
96
128
  ...CommonButtonStyles.add
97
129
  })
98
130
  }
131
+
99
132
  return {
100
133
  title: i18next.t('title.release_orders'),
101
134
  actions,
@@ -501,6 +534,13 @@ class B2bOrderList extends localize(i18next)(PageView) {
501
534
  }
502
535
  ]
503
536
  }
537
+
538
+ await this.updateComplete
539
+ if (this.dataGrist && !this._hasSelectionListener) {
540
+ this.dataGrist.addEventListener('select-record-change', () => this.updateContext())
541
+ this.dataGrist.addEventListener('select-all-change', () => this.updateContext())
542
+ this._hasSelectionListener = true
543
+ }
504
544
  }
505
545
 
506
546
  get searchForm() {
@@ -588,6 +628,10 @@ class B2bOrderList extends localize(i18next)(PageView) {
588
628
  id
589
629
  name
590
630
  }
631
+ activeWorksheet {
632
+ type
633
+ status
634
+ }
591
635
  }
592
636
  total
593
637
  }
@@ -812,6 +856,61 @@ class B2bOrderList extends localize(i18next)(PageView) {
812
856
  return { header: headerSetting, data: data }
813
857
  }
814
858
 
859
+ _shouldShowButtonForSelection() {
860
+ if (!this.dataGrist) return false
861
+
862
+ const selected = this.dataGrist.selected || []
863
+ if (selected.length === 0) return false
864
+
865
+ const allowedWorksheetTypes = ['LOADING', 'PROCESSING', 'PARTIAL_PROCESSING']
866
+ const allowedWorksheetStatuses = ['EXECUTING', 'PARTIAL_EXECUTING']
867
+
868
+ return selected.every(order => {
869
+ // Check if activeWorksheet exists
870
+ if (!order.activeWorksheet) return false
871
+
872
+ // Check if activeWorksheet.type is one of the allowed types
873
+ if (!allowedWorksheetTypes.includes(order.activeWorksheet.type)) return false
874
+
875
+ // Check if activeWorksheet.status is EXECUTING or PARTIAL_EXECUTING
876
+ return allowedWorksheetStatuses.includes(order.activeWorksheet.status)
877
+ })
878
+ }
879
+
880
+ _openPrintPackingList() {
881
+ try {
882
+ if (!this.dataGrist || !this.dataGrist.selected || this.dataGrist.selected.length === 0) {
883
+ throw new Error(i18next.t('text.please_select_one_or_more_order') || 'Please select one or more orders')
884
+ }
885
+
886
+ const selectedOrderNames = this.dataGrist.selected.map(order => order.name).filter(Boolean)
887
+ if (selectedOrderNames.length === 0) {
888
+ throw new Error(i18next.t('text.no_valid_orders_selected') || 'No valid orders selected')
889
+ }
890
+
891
+ const orderNoParam = selectedOrderNames.join(',')
892
+ navigate(`preview_print_packing_list?orderNo=${encodeURIComponent(orderNoParam)}`)
893
+ } catch (e) {
894
+ this._showToast({ type: 'error', message: e.message || i18next.t('text.failed_to_open_print_packing_label') })
895
+ }
896
+ }
897
+
898
+ _openPackingLabelHistory() {
899
+ try {
900
+ openPopup(
901
+ html` <packing-label-history-popup></packing-label-history-popup> `,
902
+ {
903
+ backdrop: true,
904
+ size: 'large',
905
+ title: i18next.t('title.packing_label_history'),
906
+ escapable: false
907
+ }
908
+ )
909
+ } catch (e) {
910
+ this._showToast({ type: 'error', message: e.message || i18next.t('text.failed_to_open_packing_label_history') })
911
+ }
912
+ }
913
+
815
914
  _showToast({ type, message }) {
816
915
  document.dispatchEvent(
817
916
  new CustomEvent('notify', {