@things-factory/operato-wms 4.3.824 → 4.3.826

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 (33) hide show
  1. package/client/pages/adjustment/transfer-inventory.js +24 -64
  2. package/client/pages/components/select-product-popup.js +20 -0
  3. package/client/pages/constants/location.js +4 -0
  4. package/client/pages/master/location-list.js +140 -18
  5. package/client/pages/order/arrival-notice/create-arrival-notice.js +18 -0
  6. package/client/pages/order/draft-release-good/draft-release-good-list.js +1 -0
  7. package/config.development.js +71 -141
  8. package/dist-server/graphql/resolvers/index.js +2 -0
  9. package/dist-server/graphql/resolvers/index.js.map +1 -1
  10. package/dist-server/graphql/resolvers/transfer-location/check-transfer-location-recommendation.js +108 -0
  11. package/dist-server/graphql/resolvers/transfer-location/check-transfer-location-recommendation.js.map +1 -0
  12. package/dist-server/graphql/resolvers/transfer-location/index.js +7 -0
  13. package/dist-server/graphql/resolvers/transfer-location/index.js.map +1 -0
  14. package/dist-server/graphql/resolvers/zone-worksheet/zone-worksheet.js +2 -13
  15. package/dist-server/graphql/resolvers/zone-worksheet/zone-worksheet.js.map +1 -1
  16. package/dist-server/graphql/types/index.js +3 -0
  17. package/dist-server/graphql/types/index.js.map +1 -1
  18. package/dist-server/graphql/types/transfer-location/index.js +14 -0
  19. package/dist-server/graphql/types/transfer-location/index.js.map +1 -0
  20. package/dist-server/graphql/types/transfer-location/transfer-location-recommendation.js +13 -0
  21. package/dist-server/graphql/types/transfer-location/transfer-location-recommendation.js.map +1 -0
  22. package/package.json +5 -5
  23. package/server/graphql/resolvers/index.ts +2 -0
  24. package/server/graphql/resolvers/transfer-location/check-transfer-location-recommendation.ts +123 -0
  25. package/server/graphql/resolvers/transfer-location/index.ts +7 -0
  26. package/server/graphql/resolvers/zone-worksheet/zone-worksheet.ts +3 -14
  27. package/server/graphql/types/index.ts +3 -0
  28. package/server/graphql/types/transfer-location/index.ts +13 -0
  29. package/server/graphql/types/transfer-location/transfer-location-recommendation.ts +7 -0
  30. package/translations/en.json +12 -0
  31. package/translations/ko.json +12 -0
  32. package/translations/ms.json +12 -0
  33. package/translations/zh.json +12 -0
