@things-factory/operato-wms 4.3.795 → 4.3.798
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/components/worksheet-information-popup.js +60 -8
- package/client/pages/constants/order.js +7 -1
- package/client/pages/order/release-order/b2b/b2b-order-list.js +17 -1
- package/client/pages/order/release-order/release-order-detail.js +19 -0
- package/client/pages/order/transport-order/print-delivery-note.js +19 -1
- package/client/pages/outbound/loading-v2/load-by-qty.js +10 -0
- package/client/pages/outbound/loading-v2/loading-execution-base.js +22 -8
- package/client/pages/outbound/loading-v2/loading-execution.js +37 -8
- package/client/pages/outbound/loading-v2/loading.js +6 -0
- package/client/pages/outbound/loading-v2/release-good-info.js +3 -0
- package/client/pages/outbound/picking-product.js +138 -17
- package/client/pages/outbound/picking-same-carton-popup.js +217 -0
- package/client/pages/outbound/picking-v2/picking-execution-base.js +20 -2
- package/client/pages/outbound/picking-v2/picking-execution.js +4 -3
- package/client/pages/outbound/picking-v2/picking.js +3 -0
- package/client/pages/outbound/single-outbound-worksheet.js +18 -1
- package/client/pages/outbound/sorting-product.js +24 -1
- package/client/pages/outbound/worksheet-zone-picking.js +1 -0
- package/dist-server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.js +9 -4
- package/dist-server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.js.map +1 -1
- package/dist-server/graphql/resolvers/outbound/load-by-qty.js +1 -1
- package/dist-server/graphql/resolvers/outbound/load-by-qty.js.map +1 -1
- package/dist-server/graphql/resolvers/outbound/loading-worksheet-v2.js +5 -1
- package/dist-server/graphql/resolvers/outbound/loading-worksheet-v2.js.map +1 -1
- package/dist-server/graphql/resolvers/zone-worksheet/zone-worksheet.js +8 -2
- package/dist-server/graphql/resolvers/zone-worksheet/zone-worksheet.js.map +1 -1
- package/package.json +8 -8
- package/server/graphql/resolvers/outbound/find-loadable-release-good-by-bin.ts +7 -1
- package/server/graphql/resolvers/outbound/load-by-qty.ts +1 -1
- package/server/graphql/resolvers/outbound/loading-worksheet-v2.ts +9 -2
- package/server/graphql/resolvers/zone-worksheet/zone-worksheet.ts +32 -23
- package/translations/en.json +2 -0
- package/translations/ko.json +2 -0
- package/translations/ms.json +2 -0
- package/translations/zh.json +2 -0
|
@@ -7,6 +7,7 @@ import '../components/worksheet-information-popup'
|
|
|
7
7
|
import './serial-number-popup'
|
|
8
8
|
import './tote-popup'
|
|
9
9
|
import './vas-list-popup'
|
|
10
|
+
import './picking-same-carton-popup'
|
|
10
11
|
|
|
11
12
|
import gql from 'graphql-tag'
|
|
12
13
|
import { css, html } from 'lit-element'
|
|
@@ -580,7 +581,7 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
580
581
|
settings: {
|
|
581
582
|
name: 'name',
|
|
582
583
|
operator: 'in',
|
|
583
|
-
value: ['enable-bin-picking', 'camera-scan-only', 'enable-picking-random-seq', 'disable-missing-button']
|
|
584
|
+
value: ['enable-bin-picking', 'camera-scan-only', 'enable-picking-random-seq', 'disable-missing-button', 'display-conversion']
|
|
584
585
|
}
|
|
585
586
|
})
|
|
586
587
|
|
|
@@ -590,6 +591,7 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
590
591
|
let cameraScanOnly = settingsMap.get('camera-scan-only') === 'true'
|
|
591
592
|
let enablePickingRandomSeq = settingsMap.get('enable-picking-random-seq') === 'true'
|
|
592
593
|
let disableMissingButton = settingsMap.get('disable-missing-button') === 'true'
|
|
594
|
+
let displayConversion = settingsMap.get('display-conversion') === 'true'
|
|
593
595
|
|
|
594
596
|
const locationSortingTask = fetchLocationSortingRule(LOCATION_SORTING_RULE.PICKING_PRODUCT.value)
|
|
595
597
|
|
|
@@ -725,6 +727,14 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
725
727
|
label: true,
|
|
726
728
|
width: 140
|
|
727
729
|
},
|
|
730
|
+
{
|
|
731
|
+
type: 'string',
|
|
732
|
+
name: 'conversion',
|
|
733
|
+
header: i18next.t('field.pack_conversion'),
|
|
734
|
+
label: true,
|
|
735
|
+
hidden: !displayConversion,
|
|
736
|
+
width: 140
|
|
737
|
+
},
|
|
728
738
|
{
|
|
729
739
|
type: 'string',
|
|
730
740
|
name: 'releaseProgress',
|
|
@@ -749,7 +759,8 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
749
759
|
this._pageSettings = {
|
|
750
760
|
...this._pageSettings,
|
|
751
761
|
enablePickingRandomSeq: (await enablePickingRandomSeq) || false,
|
|
752
|
-
cameraScanOnly: (await cameraScanOnly) || false
|
|
762
|
+
cameraScanOnly: (await cameraScanOnly) || false,
|
|
763
|
+
displayConversion: (await displayConversion) || false
|
|
753
764
|
}
|
|
754
765
|
}
|
|
755
766
|
|
|
@@ -1311,14 +1322,27 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
1311
1322
|
const scannedCartonId = this.cartonInput.value.trim()
|
|
1312
1323
|
if (scannedCartonId) {
|
|
1313
1324
|
let candidates = (this.data?.records || []).filter(
|
|
1314
|
-
rec =>
|
|
1325
|
+
rec =>
|
|
1326
|
+
rec.cartonId === scannedCartonId &&
|
|
1327
|
+
rec.status !== 'DONE' &&
|
|
1328
|
+
rec.status !== 'MISSING' &&
|
|
1329
|
+
!rec.completed &&
|
|
1330
|
+
rec.pickedQty < rec.releaseQty
|
|
1315
1331
|
)
|
|
1316
|
-
candidates = this._filterCandidatesByInputQty(candidates)
|
|
1317
|
-
|
|
1318
1332
|
// Validate carton id: must have at least one candidate
|
|
1319
1333
|
if (!candidates || candidates.length === 0) {
|
|
1320
1334
|
this._focusOnCartonNoInput()
|
|
1321
|
-
|
|
1335
|
+
const hasFullyPickedForCarton = (this.data?.records || []).some(
|
|
1336
|
+
rec =>
|
|
1337
|
+
rec.cartonId === scannedCartonId &&
|
|
1338
|
+
rec.status !== 'DONE' &&
|
|
1339
|
+
rec.status !== 'MISSING' &&
|
|
1340
|
+
!rec.completed &&
|
|
1341
|
+
rec.pickedQty >= rec.releaseQty
|
|
1342
|
+
)
|
|
1343
|
+
throw new Error(
|
|
1344
|
+
i18next.t(hasFullyPickedForCarton ? 'text.qty_exceed_release_qty' : 'text.invalid_carton_id')
|
|
1345
|
+
)
|
|
1322
1346
|
}
|
|
1323
1347
|
|
|
1324
1348
|
if (this._enableProductScanning) {
|
|
@@ -1328,11 +1352,14 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
1328
1352
|
throw new Error(i18next.t('text.empty_product_barcode'))
|
|
1329
1353
|
}
|
|
1330
1354
|
|
|
1355
|
+
this._popupCancelled = false
|
|
1331
1356
|
const matchedRecord = await this._selectRecordByGtinFromCandidates(
|
|
1332
1357
|
this.productBarcodeInput.value.trim(),
|
|
1333
1358
|
candidates
|
|
1334
1359
|
)
|
|
1335
1360
|
|
|
1361
|
+
if (this._popupCancelled) return { value: false }
|
|
1362
|
+
|
|
1336
1363
|
if (!matchedRecord) {
|
|
1337
1364
|
this._focusOnProductBarcodeInput()
|
|
1338
1365
|
this.productBarcodeInput.value = ''
|
|
@@ -1345,7 +1372,7 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
1345
1372
|
}
|
|
1346
1373
|
} else {
|
|
1347
1374
|
// Product scanning disabled: pick a deterministic candidate
|
|
1348
|
-
const matchedRecord = this._pickBestCandidate(candidates)
|
|
1375
|
+
const matchedRecord = this._pickBestCandidate(this._filterCandidatesByInputQty(candidates))
|
|
1349
1376
|
if (
|
|
1350
1377
|
matchedRecord &&
|
|
1351
1378
|
(!this._selectedOrderInventory || this._selectedOrderInventory.name !== matchedRecord.name)
|
|
@@ -1409,14 +1436,36 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
1409
1436
|
if (this._pageSettings.enablePickingRandomSeq == true) {
|
|
1410
1437
|
let cartonInputValue = this.cartonInput.value
|
|
1411
1438
|
let candidates = this.data.records.filter(
|
|
1412
|
-
rec =>
|
|
1439
|
+
rec =>
|
|
1440
|
+
rec.cartonId === cartonInputValue &&
|
|
1441
|
+
rec.status !== 'DONE' &&
|
|
1442
|
+
rec.status !== 'MISSING' &&
|
|
1443
|
+
!rec.completed &&
|
|
1444
|
+
rec.pickedQty < rec.releaseQty
|
|
1413
1445
|
)
|
|
1414
|
-
candidates
|
|
1446
|
+
// If no candidates remain, check if it's because all matching items are already fully picked
|
|
1447
|
+
if (!candidates.length) {
|
|
1448
|
+
const hasFullyPickedForCarton = this.data.records.some(
|
|
1449
|
+
rec =>
|
|
1450
|
+
rec.cartonId === cartonInputValue &&
|
|
1451
|
+
rec.status !== 'DONE' &&
|
|
1452
|
+
rec.status !== 'MISSING' &&
|
|
1453
|
+
!rec.completed &&
|
|
1454
|
+
rec.pickedQty >= rec.releaseQty
|
|
1455
|
+
)
|
|
1456
|
+
if (hasFullyPickedForCarton) {
|
|
1457
|
+
this._focusOnCartonNoInput()
|
|
1458
|
+
throw new Error(i18next.t('text.qty_exceed_release_qty'))
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1415
1462
|
if (this._enableProductScanning && this.productBarcodeInput?.value) {
|
|
1463
|
+
this._popupCancelled = false
|
|
1416
1464
|
foundRecord = await this._selectRecordByGtinFromCandidates(
|
|
1417
1465
|
this.productBarcodeInput.value.trim(),
|
|
1418
1466
|
candidates
|
|
1419
1467
|
)
|
|
1468
|
+
if (this._popupCancelled) return { value: false }
|
|
1420
1469
|
}
|
|
1421
1470
|
// If product barcode is provided but no GTIN match, stop without fallback
|
|
1422
1471
|
if (this._enableProductScanning && this.productBarcodeInput?.value && !foundRecord) {
|
|
@@ -1427,7 +1476,7 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
1427
1476
|
|
|
1428
1477
|
// No product barcode: deterministically choose best candidate among duplicates
|
|
1429
1478
|
if (!foundRecord && (!this._enableProductScanning || !this.productBarcodeInput?.value)) {
|
|
1430
|
-
foundRecord = this._pickBestCandidate(candidates)
|
|
1479
|
+
foundRecord = this._pickBestCandidate(this._filterCandidatesByInputQty(candidates))
|
|
1431
1480
|
}
|
|
1432
1481
|
|
|
1433
1482
|
if (foundRecord) {
|
|
@@ -1683,6 +1732,7 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
1683
1732
|
recall
|
|
1684
1733
|
crossDocking
|
|
1685
1734
|
type
|
|
1735
|
+
rtm
|
|
1686
1736
|
}
|
|
1687
1737
|
replenishment {
|
|
1688
1738
|
id
|
|
@@ -1724,6 +1774,7 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
1724
1774
|
targetName
|
|
1725
1775
|
packingType
|
|
1726
1776
|
packingSize
|
|
1777
|
+
conversion
|
|
1727
1778
|
location {
|
|
1728
1779
|
name
|
|
1729
1780
|
description
|
|
@@ -1779,7 +1830,7 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
1779
1830
|
this._crossDocking = worksheetInfo.releaseGood?._crossDocking
|
|
1780
1831
|
this._bizplaceName = worksheetInfo?.bizplaceName
|
|
1781
1832
|
this._orderNo = this.releaseGoodNo
|
|
1782
|
-
this._worksheetInfo = worksheetInfo
|
|
1833
|
+
this._worksheetInfo = { ...worksheetInfo, rtm: worksheetInfo.releaseGood?.rtm }
|
|
1783
1834
|
let data = { records: this.formatWorksheetDetailInfos(worksheetDetailInfos) }
|
|
1784
1835
|
this.data = { ...data }
|
|
1785
1836
|
|
|
@@ -1871,6 +1922,14 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
1871
1922
|
partnerDomainId
|
|
1872
1923
|
customerCompanyDomainId
|
|
1873
1924
|
startedAt
|
|
1925
|
+
rtm
|
|
1926
|
+
refNo
|
|
1927
|
+
refNo2
|
|
1928
|
+
refNo3
|
|
1929
|
+
shippingProvider
|
|
1930
|
+
trackingNo
|
|
1931
|
+
marketplaceStatus
|
|
1932
|
+
containerNo
|
|
1874
1933
|
}
|
|
1875
1934
|
worksheetDetailInfos {
|
|
1876
1935
|
hasMissingInventoryChanges
|
|
@@ -1892,6 +1951,7 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
1892
1951
|
status
|
|
1893
1952
|
packingType
|
|
1894
1953
|
packingSize
|
|
1954
|
+
conversion
|
|
1895
1955
|
location {
|
|
1896
1956
|
name
|
|
1897
1957
|
}
|
|
@@ -2291,6 +2351,7 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
2291
2351
|
targetName
|
|
2292
2352
|
packingType
|
|
2293
2353
|
packingSize
|
|
2354
|
+
conversion
|
|
2294
2355
|
location {
|
|
2295
2356
|
name
|
|
2296
2357
|
description
|
|
@@ -2486,7 +2547,9 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
2486
2547
|
_filterCandidatesByInputQty(candidates) {
|
|
2487
2548
|
const typedQty = this._getTypedQty()
|
|
2488
2549
|
if (!typedQty || !Array.isArray(candidates) || !candidates.length) return candidates
|
|
2489
|
-
const matches = candidates.filter(
|
|
2550
|
+
const matches = candidates.filter(
|
|
2551
|
+
rec => (parseFloat(rec?.releaseQty) - parseFloat(rec?.pickedQty ?? 0)) === typedQty
|
|
2552
|
+
)
|
|
2490
2553
|
return matches.length ? matches : candidates
|
|
2491
2554
|
}
|
|
2492
2555
|
|
|
@@ -2521,9 +2584,6 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
2521
2584
|
try {
|
|
2522
2585
|
if (!gtin || !candidates?.length) return null
|
|
2523
2586
|
|
|
2524
|
-
// Apply qty-based narrowing first when duplicates exist
|
|
2525
|
-
candidates = this._filterCandidatesByInputQty(candidates)
|
|
2526
|
-
|
|
2527
2587
|
// Use checkGtin to resolve product-packing info to match candidate rows
|
|
2528
2588
|
const response = await client.query({
|
|
2529
2589
|
query: gql`
|
|
@@ -2563,16 +2623,77 @@ class PickingProduct extends connect(store)(localize(i18next)(PageView)) {
|
|
|
2563
2623
|
itm.packingSize === rec.packingSize
|
|
2564
2624
|
)
|
|
2565
2625
|
)
|
|
2566
|
-
if (exactMatches.length) return this.
|
|
2626
|
+
if (exactMatches.length) return await this._pickBestCandidateOrShowPopup(exactMatches)
|
|
2567
2627
|
|
|
2568
2628
|
const productOnlyMatches = candidates.filter(rec => items.some(itm => itm.product?.id === rec?.product?.id))
|
|
2569
|
-
if (productOnlyMatches.length) return this.
|
|
2629
|
+
if (productOnlyMatches.length) return await this._pickBestCandidateOrShowPopup(productOnlyMatches)
|
|
2570
2630
|
|
|
2571
2631
|
return null
|
|
2572
2632
|
} catch (e) {
|
|
2573
2633
|
return null
|
|
2574
2634
|
}
|
|
2575
2635
|
}
|
|
2636
|
+
|
|
2637
|
+
_hasDuplicateSameProduct(candidates) {
|
|
2638
|
+
return this._getDuplicateSameProductRows(candidates).length > 0
|
|
2639
|
+
}
|
|
2640
|
+
|
|
2641
|
+
_getDuplicateSameProductRows(candidates) {
|
|
2642
|
+
if (!Array.isArray(candidates) || candidates.length <= 1) return []
|
|
2643
|
+
|
|
2644
|
+
// Group by cartonId + SKU, return only rows that belong to a duplicate group
|
|
2645
|
+
const groups = {}
|
|
2646
|
+
candidates.forEach(c => {
|
|
2647
|
+
const key = `${c?.cartonId || ''}|${c?.product?.sku || ''}`
|
|
2648
|
+
if (!groups[key]) groups[key] = []
|
|
2649
|
+
groups[key].push(c)
|
|
2650
|
+
})
|
|
2651
|
+
|
|
2652
|
+
const duplicateRows = []
|
|
2653
|
+
for (const rows of Object.values(groups)) {
|
|
2654
|
+
if (rows.length > 1) duplicateRows.push(...rows)
|
|
2655
|
+
}
|
|
2656
|
+
return duplicateRows
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2659
|
+
_showPickingSameCartonPopup(candidates) {
|
|
2660
|
+
return new Promise(resolve => {
|
|
2661
|
+
openPopup(
|
|
2662
|
+
html`
|
|
2663
|
+
<picking-same-carton-popup
|
|
2664
|
+
.pickingInventories="${candidates}"
|
|
2665
|
+
@selection="${e => {
|
|
2666
|
+
resolve(e.detail)
|
|
2667
|
+
}}"
|
|
2668
|
+
></picking-same-carton-popup>
|
|
2669
|
+
`,
|
|
2670
|
+
{
|
|
2671
|
+
backdrop: true,
|
|
2672
|
+
size: 'large',
|
|
2673
|
+
title: i18next.t('title.inventory_selection')
|
|
2674
|
+
}
|
|
2675
|
+
)
|
|
2676
|
+
})
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2679
|
+
async _pickBestCandidateOrShowPopup(candidates) {
|
|
2680
|
+
if (!Array.isArray(candidates) || !candidates.length) return null
|
|
2681
|
+
|
|
2682
|
+
// If multiple candidates have the same cartonId + SKU, show popup for user to choose
|
|
2683
|
+
const duplicateRows = this._getDuplicateSameProductRows(candidates)
|
|
2684
|
+
if (duplicateRows.length) {
|
|
2685
|
+
const selectedRecord = await this._showPickingSameCartonPopup(duplicateRows)
|
|
2686
|
+
if (!selectedRecord) {
|
|
2687
|
+
// User cancelled the popup — signal callers to do nothing
|
|
2688
|
+
this._popupCancelled = true
|
|
2689
|
+
return null
|
|
2690
|
+
}
|
|
2691
|
+
return selectedRecord
|
|
2692
|
+
}
|
|
2693
|
+
|
|
2694
|
+
// Otherwise, use the existing logic to pick the best candidate
|
|
2695
|
+
return this._pickBestCandidate(candidates)
|
|
2696
|
+
}
|
|
2576
2697
|
}
|
|
2577
2698
|
|
|
2578
2699
|
window.customElements.define('picking-product', PickingProduct)
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import '@things-factory/grist-ui'
|
|
2
|
+
|
|
3
|
+
import { css, html, LitElement } from 'lit-element'
|
|
4
|
+
import { connect } from 'pwa-helpers/connect-mixin'
|
|
5
|
+
|
|
6
|
+
import { SingleColumnFormStyles } from '@things-factory/form-ui'
|
|
7
|
+
import { i18next, localize } from '@things-factory/i18n-base'
|
|
8
|
+
import { store } from '@things-factory/shell'
|
|
9
|
+
import { isMobileDevice } from '@things-factory/utils'
|
|
10
|
+
|
|
11
|
+
class PickingSameCartonPopup extends connect(store)(localize(i18next)(LitElement)) {
|
|
12
|
+
static get properties() {
|
|
13
|
+
return {
|
|
14
|
+
config: Object,
|
|
15
|
+
data: Object,
|
|
16
|
+
pickingInventories: Array
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
constructor() {
|
|
21
|
+
super()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static get styles() {
|
|
25
|
+
return [
|
|
26
|
+
SingleColumnFormStyles,
|
|
27
|
+
css`
|
|
28
|
+
.button-container {
|
|
29
|
+
padding: 10px 0 12px 0;
|
|
30
|
+
text-align: center;
|
|
31
|
+
}
|
|
32
|
+
.button-container mwc-button {
|
|
33
|
+
margin: 0 5px;
|
|
34
|
+
}
|
|
35
|
+
data-grist {
|
|
36
|
+
overflow-y: hidden;
|
|
37
|
+
flex: 1;
|
|
38
|
+
}
|
|
39
|
+
.grist {
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
flex: 1;
|
|
43
|
+
overflow-y: auto;
|
|
44
|
+
}
|
|
45
|
+
:host {
|
|
46
|
+
padding: 10px;
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-direction: column;
|
|
49
|
+
overflow: hidden;
|
|
50
|
+
background-color: white;
|
|
51
|
+
}
|
|
52
|
+
.header {
|
|
53
|
+
padding: 10px;
|
|
54
|
+
font-weight: bold;
|
|
55
|
+
font-size: 14px;
|
|
56
|
+
color: var(--secondary-color);
|
|
57
|
+
border-bottom: 1px solid var(--secondary-color);
|
|
58
|
+
margin-bottom: 10px;
|
|
59
|
+
}
|
|
60
|
+
`
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
get dataGrist() {
|
|
65
|
+
return this.shadowRoot.querySelector('data-grist')
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
updated(changeProps) {
|
|
69
|
+
if (changeProps.has('pickingInventories')) {
|
|
70
|
+
if (this.pickingInventories && this.pickingInventories.length) {
|
|
71
|
+
this.data = {
|
|
72
|
+
records: this.pickingInventories.map(inv => ({
|
|
73
|
+
...inv,
|
|
74
|
+
locationName: inv.location?.name || ''
|
|
75
|
+
}))
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
render() {
|
|
82
|
+
return html`
|
|
83
|
+
<div class="header">
|
|
84
|
+
${i18next.t('text.please_select_an_inventory')}
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<div class="grist">
|
|
88
|
+
<data-grist
|
|
89
|
+
id="grist"
|
|
90
|
+
.mode=${isMobileDevice() ? 'LIST' : 'GRID'}
|
|
91
|
+
.config=${this.config}
|
|
92
|
+
.data="${this.data}"
|
|
93
|
+
></data-grist>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<div class="button-container">
|
|
97
|
+
<mwc-button
|
|
98
|
+
raised
|
|
99
|
+
@click="${this._selectPickingInventory.bind(this)}"
|
|
100
|
+
label="${i18next.t('button.select')}"
|
|
101
|
+
></mwc-button>
|
|
102
|
+
<mwc-button
|
|
103
|
+
@click="${() => {
|
|
104
|
+
this.dispatchEvent(new CustomEvent('selection', { detail: null }))
|
|
105
|
+
history.back()
|
|
106
|
+
}}"
|
|
107
|
+
label="${i18next.t('button.cancel')}"
|
|
108
|
+
></mwc-button>
|
|
109
|
+
</div>
|
|
110
|
+
`
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
firstUpdated() {
|
|
114
|
+
this.config = {
|
|
115
|
+
pagination: { infinite: true },
|
|
116
|
+
rows: { selectable: { multiple: false }, appendable: false },
|
|
117
|
+
list: {
|
|
118
|
+
fields: [
|
|
119
|
+
'locationName',
|
|
120
|
+
'palletId',
|
|
121
|
+
'batchId',
|
|
122
|
+
'batchIdRef',
|
|
123
|
+
'expirationDate',
|
|
124
|
+
'qty',
|
|
125
|
+
'releaseQty',
|
|
126
|
+
'packingType'
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
columns: [
|
|
130
|
+
{ type: 'gutter', gutterName: 'sequence' },
|
|
131
|
+
{ type: 'gutter', gutterName: 'row-selector', multiple: false, header: { renderer: () => '' } },
|
|
132
|
+
{ name: 'name', hidden: true },
|
|
133
|
+
{
|
|
134
|
+
type: 'string',
|
|
135
|
+
name: 'locationName',
|
|
136
|
+
label: true,
|
|
137
|
+
header: i18next.t('field.location'),
|
|
138
|
+
width: 120
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
type: 'string',
|
|
142
|
+
name: 'palletId',
|
|
143
|
+
label: true,
|
|
144
|
+
header: i18next.t('field.pallet_id'),
|
|
145
|
+
width: 120
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
type: 'string',
|
|
149
|
+
name: 'batchId',
|
|
150
|
+
label: true,
|
|
151
|
+
header: i18next.t('field.batch_no'),
|
|
152
|
+
width: 100
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
type: 'string',
|
|
156
|
+
name: 'batchIdRef',
|
|
157
|
+
label: true,
|
|
158
|
+
header: i18next.t('field.lot_id'),
|
|
159
|
+
width: 100
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
type: 'date',
|
|
163
|
+
name: 'expirationDate',
|
|
164
|
+
label: true,
|
|
165
|
+
header: i18next.t('field.expiration'),
|
|
166
|
+
width: 100
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
type: 'float',
|
|
170
|
+
name: 'qty',
|
|
171
|
+
label: true,
|
|
172
|
+
header: i18next.t('field.available_qty'),
|
|
173
|
+
width: 80
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
type: 'float',
|
|
177
|
+
name: 'releaseQty',
|
|
178
|
+
label: true,
|
|
179
|
+
header: i18next.t('field.release_qty'),
|
|
180
|
+
width: 80
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
type: 'string',
|
|
184
|
+
name: 'packingType',
|
|
185
|
+
label: true,
|
|
186
|
+
header: i18next.t('field.packing_type'),
|
|
187
|
+
width: 100
|
|
188
|
+
}
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async _selectPickingInventory() {
|
|
194
|
+
try {
|
|
195
|
+
const selectedInventory = this.dataGrist.selected[0]
|
|
196
|
+
if (!selectedInventory) throw new Error(i18next.t('text.please_select_inventory'))
|
|
197
|
+
|
|
198
|
+
this.dispatchEvent(new CustomEvent('selection', { detail: selectedInventory }))
|
|
199
|
+
history.back()
|
|
200
|
+
} catch (e) {
|
|
201
|
+
this._showToast(e)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
_showToast({ type, message }) {
|
|
206
|
+
document.dispatchEvent(
|
|
207
|
+
new CustomEvent('notify', {
|
|
208
|
+
detail: {
|
|
209
|
+
type,
|
|
210
|
+
message
|
|
211
|
+
}
|
|
212
|
+
})
|
|
213
|
+
)
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
window.customElements.define('picking-same-carton-popup', PickingSameCartonPopup)
|
|
@@ -12,7 +12,7 @@ import { openPopup } from '@things-factory/layout-base'
|
|
|
12
12
|
import { client, CustomAlert, gqlContext, PageView, store } from '@things-factory/shell'
|
|
13
13
|
import { CommonButtonStyles } from '@things-factory/styles'
|
|
14
14
|
|
|
15
|
-
import { showToast } from '../../../util'
|
|
15
|
+
import { fetchPageSettings, showToast } from '../../../util'
|
|
16
16
|
import { BATCH_PICKING, PICKING, ZONE_PICKING, ORDER_INVENTORY_STATUS } from '../../constants'
|
|
17
17
|
|
|
18
18
|
const PICKING_TYPES = { PICKING, BATCH_PICKING, ZONE_PICKING }
|
|
@@ -25,10 +25,26 @@ export class PickingExecutionBase extends LitElement {
|
|
|
25
25
|
data: Object,
|
|
26
26
|
pickingData: Object,
|
|
27
27
|
pickedData: Object,
|
|
28
|
-
_executionData: Object
|
|
28
|
+
_executionData: Object,
|
|
29
|
+
_displayConversion: Boolean
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
async connectedCallback() {
|
|
34
|
+
super.connectedCallback()
|
|
35
|
+
|
|
36
|
+
const pageSettings = await fetchPageSettings({
|
|
37
|
+
settings: {
|
|
38
|
+
name: 'name',
|
|
39
|
+
operator: 'in',
|
|
40
|
+
value: ['display-conversion']
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const settingsMap = new Map(pageSettings?.settings?.map(setting => [setting.name, setting.value]) || [])
|
|
45
|
+
this._displayConversion = settingsMap.get('display-conversion') === 'true'
|
|
46
|
+
}
|
|
47
|
+
|
|
32
48
|
get backButton() {
|
|
33
49
|
return {
|
|
34
50
|
title: i18next.t('button.back'),
|
|
@@ -392,6 +408,7 @@ export class PickingExecutionBase extends LitElement {
|
|
|
392
408
|
status
|
|
393
409
|
packingType
|
|
394
410
|
packingSize
|
|
411
|
+
conversion
|
|
395
412
|
}
|
|
396
413
|
inventoryChanges {
|
|
397
414
|
id
|
|
@@ -451,6 +468,7 @@ async function mapWorksheetData(data) {
|
|
|
451
468
|
status: orderInv.status,
|
|
452
469
|
packingType: orderInv.packingType,
|
|
453
470
|
packingSize: orderInv.packingSize,
|
|
471
|
+
conversion: orderInv.conversion,
|
|
454
472
|
location: {
|
|
455
473
|
name: orderInv.inventory.location.name,
|
|
456
474
|
description: orderInv.inventory.location.description
|
|
@@ -182,14 +182,15 @@ export class PickingExecution extends PickingExecutionBase {
|
|
|
182
182
|
field: 'product.name',
|
|
183
183
|
type: 'string',
|
|
184
184
|
style: '-webkit-line-clamp: 2;'
|
|
185
|
-
}
|
|
185
|
+
},
|
|
186
|
+
{ header: 'SKU', field: 'product.sku', type: 'string' }
|
|
186
187
|
]
|
|
187
188
|
},
|
|
188
189
|
{
|
|
189
190
|
type: 'row',
|
|
190
191
|
content: [
|
|
191
|
-
{ header: '
|
|
192
|
-
{ header: '
|
|
192
|
+
{ header: 'Packing Type', field: 'packingType', type: 'string' },
|
|
193
|
+
...(this._displayConversion ? [{ header: 'Pack Conversion', field: 'conversion', type: 'string' }] : [])
|
|
193
194
|
]
|
|
194
195
|
},
|
|
195
196
|
{
|
|
@@ -192,6 +192,7 @@ class PickingProductV2 extends connect(store)(localize(i18next)(PageView)) {
|
|
|
192
192
|
status
|
|
193
193
|
packingType
|
|
194
194
|
packingSize
|
|
195
|
+
conversion
|
|
195
196
|
}
|
|
196
197
|
inventoryChanges {
|
|
197
198
|
id
|
|
@@ -269,6 +270,7 @@ async function fetchWorksheet(worksheetNo, locationSortingRules) {
|
|
|
269
270
|
status
|
|
270
271
|
packingType
|
|
271
272
|
packingSize
|
|
273
|
+
conversion
|
|
272
274
|
}
|
|
273
275
|
inventoryChanges {
|
|
274
276
|
id
|
|
@@ -354,6 +356,7 @@ function mapWorksheetData(data) {
|
|
|
354
356
|
status: orderInv.status,
|
|
355
357
|
packingType: orderInv.packingType,
|
|
356
358
|
packingSize: orderInv.packingSize,
|
|
359
|
+
conversion: orderInv.conversion,
|
|
357
360
|
location: {
|
|
358
361
|
name: orderInv.inventory.location.name,
|
|
359
362
|
description: orderInv.inventory.location.description
|
|
@@ -14,7 +14,7 @@ import { CommonButtonStyles, ScrollbarStyles } from '@things-factory/styles'
|
|
|
14
14
|
import { isMobileDevice } from '@things-factory/utils'
|
|
15
15
|
|
|
16
16
|
import { fetchSettingRule } from '../../fetch-setting-value'
|
|
17
|
-
import { WORKSHEET_STATUS, WORKSHEET_TYPE } from '../constants'
|
|
17
|
+
import { RTM_OPTIONS, WORKSHEET_STATUS, WORKSHEET_TYPE } from '../constants'
|
|
18
18
|
|
|
19
19
|
import { applyParamsToFields } from '../../util'
|
|
20
20
|
|
|
@@ -237,6 +237,13 @@ class SingleOutboundWorksheet extends localize(i18next)(PageView) {
|
|
|
237
237
|
},
|
|
238
238
|
value: new Date().toISOString().split('T')[0]
|
|
239
239
|
},
|
|
240
|
+
{
|
|
241
|
+
label: i18next.t('field.rtm'),
|
|
242
|
+
name: 'releaseGoodRtm',
|
|
243
|
+
type: 'select',
|
|
244
|
+
options: [{ value: '' }, ...RTM_OPTIONS.map(option => ({ name: option.label, value: option.value }))],
|
|
245
|
+
props: { searchOper: 'eq' }
|
|
246
|
+
},
|
|
240
247
|
{
|
|
241
248
|
label: i18next.t('field.cross_docking'),
|
|
242
249
|
name: 'releaseGoodCrossDocking',
|
|
@@ -317,6 +324,14 @@ class SingleOutboundWorksheet extends localize(i18next)(PageView) {
|
|
|
317
324
|
sortable: true,
|
|
318
325
|
width: 180
|
|
319
326
|
},
|
|
327
|
+
{
|
|
328
|
+
type: 'string',
|
|
329
|
+
name: 'releaseGoodRtm',
|
|
330
|
+
header: i18next.t('field.rtm'),
|
|
331
|
+
imex: { header: i18next.t('field.rtm'), key: 'releaseGoodRtm', width: 40, type: 'string' },
|
|
332
|
+
sortable: true,
|
|
333
|
+
width: 120
|
|
334
|
+
},
|
|
320
335
|
{
|
|
321
336
|
type: 'boolean',
|
|
322
337
|
name: 'releaseGoodCrossDocking',
|
|
@@ -484,6 +499,7 @@ class SingleOutboundWorksheet extends localize(i18next)(PageView) {
|
|
|
484
499
|
name
|
|
485
500
|
description
|
|
486
501
|
refNo
|
|
502
|
+
rtm
|
|
487
503
|
crossDocking
|
|
488
504
|
courierOption
|
|
489
505
|
packingOption
|
|
@@ -533,6 +549,7 @@ class SingleOutboundWorksheet extends localize(i18next)(PageView) {
|
|
|
533
549
|
return {
|
|
534
550
|
...item,
|
|
535
551
|
releaseRefNo: item.releaseGood.refNo || '',
|
|
552
|
+
releaseGoodRtm: item.releaseGood.rtm || '',
|
|
536
553
|
releaseGoodCrossDocking: item.releaseGood.crossDocking,
|
|
537
554
|
releaseGoodCourierOption: item.releaseGood.courierOption,
|
|
538
555
|
releaseGoodPackingOption: item.releaseGood.packingOption,
|