@things-factory/operato-wms 4.3.752 → 4.3.755
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.
- package/client/pages/inbound/unload-product.js +30 -33
- package/client/pages/outbound/loading-product.js +2 -3
- package/client/pages/outbound/loading-v2/loading-execution-base.js +568 -56
- package/client/pages/outbound/loading-v2/loading-execution.js +258 -8
- package/client/pages/outbound/loading-v2/loading.js +82 -12
- package/client/pages/outbound/picking-product.js +11 -6
- package/client/pages/outbound/picking-v2/picking-execution-base.js +8 -8
- package/client/pages/outbound/picking-v2/picking-execution.js +75 -0
- package/client/pages/outbound/route-label-history-dialog.js +253 -0
- package/client/pages/outbound/route-label-popup.js +637 -131
- package/client/pages/outbound/show-ro-list-popup.js +8 -4
- package/client/pages/outbound/single-outbound-worksheet.js +55 -6
- package/client/pages/outbound/sorting-product.js +71 -25
- package/client/pages/outbound/zone-worksheet.js +62 -3
- package/dist-server/entities/index.js +9 -0
- package/dist-server/entities/index.js.map +1 -0
- package/dist-server/entities/route-label-sequence-counter.js +75 -0
- package/dist-server/entities/route-label-sequence-counter.js.map +1 -0
- package/dist-server/entities/route-label-sequence-log.js +74 -0
- package/dist-server/entities/route-label-sequence-log.js.map +1 -0
- package/dist-server/graphql/resolvers/index.js +3 -0
- package/dist-server/graphql/resolvers/index.js.map +1 -1
- package/dist-server/graphql/resolvers/outbound/complete-load.js +40 -3
- package/dist-server/graphql/resolvers/outbound/complete-load.js.map +1 -1
- package/dist-server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.js +50 -11
- package/dist-server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.js.map +1 -1
- package/dist-server/graphql/resolvers/outbound/find-loadable-release-good.js +90 -48
- package/dist-server/graphql/resolvers/outbound/find-loadable-release-good.js.map +1 -1
- package/dist-server/graphql/resolvers/outbound/loading-worksheet-v2.js +15 -7
- package/dist-server/graphql/resolvers/outbound/loading-worksheet-v2.js.map +1 -1
- package/dist-server/graphql/resolvers/outbound/sort-item.js +95 -16
- package/dist-server/graphql/resolvers/outbound/sort-item.js.map +1 -1
- package/dist-server/graphql/resolvers/route-label/index.js +7 -0
- package/dist-server/graphql/resolvers/route-label/index.js.map +1 -0
- package/dist-server/graphql/resolvers/route-label/route-label.js +220 -0
- package/dist-server/graphql/resolvers/route-label/route-label.js.map +1 -0
- package/dist-server/graphql/resolvers/zone-worksheet/index.js.map +1 -1
- package/dist-server/graphql/resolvers/zone-worksheet/zone-picking.js +123 -27
- package/dist-server/graphql/resolvers/zone-worksheet/zone-picking.js.map +1 -1
- package/dist-server/graphql/resolvers/zone-worksheet/zone-worksheet.js.map +1 -1
- package/dist-server/graphql/types/index.js +4 -0
- package/dist-server/graphql/types/index.js.map +1 -1
- package/dist-server/graphql/types/outbound/index.js +7 -1
- package/dist-server/graphql/types/outbound/index.js.map +1 -1
- package/dist-server/graphql/types/route-label/index.js +14 -0
- package/dist-server/graphql/types/route-label/index.js.map +1 -0
- package/dist-server/graphql/types/route-label/route-label-sequence.js +53 -0
- package/dist-server/graphql/types/route-label/route-label-sequence.js.map +1 -0
- package/dist-server/index.js +5 -0
- package/dist-server/index.js.map +1 -1
- package/dist-server/validators/setting-validators.js +519 -0
- package/dist-server/validators/setting-validators.js.map +1 -0
- package/helps/operato-wms/outbound/picking-product.en.md +156 -158
- package/package.json +50 -50
- package/server/entities/index.ts +6 -0
- package/server/entities/route-label-sequence-counter.ts +56 -0
- package/server/entities/route-label-sequence-log.ts +47 -0
- package/server/graphql/resolvers/index.ts +3 -0
- package/server/graphql/resolvers/outbound/complete-load.ts +42 -1
- package/server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.ts +56 -13
- package/server/graphql/resolvers/outbound/find-loadable-release-good.ts +120 -57
- package/server/graphql/resolvers/outbound/loading-worksheet-v2.ts +9 -2
- package/server/graphql/resolvers/outbound/sort-item.ts +125 -21
- package/server/graphql/resolvers/route-label/index.ts +16 -0
- package/server/graphql/resolvers/route-label/route-label.ts +264 -0
- package/server/graphql/resolvers/zone-worksheet/index.ts +2 -2
- package/server/graphql/resolvers/zone-worksheet/zone-picking.ts +156 -39
- package/server/graphql/resolvers/zone-worksheet/zone-worksheet.ts +1 -2
- package/server/graphql/types/index.ts +4 -0
- package/server/graphql/types/outbound/index.ts +7 -1
- package/server/graphql/types/route-label/index.ts +18 -0
- package/server/graphql/types/route-label/route-label-sequence.ts +50 -0
- package/server/index.ts +7 -1
- package/server/validators/setting-validators.ts +668 -0
- package/translations/en.json +280 -252
- package/translations/ko.json +29 -1
- package/translations/ms.json +28 -0
- package/translations/zh.json +28 -0
|
@@ -4,6 +4,7 @@ import './release-good-info'
|
|
|
4
4
|
import './delivery-order-info'
|
|
5
5
|
import '../show-ro-list-popup'
|
|
6
6
|
import '../transport-vehicles-popup'
|
|
7
|
+
import '../tote-popup'
|
|
7
8
|
import './load-by-qty'
|
|
8
9
|
import './warehouse-return-popup'
|
|
9
10
|
|
|
@@ -21,7 +22,8 @@ import { showToast } from '../../../util'
|
|
|
21
22
|
// Constants
|
|
22
23
|
const SETTINGS = {
|
|
23
24
|
QC_SKU: 'qc-sku',
|
|
24
|
-
DISABLE_QC: 'disable-QC-in-loading'
|
|
25
|
+
DISABLE_QC: 'disable-QC-in-loading',
|
|
26
|
+
ENABLE_TOTE_SCANNING: 'enable-tote-scanning'
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
const TAB_TYPES = {
|
|
@@ -51,6 +53,18 @@ const FIND_LOADABLE_RELEASE_GOOD = gql`
|
|
|
51
53
|
total
|
|
52
54
|
pending
|
|
53
55
|
}
|
|
56
|
+
tabCounts {
|
|
57
|
+
LOADING {
|
|
58
|
+
total
|
|
59
|
+
completed
|
|
60
|
+
pending
|
|
61
|
+
}
|
|
62
|
+
LOADED {
|
|
63
|
+
total
|
|
64
|
+
completed
|
|
65
|
+
pending
|
|
66
|
+
}
|
|
67
|
+
}
|
|
54
68
|
}
|
|
55
69
|
}
|
|
56
70
|
`
|
|
@@ -58,6 +72,22 @@ const FIND_LOADABLE_RELEASE_GOOD = gql`
|
|
|
58
72
|
const FIND_LOADABLE_RELEASE_GOOD_BY_BIN = gql`
|
|
59
73
|
query findLoadableReleaseGoodByBin($orderNo: String!) {
|
|
60
74
|
findLoadableReleaseGoodByBin(orderNo: $orderNo) {
|
|
75
|
+
worksheetInfo {
|
|
76
|
+
binLocationName
|
|
77
|
+
isReleaseGoodScan
|
|
78
|
+
releaseGood {
|
|
79
|
+
id
|
|
80
|
+
name
|
|
81
|
+
attentionCompany
|
|
82
|
+
attentionTo
|
|
83
|
+
deliveryAddress1
|
|
84
|
+
deliveryAddress2
|
|
85
|
+
status
|
|
86
|
+
refNo
|
|
87
|
+
refNo2
|
|
88
|
+
refNo3
|
|
89
|
+
}
|
|
90
|
+
}
|
|
61
91
|
worksheetDetailInfos {
|
|
62
92
|
id
|
|
63
93
|
name
|
|
@@ -90,6 +120,7 @@ const FIND_LOADABLE_RELEASE_GOOD_BY_BIN = gql`
|
|
|
90
120
|
id
|
|
91
121
|
batchId
|
|
92
122
|
packingType
|
|
123
|
+
refWorksheetId
|
|
93
124
|
product {
|
|
94
125
|
id
|
|
95
126
|
sku
|
|
@@ -150,6 +181,7 @@ const LOADING_WORKSHEET_V2 = gql`
|
|
|
150
181
|
id
|
|
151
182
|
batchId
|
|
152
183
|
packingType
|
|
184
|
+
refWorksheetId
|
|
153
185
|
product {
|
|
154
186
|
id
|
|
155
187
|
sku
|
|
@@ -191,12 +223,19 @@ const GET_DELIVERY_ORDERS = gql`
|
|
|
191
223
|
`
|
|
192
224
|
|
|
193
225
|
const SORT_ITEM = gql`
|
|
194
|
-
mutation sortItem(
|
|
226
|
+
mutation sortItem(
|
|
227
|
+
$releaseGoodNo: String!
|
|
228
|
+
$productBarcode: String!
|
|
229
|
+
$qty: Float!
|
|
230
|
+
$worksheetDetails: [Object!]
|
|
231
|
+
$toteNo: String
|
|
232
|
+
) {
|
|
195
233
|
sortItem(
|
|
196
234
|
releaseGoodNo: $releaseGoodNo
|
|
197
235
|
productBarcode: $productBarcode
|
|
198
236
|
qty: $qty
|
|
199
237
|
worksheetDetails: $worksheetDetails
|
|
238
|
+
toteNo: $toteNo
|
|
200
239
|
)
|
|
201
240
|
}
|
|
202
241
|
`
|
|
@@ -213,6 +252,16 @@ const COMPLETE_LOAD_PARTIALLY = gql`
|
|
|
213
252
|
}
|
|
214
253
|
`
|
|
215
254
|
|
|
255
|
+
const VALIDATE_QC_SEALS = gql`
|
|
256
|
+
query validateQcSeals($releaseGoodNo: String!) {
|
|
257
|
+
validateQcSeals(releaseGoodNo: $releaseGoodNo) {
|
|
258
|
+
valid
|
|
259
|
+
error
|
|
260
|
+
minimumSealNumber
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
`
|
|
264
|
+
|
|
216
265
|
export class LoadingExecutionBase extends LitElement {
|
|
217
266
|
static get properties() {
|
|
218
267
|
return {
|
|
@@ -237,13 +286,24 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
237
286
|
loadedData: Array,
|
|
238
287
|
_executionData: Object,
|
|
239
288
|
_disableQC: Boolean,
|
|
240
|
-
_useQcSku: Boolean
|
|
289
|
+
_useQcSku: Boolean,
|
|
290
|
+
_enableToteScanning: Boolean,
|
|
291
|
+
_enableToteScanningValue: Number,
|
|
292
|
+
_hasRefWorksheetId: Boolean,
|
|
293
|
+
toteNo: String,
|
|
294
|
+
_tabCounts: Object,
|
|
295
|
+
_needsSealing: Boolean
|
|
241
296
|
}
|
|
242
297
|
}
|
|
243
298
|
|
|
244
299
|
constructor() {
|
|
245
300
|
super()
|
|
246
301
|
this._useQcSku = false
|
|
302
|
+
this._enableToteScanning = false
|
|
303
|
+
this._enableToteScanningValue = 0
|
|
304
|
+
this._hasRefWorksheetId = false
|
|
305
|
+
this.toteNo = ''
|
|
306
|
+
this._needsSealing = false
|
|
247
307
|
this._worksheetState = null
|
|
248
308
|
this._executionData = {
|
|
249
309
|
ownCollection: false,
|
|
@@ -332,7 +392,12 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
332
392
|
title: i18next.t('button.order_list'),
|
|
333
393
|
action: async () => {
|
|
334
394
|
try {
|
|
335
|
-
|
|
395
|
+
// If isReleaseGoodScan is true, use release good name; otherwise use binLocationName if QC SKU mode
|
|
396
|
+
const orderNo = this.worksheet?.isReleaseGoodScan
|
|
397
|
+
? this.worksheet?.releaseGood?.name
|
|
398
|
+
: this._useQcSku
|
|
399
|
+
? this.worksheet?.binLocationName
|
|
400
|
+
: this.worksheet?.releaseGood?.name
|
|
336
401
|
|
|
337
402
|
if (!orderNo) {
|
|
338
403
|
throw new Error(i18next.t('text.no_order_selected'))
|
|
@@ -344,7 +409,8 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
344
409
|
orderNo,
|
|
345
410
|
tabName: this.state?.activeTab || TAB_TYPES.LOADING
|
|
346
411
|
},
|
|
347
|
-
context: gqlContext()
|
|
412
|
+
context: gqlContext(),
|
|
413
|
+
fetchPolicy: 'network-only' // Always fetch fresh data to show updated item counts
|
|
348
414
|
})
|
|
349
415
|
|
|
350
416
|
if (!response.errors) {
|
|
@@ -363,6 +429,57 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
363
429
|
}
|
|
364
430
|
}
|
|
365
431
|
|
|
432
|
+
get toteButton() {
|
|
433
|
+
return {
|
|
434
|
+
title: i18next.t('button.tote'),
|
|
435
|
+
action: async () => {
|
|
436
|
+
await this.openTotePopup()
|
|
437
|
+
},
|
|
438
|
+
...CommonButtonStyles.activate
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
async openTotePopup() {
|
|
443
|
+
try {
|
|
444
|
+
const orderNo = this._currentReleaseGood?.releaseGood?.name
|
|
445
|
+
const bizplace = this._currentReleaseGood?.bizplaceName
|
|
446
|
+
|
|
447
|
+
if (!orderNo) {
|
|
448
|
+
throw new Error(i18next.t('text.no_release_order_selected'))
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
openPopup(
|
|
452
|
+
html`
|
|
453
|
+
<tote-popup
|
|
454
|
+
.orderNo="${orderNo}"
|
|
455
|
+
.toteNo="${this.toteNo}"
|
|
456
|
+
.bizplace="${bizplace}"
|
|
457
|
+
@completed="${async e => {
|
|
458
|
+
this.toteNo = e.detail
|
|
459
|
+
// Check seal status after tote is sealed (may have changed)
|
|
460
|
+
await this._checkAndUpdateSealStatus()
|
|
461
|
+
// Update button visibility after sealing (Tote button may need to be hidden if sealing is complete)
|
|
462
|
+
this.getButton()
|
|
463
|
+
// Update QC banner state after tote is sealed
|
|
464
|
+
if (this._updateQcBannerState) {
|
|
465
|
+
await this._updateQcBannerState()
|
|
466
|
+
}
|
|
467
|
+
}}"
|
|
468
|
+
></tote-popup>
|
|
469
|
+
`,
|
|
470
|
+
{
|
|
471
|
+
closable: false,
|
|
472
|
+
backdrop: false,
|
|
473
|
+
escapable: false,
|
|
474
|
+
size: 'large',
|
|
475
|
+
title: i18next.t('title.tote_scanning')
|
|
476
|
+
}
|
|
477
|
+
)
|
|
478
|
+
} catch (e) {
|
|
479
|
+
showToast(e)
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
366
483
|
// Input Getters
|
|
367
484
|
get productBarcodeInput() {
|
|
368
485
|
return this.shadowRoot
|
|
@@ -396,30 +513,86 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
396
513
|
|
|
397
514
|
// Core Methods
|
|
398
515
|
async openTab(e, tabName) {
|
|
516
|
+
// Validate seals before allowing switch to LOADING tab
|
|
517
|
+
// Validation applies when tote scanning is enabled and switching from QC or LOADED to LOADING
|
|
518
|
+
// The validation query checks if totes exist and are properly sealed based on minimum-seal-number
|
|
519
|
+
if (
|
|
520
|
+
tabName === TAB_TYPES.LOADING &&
|
|
521
|
+
(this.state?.activeTab === TAB_TYPES.QC || this.state?.activeTab === TAB_TYPES.LOADED) &&
|
|
522
|
+
this._enableToteScanning
|
|
523
|
+
) {
|
|
524
|
+
const orderNo = this._currentReleaseGood?.releaseGood?.name || this.worksheet?.releaseGood?.name
|
|
525
|
+
if (orderNo) {
|
|
526
|
+
try {
|
|
527
|
+
const validationResponse = await client.query({
|
|
528
|
+
query: VALIDATE_QC_SEALS,
|
|
529
|
+
variables: { releaseGoodNo: orderNo },
|
|
530
|
+
context: gqlContext()
|
|
531
|
+
})
|
|
532
|
+
|
|
533
|
+
if (!validationResponse.errors && validationResponse.data?.validateQcSeals) {
|
|
534
|
+
const { valid, error, minimumSealNumber } = validationResponse.data.validateQcSeals
|
|
535
|
+
// Only block if valid is false AND minimumSealNumber > 0
|
|
536
|
+
// If minimumSealNumber is 0, allow switching even if valid is false
|
|
537
|
+
if (!valid && (minimumSealNumber || 0) > 0) {
|
|
538
|
+
throw new Error(error || 'Seal validation failed')
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
} catch (e) {
|
|
542
|
+
showToast(e)
|
|
543
|
+
// Don't change tab on validation failure
|
|
544
|
+
return
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
399
549
|
this.state = { ...this.state, activeTab: tabName }
|
|
400
550
|
await this.updateComplete
|
|
401
551
|
|
|
402
552
|
if (tabName === TAB_TYPES.QC) {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
this._useQcSku
|
|
407
|
-
|
|
553
|
+
// If isReleaseGoodScan is true, use release good name; otherwise use binLocationName if QC SKU mode
|
|
554
|
+
const orderNoForQc = this.worksheet?.isReleaseGoodScan
|
|
555
|
+
? this.worksheet?.releaseGood?.name
|
|
556
|
+
: this._useQcSku
|
|
557
|
+
? this.worksheet?.binLocationName
|
|
558
|
+
: this.worksheet?.releaseGood?.name
|
|
559
|
+
const useQcSkuForFetch = this._useQcSku && !this.worksheet?.isReleaseGoodScan
|
|
560
|
+
// Fetch both QC and LOADING data so banner can check if items are ready for loading
|
|
561
|
+
const [qcData, loadingData] = await Promise.all([
|
|
562
|
+
this.fetchData(orderNoForQc, 'qc', useQcSkuForFetch),
|
|
563
|
+
this.fetchData(orderNoForQc, 'loading', useQcSkuForFetch)
|
|
564
|
+
])
|
|
408
565
|
this.qcData = qcData.filter(data => data?.sortedQty != data?.pickedQty) || []
|
|
566
|
+
this.loadingData =
|
|
567
|
+
loadingData.filter(data => data?.sortedQty > 0 && data.status != WORKSHEET_STATUS.DONE.value) || []
|
|
568
|
+
// Check seal status when opening QC tab (needed for Tote button visibility)
|
|
569
|
+
await this._checkAndUpdateSealStatus()
|
|
570
|
+
// Update button visibility after fetching QC data (which updates _hasRefWorksheetId)
|
|
571
|
+
this.getButton()
|
|
572
|
+
// Update QC banner state after fetching QC data
|
|
573
|
+
if (this._updateQcBannerState) {
|
|
574
|
+
await this._updateQcBannerState()
|
|
575
|
+
}
|
|
409
576
|
} else if (tabName === TAB_TYPES.LOADING) {
|
|
410
|
-
if
|
|
577
|
+
// Use bin-based query only if QC SKU mode AND it's not a release good scan
|
|
578
|
+
if (this._useQcSku && this.worksheet?.binLocationName && !this.worksheet?.isReleaseGoodScan) {
|
|
411
579
|
const response = await client.query({
|
|
412
580
|
query: FIND_LOADABLE_RELEASE_GOOD,
|
|
413
581
|
variables: {
|
|
414
582
|
orderNo: this.worksheet?.binLocationName,
|
|
415
583
|
tabName: this.state?.activeTab || TAB_TYPES.LOADING
|
|
416
584
|
},
|
|
417
|
-
context: gqlContext()
|
|
585
|
+
context: gqlContext(),
|
|
586
|
+
fetchPolicy: 'network-only' // Always fetch fresh data to show updated item counts
|
|
418
587
|
})
|
|
419
588
|
|
|
420
589
|
if (!response.errors) {
|
|
421
590
|
let records = response.data.findLoadableReleaseGood
|
|
422
591
|
if (records.length) {
|
|
592
|
+
// Store tabCounts from first record if available
|
|
593
|
+
if (records[0]?.tabCounts) {
|
|
594
|
+
this._tabCounts = records[0].tabCounts
|
|
595
|
+
}
|
|
423
596
|
await this.selectReleaseOrderPopup(records, this.state?.activeTab)
|
|
424
597
|
if (this.state.activeTab !== TAB_TYPES.LOADING) {
|
|
425
598
|
this.state = { ...this.state, activeTab: TAB_TYPES.LOADING }
|
|
@@ -431,9 +604,50 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
431
604
|
}
|
|
432
605
|
} else {
|
|
433
606
|
this.loadingData = await this.fetchData(this.worksheet?.releaseGood?.name, 'loading', this._useQcSku)
|
|
607
|
+
// Refresh tabCounts when switching to LOADING tab
|
|
608
|
+
if (this._currentReleaseGood?.releaseGood?.name || this.worksheet?.releaseGood?.name) {
|
|
609
|
+
const orderNo = this._currentReleaseGood?.releaseGood?.name || this.worksheet?.releaseGood?.name
|
|
610
|
+
try {
|
|
611
|
+
const response = await client.query({
|
|
612
|
+
query: FIND_LOADABLE_RELEASE_GOOD,
|
|
613
|
+
variables: {
|
|
614
|
+
orderNo,
|
|
615
|
+
tabName: TAB_TYPES.LOADING
|
|
616
|
+
},
|
|
617
|
+
context: gqlContext(),
|
|
618
|
+
fetchPolicy: 'network-only' // Always fetch fresh data to show updated counts
|
|
619
|
+
})
|
|
620
|
+
if (!response.errors && response.data.findLoadableReleaseGood.length > 0) {
|
|
621
|
+
const releaseGood = response.data.findLoadableReleaseGood[0]
|
|
622
|
+
if (releaseGood.tabCounts) {
|
|
623
|
+
this._tabCounts = releaseGood.tabCounts
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
} catch (e) {
|
|
627
|
+
console.error('Error refreshing tabCounts:', e)
|
|
628
|
+
}
|
|
629
|
+
}
|
|
434
630
|
}
|
|
435
631
|
} else if (tabName === TAB_TYPES.LOADED) {
|
|
436
|
-
|
|
632
|
+
// Ensure _currentReleaseGood is set from worksheet if not already set
|
|
633
|
+
if (!this._currentReleaseGood?.releaseGood?.name && this.worksheet?.releaseGood?.name) {
|
|
634
|
+
this._currentReleaseGood = {
|
|
635
|
+
releaseGood: this.worksheet.releaseGood,
|
|
636
|
+
bizplaceName: this.worksheet?.bizplaceName,
|
|
637
|
+
startedAt: this.worksheet?.startedAt
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// If we have a current release good, use reload() which works with order number (no bin required)
|
|
642
|
+
if (this._currentReleaseGood?.releaseGood?.name) {
|
|
643
|
+
await this.reload()
|
|
644
|
+
// reload() already calls getButton(), so we can return here
|
|
645
|
+
return
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// If using QC SKU mode and need to query by bin -> require bin location
|
|
649
|
+
// Only enforce bin selection when actually needed for bin-based operations
|
|
650
|
+
if (this._useQcSku) {
|
|
437
651
|
if (!this.worksheet?.binLocationName) {
|
|
438
652
|
throw new Error(i18next.t('text.no_bin_location_selected'))
|
|
439
653
|
}
|
|
@@ -444,27 +658,33 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
444
658
|
orderNo: this.worksheet.binLocationName,
|
|
445
659
|
tabName: this.state?.activeTab || TAB_TYPES.LOADED
|
|
446
660
|
},
|
|
447
|
-
context: gqlContext()
|
|
661
|
+
context: gqlContext(),
|
|
662
|
+
fetchPolicy: 'network-only' // Always fetch fresh data to show updated item counts
|
|
448
663
|
})
|
|
449
664
|
|
|
450
665
|
if (!response.errors) {
|
|
451
666
|
let records = response.data.findLoadableReleaseGood
|
|
452
667
|
if (records.length) {
|
|
453
|
-
|
|
454
|
-
if (
|
|
455
|
-
this.
|
|
456
|
-
if (!this.worksheet?.worksheet?.id) {
|
|
457
|
-
await this.fetchData(this._currentReleaseGood.releaseGood.name, 'loading', this._useQcSku)
|
|
458
|
-
}
|
|
668
|
+
// Store tabCounts from first record if available
|
|
669
|
+
if (records[0]?.tabCounts) {
|
|
670
|
+
this._tabCounts = records[0].tabCounts
|
|
459
671
|
}
|
|
672
|
+
await this.selectReleaseOrderPopup(records, this.state?.activeTab)
|
|
673
|
+
// selectReleaseOrderPopup will handle data fetch and getButton() call
|
|
674
|
+
return
|
|
460
675
|
} else {
|
|
461
676
|
throw new Error(i18next.t('text.no_release_order_found'))
|
|
462
677
|
}
|
|
463
678
|
}
|
|
464
679
|
} else {
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
680
|
+
// Not using QC SKU mode and no current release good -> try to use order number from worksheet
|
|
681
|
+
// Allow switching to LOADED tab even without bin selection
|
|
682
|
+
if (this.worksheet?.releaseGood?.name) {
|
|
683
|
+
await this.reload()
|
|
684
|
+
return
|
|
685
|
+
} else {
|
|
686
|
+
// No order selected at all -> show error
|
|
687
|
+
throw new Error(i18next.t('text.no_release_order_selected'))
|
|
468
688
|
}
|
|
469
689
|
}
|
|
470
690
|
}
|
|
@@ -498,27 +718,66 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
498
718
|
startedAt: this.worksheet?.startedAt
|
|
499
719
|
}
|
|
500
720
|
|
|
721
|
+
// Reset tote selection when switching RO
|
|
722
|
+
this.toteNo = ''
|
|
723
|
+
// Reset refWorksheetId flag - will be updated when data is fetched
|
|
724
|
+
this._hasRefWorksheetId = false
|
|
725
|
+
// Reset seal status - will be updated after data is fetched
|
|
726
|
+
this._needsSealing = false
|
|
727
|
+
|
|
501
728
|
this._executionData = {
|
|
502
729
|
...this._executionData,
|
|
503
730
|
orderId: selectedRO.id
|
|
504
731
|
}
|
|
505
732
|
|
|
506
|
-
|
|
733
|
+
// Store tabCounts for banner display
|
|
734
|
+
if (selectedRO.tabCounts) {
|
|
735
|
+
this._tabCounts = selectedRO.tabCounts
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// UX-safe tab selection: Auto-switch to LOADED if LOADING is empty but LOADED has items
|
|
739
|
+
let finalTabName = tabName
|
|
740
|
+
if (selectedRO.tabCounts) {
|
|
741
|
+
const loadingCounts = selectedRO.tabCounts.LOADING || { total: 0, pending: 0 }
|
|
742
|
+
const loadedCounts = selectedRO.tabCounts.LOADED || { total: 0, pending: 0 }
|
|
743
|
+
|
|
744
|
+
// If current tab is LOADING and it's empty, but LOADED has items, switch to LOADED
|
|
745
|
+
if (tabName === TAB_TYPES.LOADING && loadingCounts.total === 0 && loadedCounts.total > 0) {
|
|
746
|
+
finalTabName = TAB_TYPES.LOADED
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
this.state = { ...this.state, activeTab: finalTabName }
|
|
507
751
|
await this.updateComplete
|
|
508
752
|
|
|
509
|
-
if (
|
|
753
|
+
if (finalTabName === TAB_TYPES.LOADING) {
|
|
510
754
|
this.loadingData = await this.fetchData(selectedRO.name, 'loading', false)
|
|
511
|
-
} else if (
|
|
755
|
+
} else if (finalTabName === TAB_TYPES.LOADED) {
|
|
512
756
|
this.loadedData = await fetchDeliveryOrders(selectedRO.name)
|
|
513
757
|
if (!this.worksheet?.worksheet?.id) {
|
|
514
758
|
await this.fetchData(selectedRO.name, 'loading', this._useQcSku)
|
|
515
759
|
}
|
|
516
|
-
} else if (
|
|
517
|
-
|
|
760
|
+
} else if (finalTabName === TAB_TYPES.QC) {
|
|
761
|
+
// Fetch both QC and LOADING data so banner can check if items are ready for loading
|
|
762
|
+
const [qcData, loadingData] = await Promise.all([
|
|
763
|
+
this.fetchData(selectedRO.name, 'qc', this._useQcSku),
|
|
764
|
+
this.fetchData(selectedRO.name, 'loading', this._useQcSku)
|
|
765
|
+
])
|
|
766
|
+
this.qcData = qcData.filter(data => data?.sortedQty < data?.pickedQty) || []
|
|
767
|
+
this.loadingData =
|
|
768
|
+
loadingData.filter(data => data?.sortedQty > 0 && data.status != WORKSHEET_STATUS.DONE.value) || []
|
|
769
|
+
// fetchData updates _hasRefWorksheetId, so update buttons after data is fetched
|
|
518
770
|
}
|
|
519
771
|
|
|
520
772
|
await this.updateComplete
|
|
773
|
+
// Check seal status after order is selected (needed for Tote button visibility)
|
|
774
|
+
await this._checkAndUpdateSealStatus()
|
|
775
|
+
// Update button visibility after data is fetched (which updates _hasRefWorksheetId)
|
|
521
776
|
this.getButton()
|
|
777
|
+
// Update QC banner state after data is fetched
|
|
778
|
+
if (this._updateQcBannerState) {
|
|
779
|
+
await this._updateQcBannerState()
|
|
780
|
+
}
|
|
522
781
|
}}
|
|
523
782
|
></show-ro-list-popup>
|
|
524
783
|
`,
|
|
@@ -546,6 +805,8 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
546
805
|
async resetView() {
|
|
547
806
|
this._disableQC = await fetchSettingRule(SETTINGS.DISABLE_QC)
|
|
548
807
|
this._useQcSku = await fetchSettingRule(SETTINGS.QC_SKU)
|
|
808
|
+
this._enableToteScanningValue = parseInt((await fetchSettingRule(SETTINGS.ENABLE_TOTE_SCANNING)) || '0', 10)
|
|
809
|
+
this._enableToteScanning = this._enableToteScanningValue >= 1
|
|
549
810
|
|
|
550
811
|
let activeTab = TAB_TYPES.QC
|
|
551
812
|
if (this._disableQC && !this._useQcSku) {
|
|
@@ -556,7 +817,14 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
556
817
|
|
|
557
818
|
const currentWorksheet = this.worksheet
|
|
558
819
|
|
|
559
|
-
|
|
820
|
+
// Check if any order inventory has refWorksheetId (when data comes from props)
|
|
821
|
+
if (this.worksheetDetails && this.worksheetDetails.length > 0) {
|
|
822
|
+
this._hasRefWorksheetId = this.worksheetDetails.some(
|
|
823
|
+
item => item?.relatedOrderInv?.refWorksheetId != null && item?.relatedOrderInv?.refWorksheetId !== ''
|
|
824
|
+
)
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
this.qcData = this.worksheetDetails.filter(data => data?.sortedQty < data?.pickedQty) || []
|
|
560
828
|
this.loadingData =
|
|
561
829
|
this.worksheetDetails.filter(data => data?.sortedQty > 0 && data.status != WORKSHEET_STATUS.DONE.value) || []
|
|
562
830
|
this.loadedData = this.deliveryOrdersInfo || []
|
|
@@ -567,6 +835,9 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
567
835
|
worksheetId: currentWorksheet?.worksheet?.id
|
|
568
836
|
}
|
|
569
837
|
|
|
838
|
+
// reset tote when resetting view
|
|
839
|
+
this.toteNo = ''
|
|
840
|
+
|
|
570
841
|
if (!this.worksheet && this.worksheetDetails?.length > 0) {
|
|
571
842
|
this.worksheet = {
|
|
572
843
|
...currentWorksheet,
|
|
@@ -577,10 +848,175 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
577
848
|
this.getButton()
|
|
578
849
|
}
|
|
579
850
|
|
|
851
|
+
/**
|
|
852
|
+
* Reloads all data and counts after mutations (load, undo, etc.)
|
|
853
|
+
* This ensures banner and button visibility are always accurate
|
|
854
|
+
* Always fetches counts for BOTH LOADING and LOADED tabs
|
|
855
|
+
*/
|
|
856
|
+
async reload() {
|
|
857
|
+
// If no order selected, clear stale state and show error
|
|
858
|
+
if (!this._currentReleaseGood?.releaseGood?.name && !this.worksheet?.releaseGood?.name) {
|
|
859
|
+
// Clear stale state to prevent incorrect UI
|
|
860
|
+
this._tabCounts = null
|
|
861
|
+
this.loadedData = null
|
|
862
|
+
showToast({ type: 'error', message: i18next.t('text.no_release_order_selected') })
|
|
863
|
+
this.getButton()
|
|
864
|
+
return
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
const orderNo = this._currentReleaseGood?.releaseGood?.name || this.worksheet?.releaseGood?.name
|
|
868
|
+
|
|
869
|
+
try {
|
|
870
|
+
// Query for BOTH LOADING and LOADED tabs to ensure complete tabCounts
|
|
871
|
+
const [loadingResponse, loadedResponse] = await Promise.all([
|
|
872
|
+
client.query({
|
|
873
|
+
query: FIND_LOADABLE_RELEASE_GOOD,
|
|
874
|
+
variables: {
|
|
875
|
+
orderNo,
|
|
876
|
+
tabName: TAB_TYPES.LOADING
|
|
877
|
+
},
|
|
878
|
+
context: gqlContext(),
|
|
879
|
+
fetchPolicy: 'network-only' // Always fetch fresh data to show updated counts
|
|
880
|
+
}),
|
|
881
|
+
client.query({
|
|
882
|
+
query: FIND_LOADABLE_RELEASE_GOOD,
|
|
883
|
+
variables: {
|
|
884
|
+
orderNo,
|
|
885
|
+
tabName: TAB_TYPES.LOADED
|
|
886
|
+
},
|
|
887
|
+
context: gqlContext(),
|
|
888
|
+
fetchPolicy: 'network-only' // Always fetch fresh data to show updated counts
|
|
889
|
+
})
|
|
890
|
+
])
|
|
891
|
+
|
|
892
|
+
// Merge tabCounts from both queries
|
|
893
|
+
let mergedTabCounts = {
|
|
894
|
+
LOADING: null,
|
|
895
|
+
LOADED: null
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// Extract LOADING counts
|
|
899
|
+
if (!loadingResponse.errors && loadingResponse.data.findLoadableReleaseGood.length > 0) {
|
|
900
|
+
const loadingReleaseGood = loadingResponse.data.findLoadableReleaseGood[0]
|
|
901
|
+
if (loadingReleaseGood.tabCounts?.LOADING) {
|
|
902
|
+
mergedTabCounts.LOADING = loadingReleaseGood.tabCounts.LOADING
|
|
903
|
+
}
|
|
904
|
+
// Also get LOADED counts from LOADING query if available (backend returns both)
|
|
905
|
+
if (loadingReleaseGood.tabCounts?.LOADED) {
|
|
906
|
+
mergedTabCounts.LOADED = loadingReleaseGood.tabCounts.LOADED
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
// Extract LOADED counts (prefer from LOADED query if LOADING query didn't have it)
|
|
911
|
+
if (!loadedResponse.errors && loadedResponse.data.findLoadableReleaseGood.length > 0) {
|
|
912
|
+
const loadedReleaseGood = loadedResponse.data.findLoadableReleaseGood[0]
|
|
913
|
+
if (loadedReleaseGood.tabCounts?.LOADED) {
|
|
914
|
+
mergedTabCounts.LOADED = loadedReleaseGood.tabCounts.LOADED
|
|
915
|
+
}
|
|
916
|
+
// Also get LOADING counts from LOADED query if available (backend returns both)
|
|
917
|
+
if (loadedReleaseGood.tabCounts?.LOADING && !mergedTabCounts.LOADING) {
|
|
918
|
+
mergedTabCounts.LOADING = loadedReleaseGood.tabCounts.LOADING
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
// Set merged tabCounts (only if we got at least one count)
|
|
923
|
+
if (mergedTabCounts.LOADING || mergedTabCounts.LOADED) {
|
|
924
|
+
this._tabCounts = mergedTabCounts
|
|
925
|
+
} else {
|
|
926
|
+
// Both queries returned empty or had errors - clear stale tabCounts
|
|
927
|
+
this._tabCounts = null
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
// Refresh loadedData
|
|
931
|
+
if (orderNo) {
|
|
932
|
+
this.loadedData = await fetchDeliveryOrders(orderNo)
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
// Always refresh loadingData (not just when on LOADING tab)
|
|
936
|
+
// This ensures banner condition (which uses loadingData.length) is accurate after undo/load mutations
|
|
937
|
+
// If a release good is selected (from popup), use release good query, not bin query
|
|
938
|
+
if (orderNo) {
|
|
939
|
+
const useQcSkuForReload =
|
|
940
|
+
this._useQcSku && !this.worksheet?.isReleaseGoodScan && !this._currentReleaseGood?.releaseGood?.name
|
|
941
|
+
this.loadingData = await this.fetchData(orderNo, 'loading', useQcSkuForReload)
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
// Update button visibility
|
|
945
|
+
await this.updateComplete
|
|
946
|
+
this.getButton()
|
|
947
|
+
|
|
948
|
+
// Update QC banner state after reload (in case we're on QC tab)
|
|
949
|
+
if (this._updateQcBannerState) {
|
|
950
|
+
await this._updateQcBannerState()
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
// Request update to refresh banner visibility after data reload
|
|
954
|
+
this.requestUpdate()
|
|
955
|
+
} catch (e) {
|
|
956
|
+
console.error('Error reloading data:', e)
|
|
957
|
+
// Clear stale state on error to prevent incorrect UI
|
|
958
|
+
this._tabCounts = null
|
|
959
|
+
this.loadedData = null
|
|
960
|
+
showToast({
|
|
961
|
+
type: 'error',
|
|
962
|
+
message: i18next.t('text.failed_to_refresh_data', { defaultValue: 'Failed to refresh data' })
|
|
963
|
+
})
|
|
964
|
+
this.getButton()
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
/**
|
|
969
|
+
* Checks if sealing is needed and updates _needsSealing property
|
|
970
|
+
* This can be overridden by child classes to provide custom seal checking logic
|
|
971
|
+
*/
|
|
972
|
+
async _checkAndUpdateSealStatus() {
|
|
973
|
+
if (!this._enableToteScanning) {
|
|
974
|
+
this._needsSealing = false
|
|
975
|
+
return
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
const orderNo = this._currentReleaseGood?.releaseGood?.name || this.worksheet?.releaseGood?.name
|
|
979
|
+
if (!orderNo) {
|
|
980
|
+
this._needsSealing = false
|
|
981
|
+
return
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
try {
|
|
985
|
+
const validationResponse = await client.query({
|
|
986
|
+
query: VALIDATE_QC_SEALS,
|
|
987
|
+
variables: { releaseGoodNo: orderNo },
|
|
988
|
+
context: gqlContext()
|
|
989
|
+
})
|
|
990
|
+
|
|
991
|
+
if (!validationResponse.errors && validationResponse.data?.validateQcSeals) {
|
|
992
|
+
const { valid, minimumSealNumber } = validationResponse.data.validateQcSeals
|
|
993
|
+
const minSealNum = minimumSealNumber || 0
|
|
994
|
+
// Sealing is needed if valid is false AND minimumSealNumber > 0
|
|
995
|
+
this._needsSealing = !valid && minSealNum > 0
|
|
996
|
+
} else {
|
|
997
|
+
this._needsSealing = false
|
|
998
|
+
}
|
|
999
|
+
} catch (e) {
|
|
1000
|
+
// On error, assume sealing might be needed to be safe
|
|
1001
|
+
this._needsSealing = true
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
580
1005
|
getButton() {
|
|
581
1006
|
let activeTab = this.state?.activeTab
|
|
582
1007
|
|
|
583
1008
|
let buttons = [this.backButton]
|
|
1009
|
+
// Tote button visibility logic for QC tab:
|
|
1010
|
+
if (activeTab === TAB_TYPES.QC && this._enableToteScanning && this._useQcSku === false) {
|
|
1011
|
+
const shouldShowToteButton =
|
|
1012
|
+
(this._disableQC === false && this._hasRefWorksheetId) ||
|
|
1013
|
+
(this._disableQC === false && this._enableToteScanningValue === 2 && !this._hasRefWorksheetId) ||
|
|
1014
|
+
this._needsSealing === true
|
|
1015
|
+
|
|
1016
|
+
if (shouldShowToteButton) {
|
|
1017
|
+
buttons.unshift(this.toteButton)
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
584
1020
|
if (activeTab === TAB_TYPES.LOADING) {
|
|
585
1021
|
if (this.loadingData?.length > 0) {
|
|
586
1022
|
if (this._useQcSku) {
|
|
@@ -593,10 +1029,20 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
593
1029
|
if (this._useQcSku) {
|
|
594
1030
|
buttons.unshift(this.orderListButton)
|
|
595
1031
|
}
|
|
596
|
-
|
|
1032
|
+
// Show COMPLETE button based on:
|
|
1033
|
+
// 1. Prefer _tabCounts.LOADED.total > 0 (most reliable)
|
|
1034
|
+
// 2. Only block if loadedData.completable === false explicitly
|
|
1035
|
+
// 3. Also check loadedData.deliveryOrders as fallback
|
|
1036
|
+
const hasLoadedItems =
|
|
1037
|
+
this._tabCounts?.LOADED?.total > 0 ||
|
|
1038
|
+
(this.loadedData?.deliveryOrders && this.loadedData.deliveryOrders.length > 0)
|
|
1039
|
+
const canComplete = this.loadedData?.completable !== false
|
|
1040
|
+
|
|
1041
|
+
if (hasLoadedItems && canComplete) {
|
|
597
1042
|
buttons.unshift(this.completeButton)
|
|
598
1043
|
} else if (
|
|
599
|
-
this.loadedData?.deliveryOrders
|
|
1044
|
+
this.loadedData?.deliveryOrders &&
|
|
1045
|
+
this.loadedData.deliveryOrders.length > 0 &&
|
|
600
1046
|
this._currentReleaseGood?.releaseGood?.status !== 'LOADING'
|
|
601
1047
|
) {
|
|
602
1048
|
buttons.unshift(this.partialButton)
|
|
@@ -665,7 +1111,8 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
665
1111
|
.data="${targetDO}"
|
|
666
1112
|
@undo=${async e => {
|
|
667
1113
|
showToast({ type: 'success', message: 'undo loading completed' })
|
|
668
|
-
|
|
1114
|
+
// Reload all data and counts to update banner and button visibility
|
|
1115
|
+
await this.reload()
|
|
669
1116
|
}}
|
|
670
1117
|
></delivery-order-info>
|
|
671
1118
|
`,
|
|
@@ -685,13 +1132,21 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
685
1132
|
await this.validateSorting()
|
|
686
1133
|
let selectedData = this.qcData.filter(data => this.qcDataView.selectedItems.includes(data.id))
|
|
687
1134
|
|
|
1135
|
+
// If isReleaseGoodScan is true, use release good name; otherwise use binLocationName if QC SKU mode
|
|
1136
|
+
const releaseGoodNo = this.worksheet?.isReleaseGoodScan
|
|
1137
|
+
? this.worksheet?.releaseGood?.name
|
|
1138
|
+
: this._useQcSku
|
|
1139
|
+
? this.worksheet?.binLocationName
|
|
1140
|
+
: this.worksheet?.releaseGood?.name
|
|
1141
|
+
|
|
688
1142
|
const response = await client.mutate({
|
|
689
1143
|
mutation: SORT_ITEM,
|
|
690
1144
|
variables: {
|
|
691
|
-
releaseGoodNo
|
|
1145
|
+
releaseGoodNo,
|
|
692
1146
|
productBarcode: this.productBarcodeInput.value,
|
|
693
1147
|
qty: parseFloat(this.qtyInput.value),
|
|
694
|
-
worksheetDetails: selectedData
|
|
1148
|
+
worksheetDetails: selectedData,
|
|
1149
|
+
toteNo: this._enableToteScanning && this.toteNo !== '' ? this.toteNo : null
|
|
695
1150
|
}
|
|
696
1151
|
})
|
|
697
1152
|
|
|
@@ -700,13 +1155,28 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
700
1155
|
this.qtyInput.value = ''
|
|
701
1156
|
this._focusOnProductBarcodeInput()
|
|
702
1157
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
this.
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
1158
|
+
// Fetch data for both QC and LOADING tabs to ensure banner condition is accurate
|
|
1159
|
+
// If isReleaseGoodScan is true, use release good name; otherwise use binLocationName if QC SKU mode
|
|
1160
|
+
const orderNoForRefresh = this.worksheet?.isReleaseGoodScan
|
|
1161
|
+
? this.worksheet?.releaseGood?.name
|
|
1162
|
+
: this._useQcSku
|
|
1163
|
+
? this.worksheet?.binLocationName
|
|
1164
|
+
: this.worksheet?.releaseGood?.name
|
|
1165
|
+
const useQcSkuForRefresh = this._useQcSku && !this.worksheet?.isReleaseGoodScan
|
|
1166
|
+
|
|
1167
|
+
const [qcData, loadingData] = await Promise.all([
|
|
1168
|
+
this.fetchData(orderNoForRefresh, 'qc', useQcSkuForRefresh),
|
|
1169
|
+
this.fetchData(orderNoForRefresh, 'loading', useQcSkuForRefresh)
|
|
1170
|
+
])
|
|
1171
|
+
|
|
1172
|
+
this.qcData = qcData.filter(data => data?.sortedQty < data?.pickedQty) || []
|
|
1173
|
+
this.loadingData =
|
|
1174
|
+
loadingData.filter(data => data?.sortedQty > 0 && data.status != WORKSHEET_STATUS.DONE.value) || []
|
|
1175
|
+
|
|
1176
|
+
// Update QC banner state after data changes
|
|
1177
|
+
if (this._updateQcBannerState) {
|
|
1178
|
+
await this._updateQcBannerState()
|
|
1179
|
+
}
|
|
710
1180
|
}
|
|
711
1181
|
} catch (e) {
|
|
712
1182
|
showToast(e)
|
|
@@ -750,11 +1220,8 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
750
1220
|
._executionData=${loadData}
|
|
751
1221
|
@loading=${async e => {
|
|
752
1222
|
showToast({ type: 'success', message: 'loaded successfully' })
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
'loading',
|
|
756
|
-
this._useQcSku
|
|
757
|
-
)
|
|
1223
|
+
// Reload all data and counts to update banner and button visibility
|
|
1224
|
+
await this.reload()
|
|
758
1225
|
}}
|
|
759
1226
|
></load-by-qty>
|
|
760
1227
|
`,
|
|
@@ -802,10 +1269,23 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
802
1269
|
// --- Clear previous order and UI data ---
|
|
803
1270
|
this._currentReleaseGood = null
|
|
804
1271
|
this.loadedData = []
|
|
1272
|
+
this.loadingData = []
|
|
1273
|
+
this.qcData = []
|
|
1274
|
+
this.worksheet = null
|
|
1275
|
+
this.worksheetDetails = null
|
|
1276
|
+
this._tabCounts = null
|
|
1277
|
+
this._hasRefWorksheetId = false
|
|
1278
|
+
this.toteNo = ''
|
|
1279
|
+
this.state = null
|
|
805
1280
|
|
|
806
1281
|
setTimeout(async () => {
|
|
807
1282
|
try {
|
|
808
|
-
|
|
1283
|
+
// If isReleaseGoodScan is true, use release good name; otherwise use binLocationName if QC SKU mode
|
|
1284
|
+
const orderNo = this.worksheet?.isReleaseGoodScan
|
|
1285
|
+
? this.worksheet?.releaseGood?.name
|
|
1286
|
+
: this._useQcSku
|
|
1287
|
+
? this.worksheet?.binLocationName
|
|
1288
|
+
: this.worksheet?.releaseGood?.name
|
|
809
1289
|
if (!orderNo) {
|
|
810
1290
|
resetContext(this.parent)
|
|
811
1291
|
return
|
|
@@ -817,14 +1297,18 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
817
1297
|
orderNo,
|
|
818
1298
|
tabName: this.state?.activeTab || TAB_TYPES.LOADING
|
|
819
1299
|
},
|
|
820
|
-
context: gqlContext()
|
|
1300
|
+
context: gqlContext(),
|
|
1301
|
+
fetchPolicy: 'network-only' // Always fetch fresh data to show updated item counts
|
|
821
1302
|
})
|
|
822
1303
|
|
|
823
1304
|
if (!response.errors) {
|
|
824
1305
|
const orders = response.data.findLoadableReleaseGood
|
|
825
|
-
|
|
826
|
-
|
|
1306
|
+
// Filter out orders that are already DONE
|
|
1307
|
+
const activeOrders = orders.filter(order => order.status !== 'DONE')
|
|
1308
|
+
if (activeOrders.length) {
|
|
1309
|
+
await this.selectReleaseOrderPopup(activeOrders, this.state?.activeTab)
|
|
827
1310
|
} else {
|
|
1311
|
+
// No more active orders, reset to initial scan screen
|
|
828
1312
|
resetContext(this.parent)
|
|
829
1313
|
}
|
|
830
1314
|
}
|
|
@@ -872,10 +1356,23 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
872
1356
|
// --- Clear previous order and UI data ---
|
|
873
1357
|
this._currentReleaseGood = null
|
|
874
1358
|
this.loadedData = []
|
|
1359
|
+
this.loadingData = []
|
|
1360
|
+
this.qcData = []
|
|
1361
|
+
this.worksheet = null
|
|
1362
|
+
this.worksheetDetails = null
|
|
1363
|
+
this._tabCounts = null
|
|
1364
|
+
this._hasRefWorksheetId = false
|
|
1365
|
+
this.toteNo = ''
|
|
1366
|
+
this.state = null
|
|
875
1367
|
|
|
876
1368
|
setTimeout(async () => {
|
|
877
1369
|
try {
|
|
878
|
-
|
|
1370
|
+
// If isReleaseGoodScan is true, use release good name; otherwise use binLocationName if QC SKU mode
|
|
1371
|
+
const orderNo = this.worksheet?.isReleaseGoodScan
|
|
1372
|
+
? this.worksheet?.releaseGood?.name
|
|
1373
|
+
: this._useQcSku
|
|
1374
|
+
? this.worksheet?.binLocationName
|
|
1375
|
+
: this.worksheet?.releaseGood?.name
|
|
879
1376
|
if (!orderNo) {
|
|
880
1377
|
resetContext(this.parent)
|
|
881
1378
|
return
|
|
@@ -887,14 +1384,18 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
887
1384
|
orderNo,
|
|
888
1385
|
tabName: this.state?.activeTab || TAB_TYPES.LOADING
|
|
889
1386
|
},
|
|
890
|
-
context: gqlContext()
|
|
1387
|
+
context: gqlContext(),
|
|
1388
|
+
fetchPolicy: 'network-only' // Always fetch fresh data to show updated item counts
|
|
891
1389
|
})
|
|
892
1390
|
|
|
893
1391
|
if (!response.errors) {
|
|
894
1392
|
const orders = response.data.findLoadableReleaseGood
|
|
895
|
-
|
|
896
|
-
|
|
1393
|
+
// Filter out orders that are already DONE
|
|
1394
|
+
const activeOrders = orders.filter(order => order.status !== 'DONE')
|
|
1395
|
+
if (activeOrders.length) {
|
|
1396
|
+
await this.selectReleaseOrderPopup(activeOrders, this.state?.activeTab)
|
|
897
1397
|
} else {
|
|
1398
|
+
// No more active orders, reset to initial scan screen
|
|
898
1399
|
resetContext(this.parent)
|
|
899
1400
|
}
|
|
900
1401
|
}
|
|
@@ -934,7 +1435,8 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
934
1435
|
|
|
935
1436
|
async fetchData(orderNo, tab, useQcSku) {
|
|
936
1437
|
try {
|
|
937
|
-
|
|
1438
|
+
// Otherwise, use FIND_LOADABLE_RELEASE_GOOD_BY_BIN for both QC and LOADING tabs when useQcSku is true (bin scan)
|
|
1439
|
+
if (useQcSku && !this.worksheet?.isReleaseGoodScan) {
|
|
938
1440
|
const response = await client.query({
|
|
939
1441
|
query: FIND_LOADABLE_RELEASE_GOOD_BY_BIN,
|
|
940
1442
|
variables: { orderNo }
|
|
@@ -942,6 +1444,10 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
942
1444
|
|
|
943
1445
|
if (!response.errors) {
|
|
944
1446
|
const data = response.data.findLoadableReleaseGoodByBin.worksheetDetailInfos
|
|
1447
|
+
// Check if any order inventory has refWorksheetId
|
|
1448
|
+
this._hasRefWorksheetId = data.some(
|
|
1449
|
+
item => item?.relatedOrderInv?.refWorksheetId != null && item?.relatedOrderInv?.refWorksheetId !== ''
|
|
1450
|
+
)
|
|
945
1451
|
return combineSameProducts(data)
|
|
946
1452
|
}
|
|
947
1453
|
} else {
|
|
@@ -973,7 +1479,13 @@ export class LoadingExecutionBase extends LitElement {
|
|
|
973
1479
|
worksheetId: worksheetInfo.worksheet.id
|
|
974
1480
|
}
|
|
975
1481
|
|
|
976
|
-
|
|
1482
|
+
const worksheetDetailInfos = response.data.loadingWorksheetv2.worksheetDetailInfos
|
|
1483
|
+
// Check if any order inventory has refWorksheetId
|
|
1484
|
+
this._hasRefWorksheetId = worksheetDetailInfos.some(
|
|
1485
|
+
item => item?.relatedOrderInv?.refWorksheetId != null && item?.relatedOrderInv?.refWorksheetId !== ''
|
|
1486
|
+
)
|
|
1487
|
+
|
|
1488
|
+
return worksheetDetailInfos
|
|
977
1489
|
}
|
|
978
1490
|
}
|
|
979
1491
|
} catch (e) {
|