@@ -0,0 +1,123 @@
1
+ import { EntityManager } from 'typeorm'
2
+
3
+ import { Setting } from '@things-factory/setting-base'
4
+ import { Domain } from '@things-factory/shell'
5
+ import { Inventory, Location, INVENTORY_STATUS, LOCATION_STATUS, calcVolumeInM3, buildProductDetailLabel } from '@things-factory/warehouse-base'
6
+
7
+ export const checkTransferLocationRecommendation = {
8
+ async checkTransferLocationRecommendation(
9
+ _: any,
10
+ { originPalletId, toLocationName, qty }: { originPalletId: string; toLocationName: string; qty: number },
11
+ context: any
12
+ ): Promise<{ warningMessage: string | null }> {
13
+ const { domain, tx }: { domain: Domain; tx: EntityManager } = context.state
14
+
15
+ const levelSetting: Setting = await tx
16
+ .getRepository(Setting)
17
+ .findOne({ where: { domain, name: 'location-recommendation-level' } })
18
+
19
+ const level = levelSetting?.value?.toUpperCase().trim()
20
+ if (!level) return { warningMessage: null }
21
+
22
+ const inventory: Inventory = await tx
23
+ .getRepository(Inventory)
24
+ .createQueryBuilder('inv')
25
+ .innerJoinAndSelect('inv.product', 'product')
26
+ .leftJoinAndSelect('inv.productDetail', 'productDetail')
27
+ .where('inv.domain_id = :domainId', { domainId: domain.id })
28
+ .andWhere('inv.pallet_id = :palletId', { palletId: originPalletId })
29
+ .getOne()
30
+ if (!inventory) return { warningMessage: null } // Return silently. Actual transfer location process will only prompt error
31
+
32
+ const toLocation: Location = await tx.getRepository(Location).findOne({ where: { domain, name: toLocationName } })
33
+ if (!toLocation) return { warningMessage: null } // Return silently. Actual transfer location process will only prompt error
34
+
35
+ const inventoriesAtLocation: Inventory[] = await tx
36
+ .getRepository(Inventory)
37
+ .createQueryBuilder('inv')
38
+ .innerJoinAndSelect('inv.product', 'product')
39
+ .leftJoinAndSelect('inv.productDetail', 'productDetail')
40
+ .where('inv.domain_id = :domainId', { domainId: domain.id })
41
+ .andWhere('inv.location_id = :locationId', { locationId: toLocation.id })
42
+ .andWhere('inv.status = :status', { status: INVENTORY_STATUS.STORED })
43
+ .getMany()
44
+
45
+ switch (level) {
46
+ case 'LEVEL 1': {
47
+ if (toLocation.status?.toUpperCase() !== LOCATION_STATUS.EMPTY) {
48
+ return { warningMessage: 'reminder_location_assigned_to_another_sku' }
49
+ }
50
+ break
51
+ }
52
+
53
+ case 'LEVEL 2': {
54
+ const fromSku = inventory.product?.sku
55
+ const hasDifferentSku = inventoriesAtLocation.some(inv => inv.product?.sku !== fromSku)
56
+ if (hasDifferentSku) {
57
+ return { warningMessage: 'reminder_location_assigned_to_another_sku' }
58
+ }
59
+ break
60
+ }
61
+
62
+ case 'LEVEL 3': {
63
+ const fromSku = inventory.product?.sku
64
+ const hasDifferentSku = inventoriesAtLocation.some(inv => inv.product?.sku !== fromSku)
65
+
66
+ const stackingSetting: Setting = await tx.getRepository(Setting).findOne({ where: { domain, name: 'stacking-option-limit' } })
67
+
68
+ let maxLimit = 1
69
+ if (stackingSetting?.value) {
70
+ try {
71
+ const parsed = JSON.parse(stackingSetting.value)
72
+ maxLimit = Number(parsed.Max) || 1
73
+ } catch {
74
+ // ignore malformed setting
75
+ }
76
+ }
77
+
78
+ const stackingLimit = inventory.product?.allowStackingOption ? maxLimit : null
79
+ const hitStackingLimit = stackingLimit != null && inventoriesAtLocation.length >= stackingLimit
80
+
81
+ if (hasDifferentSku || hitStackingLimit) {
82
+ return { warningMessage: 'reminder_location_occupied_by_different_sku_or_stacking_capacity' }
83
+ }
84
+ break
85
+ }
86
+
87
+ case 'LEVEL 4': {
88
+ if (!toLocation.volume) return { warningMessage: 'location_missing_volume' }
89
+
90
+ // Check selected inventory's product
91
+ const incomingPd = inventory.productDetail
92
+ const incomingInvalid =
93
+ !incomingPd?.lengthUnit ||
94
+ (incomingPd?.volume == null && (!incomingPd?.width || !incomingPd?.depth || !incomingPd?.height))
95
+ if (incomingInvalid) return { warningMessage: 'incoming_inventory_missing_product_dimensions' }
96
+
97
+ // Check products stored in the targeted destination location
98
+ const existingInvalid = inventoriesAtLocation.some(inv => {
99
+ const pd = inv.productDetail
100
+ return !pd?.lengthUnit || (pd?.volume == null && (!pd?.width || !pd?.depth || !pd?.height))
101
+ })
102
+ if (existingInvalid) return { warningMessage: 'existing_inventory_missing_product_dimensions' }
103
+
104
+
105
+ const locationVolume = toLocation.volume
106
+ const existingVolume = inventoriesAtLocation.reduce((sum, inv) => {
107
+ const pd = inv.productDetail
108
+ const detail = buildProductDetailLabel(pd)
109
+ const label = `SKU: ${inv.product?.sku} ${detail}`.trim()
110
+ return sum + calcVolumeInM3(pd, label) * (inv.qty ?? 0)
111
+ }, 0)
112
+
113
+ const incomingDetail = buildProductDetailLabel(incomingPd)
114
+ const incomingLabel = `SKU: ${inventory.product?.sku} ${incomingDetail}`.trim()
115
+ if (existingVolume + calcVolumeInM3(incomingPd, incomingLabel) * qty > locationVolume) return { warningMessage: 'volume_over_location_capacity' }
116
+ break
117
+ }
118
+ }
119
+
120
+ return { warningMessage: null }
121
+ }
122
+ }
123
+
@@ -0,0 +1,7 @@
1
+ import { checkTransferLocationRecommendation } from './check-transfer-location-recommendation'
2
+
3
+ export const Query = {
4
+ ...checkTransferLocationRecommendation
5
+ }
6
+
7
+ export const Mutation = {}
@@ -75,16 +75,6 @@ export const zonePickingWorksheet = {
75
75
  where: { worksheet }
76
76
  })
77
77
 
78
- // Lightweight pre-pass: only the columns needed to compute invIds, roIds, and
79
- // isCompletable. Avoids running the heavy joined SELECT (product/inventory/
80
- // location/productDetail/...) twice — the second, filtered getMany() below
81
- // produces the rows actually returned to the client.
82
- const orderInventories: OrderInventory[] = await getRepository(OrderInventory)
83
- .createQueryBuilder('oi')
84
- .select(['oi.id', 'oi.inventoryId', 'oi.releaseGoodId', 'oi.status'])
85
- .where('oi.ref_worksheet_id = :worksheetId', { worksheetId: worksheet.id })
86
- .getMany()
87
-
88
78
  //fetch order inventories
89
79
  let qb = getRepository(OrderInventory)
90
80
  .createQueryBuilder('oi')
@@ -97,6 +87,9 @@ export const zonePickingWorksheet = {
97
87
  .leftJoinAndSelect('pd.parentProductDetails', 'ppd')
98
88
  .where('ref_worksheet_id = :worksheetId', { worksheetId: worksheet.id })
99
89
 
90
+ //get all oi to find inventory changes and determine if the worksheet is completable
91
+ const orderInventories: OrderInventory[] = await qb.getMany()
92
+
100
93
  //item assigned to obsolete inventories will not be displayed during picking
101
94
  if (filter) {
102
95
  qb.andWhere('rg.status != :orderStatus', { orderStatus: ORDER_STATUS.OBSOLETE })
@@ -181,10 +174,6 @@ export const zonePickingWorksheet = {
181
174
  }
182
175
 
183
176
  function isCompletable(oi: OrderInventory[], ic: InventoryChange[]): String {
184
- // NOTE: callers may pass a partial OrderInventory with only id/inventoryId/
185
- // releaseGoodId/status populated (see the lightweight pre-pass in
186
- // zonePickingWorksheet). Don't reference other fields here without first
187
- // widening that SELECT.
188
177
  //find processing oi and check if there is any pending inventory adjustment
189
178
  let processingOi = oi.filter(item => item.status === ORDER_INVENTORY_STATUS.PROCESSING)
190
179
 
@@ -7,6 +7,7 @@ import * as OpaMenu from './opa-menu'
7
7
  import * as Reports from './reports'
8
8
  import * as InventoryComparison from './inventory-comparison'
9
9
  import * as ShippingProvider from './shipping-provider'
10
+ import * as TransferLocation from './transfer-location'
10
11
  import * as WarehouseInventory from './warehouse-inventory-adjustment'
11
12
  import * as RouteLabel from './route-label'
12
13
  import * as ZoneWorksheet from './zone-worksheet'
@@ -22,6 +23,7 @@ export const queries = [
22
23
  InventoryComparison.Query,
23
24
  ShippingProvider.Query,
24
25
  Other.Query,
26
+ TransferLocation.Query,
25
27
  RouteLabel.Query,
26
28
  ZoneWorksheet.Query,
27
29
  Outbound.Query
@@ -44,6 +46,7 @@ export const types = [
44
46
  ...InventoryComparison.Types,
45
47
  ...ShippingProvider.Types,
46
48
  ...Other.Types,
49
+ ...TransferLocation.Types,
47
50
  ...RouteLabel.Types,
48
51
  ...ZoneWorksheet.Types,
49
52
  ...Outbound.Types
@@ -0,0 +1,13 @@
1
+ import { TransferLocationRecommendationResult } from './transfer-location-recommendation'
2
+
3
+ export const Query = `
4
+ checkTransferLocationRecommendation(
5
+ originPalletId: String!
6
+ toLocationName: String!
7
+ qty: Float!
8
+ ): TransferLocationRecommendationResult @privilege(category: "inventory", privilege: "query") @transaction
9
+ `
10
+
11
+ export const Mutation = ``
12
+
13
+ export const Types = [TransferLocationRecommendationResult]
@@ -0,0 +1,7 @@
1
+ import gql from 'graphql-tag'
2
+
3
+ export const TransferLocationRecommendationResult = gql`
4
+ type TransferLocationRecommendationResult {
5
+ warningMessage: String
6
+ }
7
+ `
@@ -425,6 +425,9 @@
425
425
  "field.latest_execution_to_date": "latest execution to date",
426
426
  "field.latest_execution": "latest execution",
427
427
  "field.latlng": "latlng",
428
+ "field.length_m": "length (m)",
429
+ "field.width_m": "width (m)",
430
+ "field.height_m": "height (m)",
428
431
  "field.length_unit": "length unit",
429
432
  "field.level_end": "level end",
430
433
  "field.level_start": "level start",
@@ -814,6 +817,7 @@
814
817
  "field.vehicle_no": "vehicle no",
815
818
  "field.view": "view",
816
819
  "field.volume_m3": "volume (M3)",
820
+ "field.class": "Class",
817
821
  "field.volume_size": "volume size",
818
822
  "field.volume": "volume",
819
823
  "field.w/h": "W/H",
@@ -1566,6 +1570,9 @@
1566
1570
  "text.goods_received_note_has_been_sent_successfully": "GRN has been sent successfully",
1567
1571
  "text.group_quantity_cannot_be_negative": "group quantity cannot be negative",
1568
1572
  "text.group_quantity_cannot_be_zero": "group quantity cannot be zero",
1573
+ "text.value_must_be_greater_than_zero": "value must be greater than 0",
1574
+ "text.cannot_update_class_for_quarantine_or_damage_location": "Class is not supported for Quarantine and Damage location types. Please select a different location type.",
1575
+ "text.missing_product_dimensions_for_level_4": "Some products are missing dimensions. Please provide width, depth, height (or volume) and length unit in the product master. You may still proceed to create GAN.",
1569
1576
  "text.group_quantity_exceeds_total": "group quantity cannot exceed total quantity",
1570
1577
  "text.holder_field_is_empty": "holder field is empty",
1571
1578
  "text.inbound": "inbound",
@@ -1974,6 +1981,11 @@
1974
1981
  "text.tracking_no_duplicated": "tracking no duplicated",
1975
1982
  "text.reminder_location_assigned_to_another_sku": "This location is already assigned to another SKU.",
1976
1983
  "text.reminder_location_occupied_by_different_sku_or_stacking_capacity": "This location is occupied by a different SKU or has reached its stacking capacity.",
1984
+ "text.location_missing_volume": "To location does not have a volume set. Please update the Location Master.",
1985
+ "text.existing_inventory_missing_product_dimensions": "Inventory at the destination location is missing product dimensions or length unit. Please update the product details.",
1986
+ "text.incoming_inventory_missing_product_dimensions": "The selected inventory is missing product dimensions or length unit. Please update the product details.",
1987
+ "text.volume_over_location_capacity": "Reminder: The volume for this inventory is over the Location Volume",
1988
+ "text.may_proceed_without_level_4_recommendation": "You may still proceed without level 4 recommendation checking",
1977
1989
  "text.transfer_inventory_to_different_location": "transfer inventory to different location",
1978
1990
  "text.transfer_location_completed": "transfer location completed",
1979
1991
  "text.transfer_qty_cannot_exceed_3_decimal_places": "Transfer qty cannot exceed 3 decimal places",
@@ -426,6 +426,9 @@
426
426
  "field.label_id_for_location": "로케이션 라벨 아이디",
427
427
  "field.label_id_for_pallet": "파레트 라벨 아이디",
428
428
  "field.latlng": "위경도",
429
+ "field.length_m": "길이 (m)",
430
+ "field.width_m": "너비 (m)",
431
+ "field.height_m": "높이 (m)",
429
432
  "field.length_unit": "길이 단위",
430
433
  "field.level_end": "level end",
431
434
  "field.level_start": "level start",
@@ -794,6 +797,7 @@
794
797
  "field.view": "보기",
795
798
  "field.volume": "볼륨",
796
799
  "field.volume_m3": "[ko] volume (M3)",
800
+ "field.class": "클래스",
797
801
  "field.volume_size": "[ko]volume size",
798
802
  "field.w/h": "창고",
799
803
  "field.warehouse_name": "창고명",
@@ -1529,6 +1533,9 @@
1529
1533
  "text.goods_received_note_uploaded": "text.goods_received_note_uploaded",
1530
1534
  "text.group_quantity_cannot_be_negative": "그룹 수량은 음수가 될 수 없습니다",
1531
1535
  "text.group_quantity_cannot_be_zero": "그룹 수량은 0이 될 수 없습니다",
1536
+ "text.value_must_be_greater_than_zero": "값은 0보다 커야 합니다",
1537
+ "text.cannot_update_class_for_quarantine_or_damage_location": "클래스는 검역 및 손상 위치 유형에 지원되지 않습니다. 다른 위치 유형을 선택하세요.",
1538
+ "text.missing_product_dimensions_for_level_4": "일부 제품의 치수가 누락되었습니다. 제품 마스터에서 너비, 깊이, 높이(또는 부피)와 길이 단위를 입력해 주세요. GAN 생성을 계속 진행할 수 있습니다.",
1532
1539
  "text.group_quantity_exceeds_total": "그룹 수량이 총 수량을 초과할 수 없습니다",
1533
1540
  "text.holder_field_is_empty": "[ko] holder field is empty",
1534
1541
  "text.inbound": "[ko]inbound",
@@ -1953,6 +1960,11 @@
1953
1960
  "text.tracking_no_deleted": "[ko] tracking no deleted",
1954
1961
  "text.reminder_location_assigned_to_another_sku": "이 위치는 이미 다른 SKU에 할당되어 있습니다.",
1955
1962
  "text.reminder_location_occupied_by_different_sku_or_stacking_capacity": "이 위치는 다른 SKU가 점유하고 있거나 적재 용량에 도달했습니다.",
1963
+ "text.location_missing_volume": "이동할 위치에 부피가 설정되어 있지 않습니다. 위치 마스터를 업데이트하세요.",
1964
+ "text.existing_inventory_missing_product_dimensions": "목적지 위치에 이미 보관된 재고 중 제품 치수 또는 길이 단위가 없는 항목이 있습니다. 제품 세부 정보를 업데이트하세요.",
1965
+ "text.incoming_inventory_missing_product_dimensions": "선택된 재고에 제품 치수 또는 길이 단위가 없습니다. 제품 세부 정보를 업데이트하세요.",
1966
+ "text.volume_over_location_capacity": "알림: 이 재고의 부피가 위치 부피를 초과합니다",
1967
+ "text.may_proceed_without_level_4_recommendation": "레벨 4 추천 검사 없이 진행할 수 있습니다",
1956
1968
  "text.transfer_inventory_to_different_location": "[ko] transfer inventory to different location",
1957
1969
  "text.transfer_location_completed": "이동 완료",
1958
1970
  "text.transfer_quantity_cannot_be_uploaded_as_it_does_not_meet_the_minimum_required_quantity": "[ko] transfer quantity cannot be uploaded as it does not meet the minimum required quantity",
@@ -445,6 +445,9 @@
445
445
  "field.latest_execution_from_date": "pengendalian terakhir dari tarikh",
446
446
  "field.latest_execution_to_date": "pengendalian terakhir hingga tarikh",
447
447
  "field.latlng": "latlng",
448
+ "field.length_m": "panjang (m)",
449
+ "field.width_m": "lebar (m)",
450
+ "field.height_m": "tinggi (m)",
448
451
  "field.length_unit": "unit panjang",
449
452
  "field.level_end": "pengakhiran peringkat",
450
453
  "field.level_start": "permulaan peringkat",
@@ -837,6 +840,7 @@
837
840
  "field.view": "paparan",
838
841
  "field.volume": "volume",
839
842
  "field.volume_m3": "volume (M3)",
843
+ "field.class": "Kelas",
840
844
  "field.volume_size": "saiz volume",
841
845
  "field.w/h": "W/H",
842
846
  "field.warehouse": "gudang",
@@ -1577,6 +1581,9 @@
1577
1581
  "text.goods_received_note_has_been_sent_successfully": "GRN berjaya dihantar",
1578
1582
  "text.group_quantity_cannot_be_negative": "kuantiti kumpulan tidak boleh negatif",
1579
1583
  "text.group_quantity_cannot_be_zero": "kuantiti kumpulan tidak boleh sifar",
1584
+ "text.value_must_be_greater_than_zero": "value mesti lebih daripada 0",
1585
+ "text.cannot_update_class_for_quarantine_or_damage_location": "Kelas tidak disokong untuk jenis lokasi Kuarantin dan Rosak. Sila pilih jenis lokasi yang lain.",
1586
+ "text.missing_product_dimensions_for_level_4": "Sesetengah produk tiada dimensi. Sila masukkan lebar, kedalaman, tinggi (atau isipadu) dan unit panjang dalam rekod induk produk. Anda masih boleh teruskan untuk mencipta GAN.",
1580
1587
  "text.group_quantity_exceeds_total": "kuantiti kumpulan tidak boleh melebihi jumlah keseluruhan",
1581
1588
  "text.holder_field_is_empty": "ruangan pemilik kosong",
1582
1589
  "text.inbound": "masuk",
@@ -2006,6 +2013,11 @@
2006
2013
  "text.tracking_no_duplicated": "no. penjejak duplikat",
2007
2014
  "text.reminder_location_assigned_to_another_sku": "Lokasi ini sudah ditetapkan kepada SKU lain.",
2008
2015
  "text.reminder_location_occupied_by_different_sku_or_stacking_capacity": "Lokasi ini diduduki oleh SKU yang berbeza atau telah mencapai kapasiti susunan.",
2016
+ "text.location_missing_volume": "Lokasi destinasi tidak mempunyai isipadu yang ditetapkan. Sila kemaskini Lokasi Master.",
2017
+ "text.existing_inventory_missing_product_dimensions": "Inventori di lokasi destinasi tiada dimensi produk atau unit panjang. Sila kemaskini butiran produk.",
2018
+ "text.incoming_inventory_missing_product_dimensions": "Inventori terpilih tiada dimensi produk atau unit panjang. Sila kemaskini butiran produk.",
2019
+ "text.volume_over_location_capacity": "Peringatan: Isipadu inventori ini melebihi isipadu lokasi",
2020
+ "text.may_proceed_without_level_4_recommendation": "Anda masih boleh meneruskan tanpa semakan cadangan tahap 4",
2009
2021
  "text.transfer_inventory_to_different_location": "transfer inventori ke lokasi berlainan",
2010
2022
  "text.transfer_location_completed": "transfer lokasi telah selesai",
2011
2023
  "text.transfer_qty_cannot_exceed_3_decimal_places": "kuantiti transfer tidak boleh melebihi 3 tempat perpuluhan",
@@ -445,6 +445,9 @@
445
445
  "field.latest_execution_from_date": "最新执行从日期",
446
446
  "field.latest_execution_to_date": "最新执行到日期",
447
447
  "field.latlng": "经纬度",
448
+ "field.length_m": "长度 (m)",
449
+ "field.width_m": "宽度 (m)",
450
+ "field.height_m": "高度 (m)",
448
451
  "field.length_unit": "长度单位",
449
452
  "field.level_end": "层级结束",
450
453
  "field.level_start": "层级开始",
@@ -842,6 +845,7 @@
842
845
  "field.view": "视图",
843
846
  "field.volume": "体积",
844
847
  "field.volume_m3": "体积 (M3)",
848
+ "field.class": "分类",
845
849
  "field.volume_size": "体积大小",
846
850
  "field.w/h": "W/H",
847
851
  "field.warehouse": "仓库",
@@ -1603,6 +1607,9 @@
1603
1607
  "text.goods_received_note_has_been_sent_successfully": "GRN已发送成功",
1604
1608
  "text.group_quantity_cannot_be_negative": "分组数量不能为负数",
1605
1609
  "text.group_quantity_cannot_be_zero": "分组数量不能为零",
1610
+ "text.value_must_be_greater_than_zero": "值必须大于0",
1611
+ "text.cannot_update_class_for_quarantine_or_damage_location": "隔离和损坏位置类型不支持分类。请选择其他位置类型。",
1612
+ "text.missing_product_dimensions_for_level_4": "部分产品缺少尺寸信息。请在产品主数据中提供宽度、深度、高度(或体积)及长度单位。您仍可继续创建GAN。",
1606
1613
  "text.group_quantity_exceeds_total": "分组数量不能超过总数量",
1607
1614
  "text.holder_field_is_empty": "持有人字段为空",
1608
1615
  "text.inbound": "入库",
@@ -2039,6 +2046,11 @@
2039
2046
  "text.tracking_no_duplicated": "跟踪号已重复",
2040
2047
  "text.reminder_location_assigned_to_another_sku": "此位置已分配给另一个SKU。",
2041
2048
  "text.reminder_location_occupied_by_different_sku_or_stacking_capacity": "此位置已被不同SKU占用或已达到堆叠容量。",
2049
+ "text.location_missing_volume": "目标位置未设置体积。请更新位置主数据。",
2050
+ "text.existing_inventory_missing_product_dimensions": "目标位置已存放的库存中存在缺少产品尺寸或长度单位的记录。请更新产品详情。",
2051
+ "text.incoming_inventory_missing_product_dimensions": "所选待转移库存缺少产品尺寸或长度单位。请更新产品详情。",
2052
+ "text.volume_over_location_capacity": "提醒:此库存的体积超过了库位体积",
2053
+ "text.may_proceed_without_level_4_recommendation": "您仍可在不进行第4级推荐检查的情况下继续操作",
2042
2054
  "text.transfer_inventory_to_different_location": "转移库存到不同位置",
2043
2055
  "text.transfer_location_completed": "转移位置已完成",
2044
2056
  "text.transfer_qty_cannot_exceed_3_decimal_places": "转移数量不能超过3个小数位",