Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
M
mini-wms
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Members
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
周海峰
mini-wms
Commits
4d2dea9b
Commit
4d2dea9b
authored
Dec 18, 2025
by
yubin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
导入无库存插入-库存 加导入手动标识 导入日志
parent
c5a19854
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
325 行增加
和
277 行删除
+325
-277
ruoyi-inventory/src/main/java/com/ruoyi/inventory/mapper/InventoryMapper.java
+1
-1
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/impl/OutboundOrdersServiceImpl.java
+164
-261
ruoyi-inventory/src/main/java/com/ruoyi/inventory/utils/InventoryCache.java
+160
-15
没有找到文件。
ruoyi-inventory/src/main/java/com/ruoyi/inventory/mapper/InventoryMapper.java
View file @
4d2dea9b
...
...
@@ -117,5 +117,5 @@ public interface InventoryMapper
public
List
<
java
.
util
.
Map
<
String
,
String
>>
selectInventoryTopTenByAmount
();
public
List
<
java
.
util
.
Map
<
String
,
String
>>
selectInventoryTopTenByQuantity
();
public
void
batchUpdateInventory
(
List
<
Inventory
>
inventoryList
);
public
int
batchUpdateInventory
(
List
<
Inventory
>
inventoryList
);
}
ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/impl/OutboundOrdersServiceImpl.java
View file @
4d2dea9b
...
...
@@ -21,8 +21,6 @@ import org.springframework.beans.BeanUtils;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.transaction.support.TransactionSynchronization
;
import
org.springframework.transaction.support.TransactionSynchronizationManager
;
import
org.springframework.util.CollectionUtils
;
import
java.util.*
;
...
...
@@ -31,11 +29,12 @@ import java.util.stream.Collectors;
/**
* 出库单主Service业务层处理
* 最终修复版:
* 1. 合并维度调整为「物料ID+库存类型+库位ID」,确保库位信息准确
* 2. 扣减时按该维度分组,统一收集记录后合并
* 3. 修复跨场景(无库位→有库位)扣减同一物料+库存类型的合并逻辑
* 4. 新增相同库存维度的明细合并逻辑,插入前合并为一条记录
* 最终适配版:
* 1. 合并维度「物料ID+库存类型+库位ID」,支持相同维度多库存ID遍历扣减
* 2. 库存加载改为按维度收集所有库存,扣减时按数量从多到少排序
* 3. 无库位明细拆分精准匹配实际扣减的库存ID+数量
* 4. 缓存与数据库实时同步,解决数据不一致问题
* 5. 合并/扣减/拆分逻辑完全对齐维度,杜绝数据错乱
*
* @author ruoyi
* @date 2025-12-03
...
...
@@ -101,7 +100,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
outboundOrders
.
setCreateTime
(
DateUtils
.
getNowDate
());
outboundOrders
.
setCreateUserCode
(
SystemUtils
.
getUserName
());
outboundOrders
.
setId
(
UUID
.
randomUUID
().
toString
());
outboundOrders
.
setIsImport
(
0
l
);
outboundOrders
.
setIsImport
(
0
L
);
int
rows
=
outboundOrdersMapper
.
insertOutboundOrders
(
outboundOrders
);
insertOutboundOrderItems
(
outboundOrders
);
...
...
@@ -117,7 +116,14 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
@Transactional
@Override
public
int
updateOutboundOrders
(
OutboundOrders
outboundOrders
)
{
throw
new
ServiceException
(
"当前系统仅支持新增出库单,不支持修改操作"
);
outboundOrdersMapper
.
deleteOutboundOrderItemsByOrderId
(
outboundOrders
.
getId
());
outboundOrderLogMapper
.
deleteOutboundOrderLogByOrdersId
(
outboundOrders
.
getId
());
outboundOrders
.
setUpdateUserCode
(
SystemUtils
.
getUserName
());
outboundOrders
.
setUpdateTime
(
DateUtils
.
getNowDate
());
insertOutboundOrderItems
(
outboundOrders
);
return
outboundOrdersMapper
.
updateOutboundOrders
(
outboundOrders
);
}
/**
...
...
@@ -176,19 +182,16 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
outboundOrders
.
setUpdateUserCode
(
updateUser
);
outboundOrdersMapper
.
updateOutboundOrders
(
outboundOrders
);
loadInventoryTOIdMap
();
// 3. 执行库存扣减(无库位不足时扣有库位)
this
.
deductInventory
(
outboundOrderItems
,
updateUser
,
updateTime
);
inventoryService
.
ship
(
outboundOrderItems
);
return
1
;
}
/**
* 核心库存扣减逻辑(最终修复版)
* 1. 扣减维度:物料ID+库存类型+库位ID(统一维度,跨场景合并)
* 2. 扣减时先按该维度分组,再累计扣减数量
* 3. 收集记录时按该维度统一收集,合并器仅做最终校验
* 核心库存扣减逻辑(最终适配版)
* 1. 扣减维度:物料ID+库存类型+库位ID
* 2. 相同维度多库存:按数量从多到少遍历扣减,支持全部扣完
* 3. 无库位→有库位:自动匹配所有可用库位库存,精准扣减
* 4. 扣减记录按单库存ID生成,支持后续明细精准拆分
*/
private
Map
<
String
,
List
<
Map
<
String
,
Object
>>>
deductInventory
(
List
<
OutboundOrderItems
>
outboundOrderItems
,
String
updateUser
,
Date
updateTime
)
{
if
(
CollectionUtils
.
isEmpty
(
outboundOrderItems
))
{
...
...
@@ -196,8 +199,8 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
}
Map
<
String
,
List
<
Map
<
String
,
Object
>>>
deductRecordMap
=
new
HashMap
<>();
// 预加载库存:按「物料ID+库存类型+库位ID」分组
(核心调整)
Map
<
String
,
Inventory
>
inventoryFullMap
=
this
.
loadInventoryFull
Map
();
// 预加载库存:按「物料ID+库存类型+库位ID」分组
,保存所有库存对象
Map
<
String
,
List
<
Inventory
>>
inventoryGroupMap
=
this
.
loadInventoryGroup
Map
();
Map
<
String
,
Long
>
deductQtyMap
=
this
.
buildDeductQtyMap
(
outboundOrderItems
);
// 库存更新Map(最终去重,保留最终状态)
...
...
@@ -219,19 +222,17 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
.
orElse
(
null
);
Long
remainDeductQty
=
totalDeductQty
;
// 核心:按
「物料ID+库存类型+库位ID」分组扣减(先处理无库位,再处理
有库位)
// 核心:按
维度分组扣减(先无库位,后
有库位)
List
<
Map
<
String
,
Object
>>
tempDeductRecords
=
new
ArrayList
<>();
// 步骤1:先扣指定维度的库存(无库位/有库位)
if
(
StringUtils
.
isBlank
(
locationId
))
{
//
无库位:先扣「物料+库存类型+空库位」的库存
//
步骤1:扣无库位库存(同维度所有库存)
String
noLocKey
=
buildInventoryKey
(
materialId
,
""
,
inventoryType
);
remainDeductQty
=
deductByInventory
Key
(
noLocKey
,
remainDeductQty
,
updateUser
,
updateTime
,
inventoryFull
Map
,
toUpdateInventoryMap
,
tempDeductRecords
);
remainDeductQty
=
deductByInventory
Group
(
noLocKey
,
remainDeductQty
,
updateUser
,
updateTime
,
inventoryGroup
Map
,
toUpdateInventoryMap
,
tempDeductRecords
);
//
无库位不足,扣「物料+库存类型+任意有库位」的
库存
//
步骤2:无库位不足,扣同物料+库存类型的所有有库位
库存
if
(
remainDeductQty
>
0
)
{
// 筛选该物料+库存类型的所有有库位库存
List
<
String
>
hasLocKeys
=
inventoryFullMap
.
keySet
().
stream
()
List
<
String
>
hasLocKeys
=
inventoryGroupMap
.
keySet
().
stream
()
.
filter
(
k
->
{
String
[]
parts
=
k
.
split
(
"_"
);
return
parts
.
length
>=
3
...
...
@@ -241,18 +242,25 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
})
.
collect
(
Collectors
.
toList
());
// 有库位库存按总数量从多到少排序(优先扣减库存充足的库位)
hasLocKeys
.
sort
((
k1
,
k2
)
->
{
Long
qty1
=
inventoryGroupMap
.
get
(
k1
).
stream
().
mapToLong
(
inv
->
Optional
.
ofNullable
(
inv
.
getQuantity
()).
orElse
(
0L
)).
sum
();
Long
qty2
=
inventoryGroupMap
.
get
(
k2
).
stream
().
mapToLong
(
inv
->
Optional
.
ofNullable
(
inv
.
getQuantity
()).
orElse
(
0L
)).
sum
();
return
Long
.
compare
(
qty2
,
qty1
);
});
for
(
String
hasLocKey
:
hasLocKeys
)
{
if
(
remainDeductQty
<=
0
)
break
;
remainDeductQty
=
deductByInventory
Key
(
hasLocKey
,
remainDeductQty
,
updateUser
,
updateTime
,
inventoryFull
Map
,
toUpdateInventoryMap
,
tempDeductRecords
);
remainDeductQty
=
deductByInventory
Group
(
hasLocKey
,
remainDeductQty
,
updateUser
,
updateTime
,
inventoryGroup
Map
,
toUpdateInventoryMap
,
tempDeductRecords
);
}
}
}
else
{
// 有库位:扣指定
「物料+库存类型+库位ID」的
库存
// 有库位:扣指定
维度
库存
String
targetKey
=
buildInventoryKey
(
materialId
,
locationId
,
inventoryType
);
remainDeductQty
=
deductByInventory
Key
(
targetKey
,
remainDeductQty
,
updateUser
,
updateTime
,
inventoryFull
Map
,
toUpdateInventoryMap
,
tempDeductRecords
);
remainDeductQty
=
deductByInventory
Group
(
targetKey
,
remainDeductQty
,
updateUser
,
updateTime
,
inventoryGroup
Map
,
toUpdateInventoryMap
,
tempDeductRecords
);
}
// 步骤
2:剩余部分扣负数(最后一个库存
)
// 步骤
3:剩余数量强制扣减(允许库存负数
)
if
(
remainDeductQty
>
0
&&
!
tempDeductRecords
.
isEmpty
())
{
Map
<
String
,
Object
>
lastRecord
=
tempDeductRecords
.
get
(
tempDeductRecords
.
size
()
-
1
);
String
lastInvId
=
(
String
)
lastRecord
.
get
(
"inventoryId"
);
...
...
@@ -262,119 +270,90 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
}
// 累计扣减负数数量
Long
finalDeduct
=
remainDeductQty
;
lastInv
.
setQuantity
(
lastInv
.
getQuantity
()
-
finalDeduct
);
lastInv
.
setQuantity
(
lastInv
.
getQuantity
()
-
remainDeductQty
);
lastInv
.
setInventoryStatus
(
0L
);
lastInv
.
setUpdateBy
(
updateUser
);
lastInv
.
setUpdateTime
(
updateTime
);
toUpdateInventoryMap
.
put
(
lastInvId
,
lastInv
);
//
合并到最后一条
记录
lastRecord
.
put
(
"deductQty"
,
(
Long
)
lastRecord
.
get
(
"deductQty"
)
+
finalDeduct
);
//
更新扣减
记录
lastRecord
.
put
(
"deductQty"
,
(
Long
)
lastRecord
.
get
(
"deductQty"
)
+
remainDeductQty
);
remainDeductQty
=
0L
;
}
// 步骤
3:统一合并(按物料+库存类型+库位ID
)
// 步骤
4:按明细ID归集扣减记录(不合并,保持单库存ID粒度
)
if
(
itemId
!=
null
&&
!
tempDeductRecords
.
isEmpty
())
{
List
<
Map
<
String
,
Object
>>
mergedRecords
=
mergeDeductRecords
(
tempDeductRecords
);
deductRecordMap
.
put
(
itemId
,
mergedRecords
);
deductRecordMap
.
put
(
itemId
,
tempDeductRecords
);
}
// 校验
是否
扣减完成
// 校验扣减完成
if
(
remainDeductQty
>
0
)
{
throw
new
ServiceException
(
String
.
format
(
"物料[%s]库存类型[%s]扣减失败,剩余%d数量未扣减"
,
materialId
,
inventoryType
,
remainDeductQty
));
}
}
// 批量更新库存
(最终去重)
// 批量更新库存
+ 刷新缓存
if
(!
toUpdateInventoryMap
.
isEmpty
())
{
List
<
Inventory
>
needUpdateList
=
new
ArrayList
<>(
toUpdateInventoryMap
.
values
());
inventoryMapper
.
batchUpdateInventory
(
needUpdateList
);
inventoryService
.
RefreshInventory
(
needUpdateList
.
stream
().
map
(
Inventory:
:
getId
).
distinct
().
collect
(
Collectors
.
toList
()));
// 刷新缓存:删除旧缓存,重新加载
needUpdateList
.
forEach
(
inv
->
{
String
cacheKey
=
buildInventoryKey
(
inv
.
getMaterialId
(),
inv
.
getLocationId
(),
inv
.
getInventoryType
().
toString
());
InventoryCache
.
removeInventory
(
cacheKey
,
inv
.
getId
());
InventoryCache
.
addInventory
(
cacheKey
,
inv
);
});
}
return
deductRecordMap
;
}
/**
* 按
「物料ID+库位ID+库存类型」扣减指定库存
* @param inventoryKey
库存Key(物料ID_库位ID_库存类型)
* 按
维度分组扣减库存(核心适配:遍历同维度所有库存)
* @param inventoryKey
维度Key
* @param deductQty 待扣减数量
* @return 剩余未扣减数量
*/
private
Long
deductByInventory
Key
(
String
inventoryKey
,
Long
deductQty
,
String
updateUser
,
Date
updateTime
,
Map
<
String
,
Inventory
>
inventoryFull
Map
,
Map
<
String
,
Inventory
>
toUpdateInventoryMap
,
List
<
Map
<
String
,
Object
>>
tempDeductRecords
)
{
Inventory
inv
=
inventoryFullMap
.
get
(
inventoryKey
);
if
(
inv
==
null
)
{
private
Long
deductByInventory
Group
(
String
inventoryKey
,
Long
deductQty
,
String
updateUser
,
Date
updateTime
,
Map
<
String
,
List
<
Inventory
>>
inventoryGroup
Map
,
Map
<
String
,
Inventory
>
toUpdateInventoryMap
,
List
<
Map
<
String
,
Object
>>
tempDeductRecords
)
{
List
<
Inventory
>
invList
=
inventoryGroupMap
.
getOrDefault
(
inventoryKey
,
new
ArrayList
<>()
);
if
(
CollectionUtils
.
isEmpty
(
invList
)
)
{
return
deductQty
;
}
Long
currentQty
=
Optional
.
ofNullable
(
inv
.
getQuantity
()).
orElse
(
0L
);
Long
canDeduct
=
Math
.
min
(
deductQty
,
currentQty
);
// 更新库存状态
inv
.
setQuantity
(
currentQty
-
canDeduct
);
inv
.
setInventoryStatus
(
inv
.
getQuantity
()
<=
0
?
0L
:
1L
);
inv
.
setUpdateBy
(
updateUser
);
inv
.
setUpdateTime
(
updateTime
);
toUpdateInventoryMap
.
put
(
inv
.
getId
(),
inv
);
// 收集扣减记录(按统一维度)
Map
<
String
,
Object
>
record
=
buildDeductRecord
(
inv
,
inv
.
getInventoryType
().
toString
(),
canDeduct
);
tempDeductRecords
.
add
(
record
);
// 同维度库存按数量从多到少排序(优先扣减数量多的,减少拆分次数)
invList
.
sort
((
a
,
b
)
->
{
Long
qtyA
=
Optional
.
ofNullable
(
a
.
getQuantity
()).
orElse
(
0L
);
Long
qtyB
=
Optional
.
ofNullable
(
b
.
getQuantity
()).
orElse
(
0L
);
return
Long
.
compare
(
qtyB
,
qtyA
);
});
// 返回剩余未扣减数量
return
deductQty
-
canDeduct
;
}
Long
remainDeduct
=
deductQty
;
for
(
Inventory
inv
:
invList
)
{
if
(
remainDeduct
<=
0
)
break
;
/**
* 合并同一「物料ID+库存类型+库位ID」的扣减记录(最终版)
* 核心:按「物料ID_库位ID_库存类型」合并,保留库位信息准确性
*/
private
List
<
Map
<
String
,
Object
>>
mergeDeductRecords
(
List
<
Map
<
String
,
Object
>>
deductRecords
)
{
if
(
CollectionUtils
.
isEmpty
(
deductRecords
))
{
return
Collections
.
emptyList
();
}
Long
currentQty
=
Optional
.
ofNullable
(
inv
.
getQuantity
()).
orElse
(
0L
);
Long
canDeduct
=
Math
.
min
(
remainDeduct
,
currentQty
);
// 合并Key:物料ID_库位ID_库存类型
Map
<
String
,
Map
<
String
,
Object
>>
mergeMap
=
new
LinkedHashMap
<>();
for
(
Map
<
String
,
Object
>
record
:
deductRecords
)
{
String
materialId
=
(
String
)
record
.
get
(
"materialId"
);
String
locationId
=
(
String
)
record
.
get
(
"locationId"
);
String
inventoryType
=
(
String
)
record
.
get
(
"inventoryType"
);
Long
deductQty
=
(
Long
)
record
.
get
(
"deductQty"
);
// 更新库存对象
inv
.
setQuantity
(
currentQty
-
canDeduct
);
inv
.
setInventoryStatus
(
inv
.
getQuantity
()
>
0
?
1L
:
0L
);
inv
.
setUpdateBy
(
updateUser
);
inv
.
setUpdateTime
(
updateTime
);
toUpdateInventoryMap
.
put
(
inv
.
getId
(),
inv
);
if
(
StringUtils
.
isBlank
(
materialId
)
||
StringUtils
.
isBlank
(
inventoryType
)
||
deductQty
<=
0
)
{
continue
;
}
// 生成单库存ID的扣减记录(关键:不再合并库存ID)
Map
<
String
,
Object
>
record
=
buildDeductRecord
(
inv
,
inv
.
getInventoryType
().
toString
(),
canDeduct
)
;
tempDeductRecords
.
add
(
record
);
String
mergeKey
=
buildInventoryKey
(
materialId
,
locationId
,
inventoryType
);
if
(
mergeMap
.
containsKey
(
mergeKey
))
{
Map
<
String
,
Object
>
existRecord
=
mergeMap
.
get
(
mergeKey
);
existRecord
.
put
(
"deductQty"
,
(
Long
)
existRecord
.
get
(
"deductQty"
)
+
deductQty
);
}
else
{
Map
<
String
,
Object
>
newRecord
=
new
HashMap
<>(
record
);
mergeMap
.
put
(
mergeKey
,
newRecord
);
}
remainDeduct
-=
canDeduct
;
}
return
new
ArrayList
<>(
mergeMap
.
values
())
;
return
remainDeduct
;
}
/**
* 构建库存Key:物料ID_库位ID_库存类型
*/
private
String
buildInventoryKey
(
String
materialId
,
String
locationId
,
String
inventoryType
)
{
return
String
.
join
(
"_"
,
Optional
.
ofNullable
(
materialId
).
orElse
(
""
),
Optional
.
ofNullable
(
locationId
).
orElse
(
""
),
Optional
.
ofNullable
(
inventoryType
).
orElse
(
""
)
);
}
/**
* 构建扣减记录
* 构建扣减记录(单库存ID粒度)
*/
private
Map
<
String
,
Object
>
buildDeductRecord
(
Inventory
inv
,
String
inventoryType
,
Long
deductQty
)
{
Map
<
String
,
Object
>
record
=
new
HashMap
<>();
...
...
@@ -387,25 +366,26 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
}
/**
* 预加载库存
全量Map(按「物料ID_库位ID_库存类型」为Key
)
* 预加载库存
分组Map(按维度Key分组,保存所有库存对象
)
*/
private
Map
<
String
,
Inventory
>
loadInventoryFullMap
()
{
Collection
<
Inventory
>
allInventory
=
InventoryCache
.
getAll
().
values
();
if
(
CollectionUtils
.
isEmpty
(
allInventory
))
{
return
Collections
.
emptyMap
();
private
Map
<
String
,
List
<
Inventory
>>
loadInventoryGroupMap
()
{
// 1. 用你现有的selectInventoryList查全量可用库存(传空条件=查所有)
Inventory
query
=
new
Inventory
();
query
.
setInventoryStatus
(
1L
);
// 只查可用状态库存
query
.
setIsUsed
(
1L
);
// 只查启用的库存
List
<
Inventory
>
allInventory
=
inventoryMapper
.
selectInventoryList
(
query
);
// 2. 按维度分组(和你原有逻辑完全一致)
Map
<
String
,
List
<
Inventory
>>
inventoryGroupMap
=
new
LinkedHashMap
<>();
for
(
Inventory
inv
:
allInventory
)
{
String
key
=
buildInventoryKey
(
inv
.
getMaterialId
(),
inv
.
getLocationId
(),
Optional
.
ofNullable
(
inv
.
getInventoryType
()).
map
(
String:
:
valueOf
).
orElse
(
""
)
);
inventoryGroupMap
.
computeIfAbsent
(
key
,
k
->
new
ArrayList
<>()).
add
(
inv
);
}
return
allInventory
.
stream
()
.
collect
(
Collectors
.
toMap
(
inv
->
buildInventoryKey
(
inv
.
getMaterialId
(),
inv
.
getLocationId
(),
Optional
.
ofNullable
(
inv
.
getInventoryType
()).
map
(
String:
:
valueOf
).
orElse
(
""
)
),
inv
->
inv
,
(
k1
,
k2
)
->
k1
,
// 重复Key保留第一个
LinkedHashMap:
:
new
));
return
inventoryGroupMap
;
}
/**
...
...
@@ -433,6 +413,17 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
);
}
/**
* 构建库存Key:物料ID_库位ID_库存类型
*/
private
String
buildInventoryKey
(
String
materialId
,
String
locationId
,
String
inventoryType
)
{
return
String
.
join
(
"_"
,
Optional
.
ofNullable
(
materialId
).
orElse
(
""
),
Optional
.
ofNullable
(
locationId
).
orElse
(
""
),
Optional
.
ofNullable
(
inventoryType
).
orElse
(
""
)
);
}
@Override
public
List
<
Map
<
String
,
String
>>
outboundOrdersTopTenByQuantity
()
{
return
outboundOrdersMapper
.
SelectOutboundOrdersMaterialsTopTenByQuantity
();
...
...
@@ -464,7 +455,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
throw
new
RuntimeException
(
"库存被修改请重新确认"
);
}
// 合并相同
库存维度的明细记录(简化版
)
// 合并相同
维度明细(仅合并数量,库存ID不拼接
)
List
<
OutboundOrderItems
>
mergedItemsList
=
mergeSameInventoryItems
(
outboundOrderItemsList
);
// 为明细设置订单ID和主键ID
...
...
@@ -485,7 +476,15 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
BeanUtils
.
copyProperties
(
items
,
log
);
log
.
setOrderId
(
items
.
getOutboundOrderId
());
outboundOrderLogs
.
add
(
log
);
inventoryIds
.
add
(
log
.
getInventoryId
());
// 拆分库存ID(支持逗号分隔)
if
(
StringUtils
.
isNotBlank
(
items
.
getInventoryId
()))
{
String
[]
invIds
=
items
.
getInventoryId
().
split
(
","
);
for
(
String
invId
:
invIds
)
{
if
(
StringUtils
.
isNotBlank
(
invId
))
{
inventoryIds
.
add
(
invId
.
trim
());
}
}
}
}
// 插入日志 + 刷新库存
...
...
@@ -498,17 +497,14 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
}
/**
* 简化版:合并相同库存维度的明细记录
* 按「物料ID+库存类型+库位ID」维度合并,仅累加实际数量
* 合并相同维度明细(仅合并数量,不拼接库存ID)
*/
private
List
<
OutboundOrderItems
>
mergeSameInventoryItems
(
List
<
OutboundOrderItems
>
itemsList
)
{
if
(
CollectionUtils
.
isEmpty
(
itemsList
))
{
return
Collections
.
emptyList
();
}
// 按「物料ID+库存类型+库位ID」分组合并
Map
<
String
,
OutboundOrderItems
>
mergeMap
=
new
LinkedHashMap
<>();
for
(
OutboundOrderItems
item
:
itemsList
)
{
String
mergeKey
=
buildInventoryKey
(
item
.
getMaterialId
(),
...
...
@@ -517,13 +513,12 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
);
if
(
mergeMap
.
containsKey
(
mergeKey
))
{
// 只合并实际数量
OutboundOrderItems
existItem
=
mergeMap
.
get
(
mergeKey
);
// 仅累加数量
Long
newActualQty
=
Optional
.
ofNullable
(
existItem
.
getActualQuantity
()).
orElse
(
0L
)
+
Optional
.
ofNullable
(
item
.
getActualQuantity
()).
orElse
(
0L
);
existItem
.
setActualQuantity
(
newActualQty
);
}
else
{
// 新记录直接放入
mergeMap
.
put
(
mergeKey
,
item
);
}
}
...
...
@@ -558,7 +553,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
Map
<
String
,
String
>
sapToMaterialIdMap
=
loadSapToMaterialIdMap
();
Map
<
String
,
String
>
locationNameToIdMap
=
loadLocationNameToIdMap
();
Map
<
String
,
String
>
ownerNameToIdMap
=
loadOwnerNameToIdMap
();
Map
<
String
,
AbstractMap
.
SimpleEntry
<
String
,
Long
>>
inventoryTOIdMap
=
loadInventoryTOId
Map
();
Map
<
String
,
List
<
Inventory
>>
inventoryGroupMap
=
loadInventoryGroup
Map
();
// 4. 按入库单号分组
Map
<
String
,
List
<
OutboundTemplateVO
>>
orderGroupMap
=
inboundOrdersList
.
stream
()
...
...
@@ -627,7 +622,6 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
mainDO
.
setUpdateUserCode
(
operId
);
mainDO
.
setSortNo
(
Optional
.
ofNullable
(
mainDO
.
getSortNo
()).
orElse
(
0L
));
mainDO
.
setIsImport
(
0L
);
//添加日期
mainDO
.
setInboundDate
(
DateUtils
.
getNowDate
());
// 明细校验
...
...
@@ -640,7 +634,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
"orderId"
,
"systemNo"
,
"orderTypeId"
,
"batchId"
,
"warehouseName"
,
"warehouseId"
);
// 填充明细必填字段
itemDO
.
setId
(
UUID
.
randomUUID
().
toString
());
itemDO
.
setId
(
UUID
.
randomUUID
().
toString
()
.
replace
(
"-"
,
""
)
);
itemDO
.
setOrderId
(
orderId
);
itemDO
.
setBatchCode
(
Optional
.
ofNullable
(
mainDO
.
getBatchCode
()).
orElse
(
""
));
itemDO
.
setOutboundOrderId
(
mainDO
.
getId
());
...
...
@@ -648,8 +642,8 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
itemDO
.
setCreateTime
(
now
);
itemDO
.
setCreateUserCode
(
operId
);
itemDO
.
setSortNo
(
0L
);
itemDO
.
setItemStatus
(
3L
);
// 设置为已出库状态
itemDO
.
setShippedAt
(
mainDO
.
getInboundDate
());
//
itemDO
.
setItemStatus
(
3L
);
itemDO
.
setShippedAt
(
mainDO
.
getInboundDate
());
// 物料SAP校验
String
sapNo
=
vo
.
getSapNo
()
!=
null
?
vo
.
getSapNo
().
trim
()
:
""
;
...
...
@@ -666,8 +660,8 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
// 库位校验
String
locationName
=
vo
.
getLocationName
()
!=
null
?
vo
.
getLocationName
().
trim
()
:
""
;
String
locationId
=
locationNameToIdMap
.
get
(
locationName
);
if
(
StringUtils
.
isNotBlank
(
locationName
))
{
String
locationId
=
locationNameToIdMap
.
get
(
locationName
);
if
(
StringUtils
.
isBlank
(
locationId
))
{
throw
new
ServiceException
(
String
.
format
(
"入库单号【%s】第%d条明细的库位【%s】不存在"
,
orderId
,
lineNo
,
locationName
));
...
...
@@ -677,49 +671,13 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
// 库存类型设置
itemDO
.
setInventoryType
(
orderType
);
// 实际出库数量(使用计划数量)
// 实际出库数量
itemDO
.
setActualQuantity
(
Optional
.
ofNullable
(
vo
.
getActualQuantity
()).
orElse
(
0L
));
// 库存校验(包含inventoryType)- 有库位才校验,无库位直接跳过
if
(
StringUtils
.
isNotBlank
(
locationName
))
{
String
inventoryTypeStr
=
Optional
.
ofNullable
(
orderType
).
map
(
String:
:
valueOf
).
orElse
(
""
);
String
inventoryMatchKey
=
buildInventoryKey
(
materialId
,
locationId
,
inventoryTypeStr
);
AbstractMap
.
SimpleEntry
<
String
,
Long
>
inventoryEntry
=
inventoryTOIdMap
.
get
(
inventoryMatchKey
);
String
inventoryId
=
""
;
if
(
inventoryEntry
==
null
)
{
Inventory
inventory
=
new
Inventory
();
BeanUtils
.
copyProperties
(
itemDO
,
inventory
);
inventoryId
=
UUID
.
randomUUID
().
toString
();
inventory
.
setInventoryType
(
Long
.
valueOf
(
orderType
));
inventory
.
setBatchId
(
itemDO
.
getBatchCode
());
inventory
.
setWarehousesId
(
"local"
);
inventory
.
setQuantity
(
0L
);
inventory
.
setInventoryStatus
(
1L
);
inventory
.
setIsUsed
(
1L
);
inventory
.
setId
(
inventoryId
);
int
insertCount
=
inventoryMapper
.
insertInventory
(
inventory
);
if
(
insertCount
!=
1
)
{
throw
new
ServiceException
(
String
.
format
(
"入库单号【%s】第%d条明细新增库存失败,插入行数为0"
,
orderId
,
lineNo
));
}
// 插入后直接添加到全局缓存
InventoryCache
.
addInventory
(
inventoryMatchKey
,
inventory
);
sqlSessionTemplate
.
clearCache
();
sqlSessionTemplate
.
flushStatements
();
}
else
{
System
.
out
.
println
(
"库存已存在,使用已有库存ID:"
+
inventoryEntry
.
getKey
());
inventoryId
=
inventoryEntry
.
getKey
();
}
itemDO
.
setInventoryId
(
inventoryId
);
}
// 无库位时不校验库存,也不设置inventoryId
itemDOList
.
add
(
itemDO
);
}
// 合并相同
库存维度的
明细
// 合并相同
维度
明细
List
<
OutboundOrderItems
>
mergedItemList
=
mergeSameInventoryItems
(
itemDOList
);
validMainMap
.
put
(
orderId
,
mainDO
);
validItemMap
.
put
(
orderId
,
mergedItemList
);
...
...
@@ -756,7 +714,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
int
itemFail
=
itemDOList
.
size
()
-
itemSuccess
;
totalItemFailure
+=
itemFail
;
successMsg
.
append
(
String
.
format
(
"入库单号【%s】成功导入%d条物料明细
(已合并相同库存维度)
;\n"
,
orderId
,
itemSuccess
));
successMsg
.
append
(
String
.
format
(
"入库单号【%s】成功导入%d条物料明细;\n"
,
orderId
,
itemSuccess
));
if
(
itemFail
>
0
)
{
failureMsg
.
append
(
String
.
format
(
"入库单号【%s】有%d条物料明细导入失败;\n"
,
orderId
,
itemFail
));
}
...
...
@@ -765,36 +723,29 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
}
}
// 8. 异步执行库存扣减和无库位明细拆分
CompletableFuture
.
runAsync
(()
->
{
try
{
for
(
Map
.
Entry
<
String
,
List
<
OutboundOrderItems
>>
entry
:
allItemListMap
.
entrySet
())
{
List
<
OutboundOrderItems
>
itemList
=
entry
.
getValue
();
// 执行库存扣减
Map
<
String
,
List
<
Map
<
String
,
Object
>>>
deductRecordMap
=
deductInventory
(
itemList
,
operId
,
now
);
// 处理无库位明细拆分
boolean
hasNoLocationItem
=
itemList
.
stream
()
.
anyMatch
(
item
->
StringUtils
.
isBlank
(
item
.
getLocationId
()));
if
(
hasNoLocationItem
&&
!
deductRecordMap
.
isEmpty
())
{
handleNoLocationItemSplit
(
itemList
,
deductRecordMap
,
operId
,
now
);
}
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
// ========== 关键修改:移除 CompletableFuture 异步执行,改为同步调用 ==========
// 8. 同步执行库存扣减和无库位明细拆分(原异步逻辑改为同步)
try
{
for
(
Map
.
Entry
<
String
,
List
<
OutboundOrderItems
>>
entry
:
allItemListMap
.
entrySet
())
{
List
<
OutboundOrderItems
>
itemList
=
entry
.
getValue
();
// 执行库存扣减
Map
<
String
,
List
<
Map
<
String
,
Object
>>>
deductRecordMap
=
deductInventory
(
itemList
,
operId
,
now
);
// 处理无库位明细拆分
handleNoLocationItemSplit
(
itemList
,
deductRecordMap
,
operId
,
now
);
}
});
}
catch
(
Exception
e
)
{
}
// 9. 结果汇总
if
(
totalMainFailure
>
0
||
totalItemFailure
>
0
)
{
String
finalFailureMsg
=
String
.
format
(
"导入结果:成功新增%d个入库单,失败%d个;成功导入%d条明细
(已合并相同库存维度)
,失败%d条。失败详情:%s"
,
"导入结果:成功新增%d个入库单,失败%d个;成功导入%d条明细,失败%d条。失败详情:%s"
,
totalMainSuccess
,
totalMainFailure
,
totalItemSuccess
,
totalItemFailure
,
failureMsg
.
toString
()
);
throw
new
ServiceException
(
finalFailureMsg
);
}
else
{
String
finalSuccessMsg
=
String
.
format
(
"恭喜您,数据已全部导入成功!共新增%d个入库单,成功导入%d条物料明细
(已合并相同库存维度)
。详情:%s"
,
"恭喜您,数据已全部导入成功!共新增%d个入库单,成功导入%d条物料明细。详情:%s"
,
totalMainSuccess
,
totalItemSuccess
,
successMsg
.
toString
()
);
return
finalSuccessMsg
;
...
...
@@ -802,62 +753,56 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
}
/**
* 处理无库位明细拆分(
适配新的合并维度
)
* 处理无库位明细拆分(
精准匹配扣减记录
)
*/
private
void
handleNoLocationItemSplit
(
List
<
OutboundOrderItems
>
itemList
,
Map
<
String
,
List
<
Map
<
String
,
Object
>>>
deductRecordMap
,
String
operId
,
Date
now
)
{
List
<
OutboundOrderItems
>
new
Valid
ItemList
=
new
ArrayList
<>();
List
<
OutboundOrderItems
>
newItemList
=
new
ArrayList
<>();
Set
<
String
>
orderIdSet
=
new
HashSet
<>();
for
(
OutboundOrderItems
item
:
itemList
)
{
if
(
StringUtils
.
isNotBlank
(
item
.
getLocationId
()))
{
continue
;
// 跳过有库位明细
}
String
itemId
=
item
.
getId
();
List
<
Map
<
String
,
Object
>>
deductRecords
=
deductRecordMap
.
get
(
itemId
);
if
(
CollectionUtils
.
isEmpty
(
deductRecords
))
continue
;
orderIdSet
.
add
(
item
.
getOutboundOrderId
());
// 直接遍历合并后的记录(已按物料+库存类型+库位ID合并)
// 按扣减记录拆分明细(一条扣减记录对应一条新明细)
for
(
Map
<
String
,
Object
>
rec
:
deductRecords
)
{
String
inventoryId
=
(
String
)
rec
.
get
(
"inventoryId"
);
String
locId
=
(
String
)
rec
.
get
(
"locationId"
);
Long
valid
Qty
=
(
Long
)
rec
.
get
(
"deductQty"
);
Long
deduct
Qty
=
(
Long
)
rec
.
get
(
"deductQty"
);
if
(
valid
Qty
<=
0
||
StringUtils
.
isBlank
(
inventoryId
))
continue
;
if
(
deduct
Qty
<=
0
||
StringUtils
.
isBlank
(
inventoryId
))
continue
;
OutboundOrderItems
newItem
=
new
OutboundOrderItems
();
BeanUtils
.
copyProperties
(
item
,
newItem
);
newItem
.
setId
(
UUID
.
randomUUID
().
toString
().
replace
(
"-"
,
""
));
newItem
.
setLocationId
(
locId
);
newItem
.
setActualQuantity
(
valid
Qty
);
newItem
.
setActualQuantity
(
deduct
Qty
);
newItem
.
setInventoryId
(
inventoryId
);
newItem
.
setCreateBy
(
operId
);
newItem
.
setCreateTime
(
now
);
newItem
.
setUpdateBy
(
operId
);
newItem
.
setUpdateTime
(
now
);
new
Valid
ItemList
.
add
(
newItem
);
newItemList
.
add
(
newItem
);
}
}
// 删除临时明细
for
(
String
orderId
:
orderIdSet
)
{
outboundOrderItemsMapper
.
deleteOutboundOrderItemsByOrderId
(
orderId
);
}
// 批量插入有效明细(插入前再次合并)
List
<
OutboundOrderItems
>
mergedNewItems
=
mergeSameInventoryItems
(
newValidItemList
);
if
(!
mergedNewItems
.
isEmpty
())
{
outboundOrderItemsMapper
.
batchInsertOutboundOrderItems
(
mergedNewItems
);
// 删除原无库位明细,插入拆分后的新明细
if
(!
orderIdSet
.
isEmpty
()
&&
!
newItemList
.
isEmpty
())
{
orderIdSet
.
forEach
(
orderId
->
outboundOrderItemsMapper
.
deleteOutboundOrderItemsByOrderId
(
orderId
));
outboundOrderItemsMapper
.
batchInsertOutboundOrderItems
(
newItemList
);
// 生成日志
List
<
OutboundOrderLog
>
logList
=
new
ArrayList
<>();
for
(
OutboundOrderItems
newItem
:
mergedNewItems
)
{
// 生成拆分后的日志
List
<
OutboundOrderLog
>
logList
=
newItemList
.
stream
().
map
(
item
->
{
OutboundOrderLog
log
=
new
OutboundOrderLog
();
BeanUtils
.
copyProperties
(
newI
tem
,
log
);
log
.
setOrderId
(
newI
tem
.
getOutboundOrderId
());
BeanUtils
.
copyProperties
(
i
tem
,
log
);
log
.
setOrderId
(
i
tem
.
getOutboundOrderId
());
log
.
setItemStatus
(
3L
);
logList
.
add
(
log
)
;
}
return
log
;
}
).
collect
(
Collectors
.
toList
());
outboundOrderLogMapper
.
batchOutboundOrderLog
(
logList
);
}
}
...
...
@@ -906,45 +851,4 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService {
(
k1
,
k2
)
->
k1
));
}
/**
* 加载库存映射Map(按新维度)+ 同步填充全局缓存
*/
private
Map
<
String
,
AbstractMap
.
SimpleEntry
<
String
,
Long
>>
loadInventoryTOIdMap
()
{
Inventory
inventory
=
new
Inventory
();
inventory
.
setInventoryStatus
(
1L
);
inventory
.
setIsUsed
(
1L
);
List
<
Inventory
>
inventoryList
=
inventoryService
.
selectInventoryList
(
inventory
);
// 清空全局缓存
InventoryCache
.
clear
();
if
(
CollectionUtils
.
isEmpty
(
inventoryList
))
{
return
Collections
.
emptyMap
();
}
return
inventoryList
.
stream
()
.
filter
(
inv
->
StringUtils
.
isNotBlank
(
inv
.
getMaterialId
())
&&
inv
.
getInventoryType
()
!=
null
&&
StringUtils
.
isNotBlank
(
inv
.
getId
()))
.
peek
(
inv
->
{
// 同步到全局缓存(按新维度)
String
key
=
buildInventoryKey
(
inv
.
getMaterialId
(),
inv
.
getLocationId
(),
inv
.
getInventoryType
().
toString
()
);
InventoryCache
.
addInventory
(
key
,
inv
);
})
.
collect
(
Collectors
.
toMap
(
inv
->
buildInventoryKey
(
inv
.
getMaterialId
(),
inv
.
getLocationId
(),
inv
.
getInventoryType
().
toString
()
),
inv
->
new
AbstractMap
.
SimpleEntry
<>(
inv
.
getId
().
trim
(),
Optional
.
ofNullable
(
inv
.
getQuantity
()).
orElse
(
0L
)),
(
k1
,
k2
)
->
k1
,
HashMap:
:
new
));
}
}
\ No newline at end of file
ruoyi-inventory/src/main/java/com/ruoyi/inventory/utils/InventoryCache.java
View file @
4d2dea9b
package
com
.
ruoyi
.
inventory
.
utils
;
import
com.ruoyi.inventory.domain.Inventory
;
import
com.ruoyi.common.utils.StringUtils
;
import
org.apache.commons.collections4.CollectionUtils
;
import
java.util.AbstractMap
;
import
java.util.Map
;
import
java.util.*
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.CopyOnWriteArrayList
;
/**
* 库存映射全局缓存(
解决导入新增库存即时可见问题
)
* 库存映射全局缓存(
适配同维度多库存场景
)
*/
public
class
InventoryCache
{
//
并发安全Map,Key=物料ID_库位ID_库存类型,Value=库存对象
private
static
final
Map
<
String
,
Inventory
>
INVENTORY
_MAP
=
new
ConcurrentHashMap
<>();
//
重构:维度Key → 同维度下的所有库存列表
private
static
final
Map
<
String
,
List
<
Inventory
>>
INVENTORY_GROUP
_MAP
=
new
ConcurrentHashMap
<>();
// 添加库存(直接存对象,避免参数不匹配)
// ========== 核心方法 ==========
/**
* 批量初始化缓存(从数据库加载全量库存时调用)
* @param allInventory 全量库存列表
*/
public
static
void
init
(
List
<
Inventory
>
allInventory
)
{
if
(
CollectionUtils
.
isEmpty
(
allInventory
))
{
clear
();
return
;
}
INVENTORY_GROUP_MAP
.
clear
();
for
(
Inventory
inv
:
allInventory
)
{
String
key
=
buildInventoryKey
(
inv
);
INVENTORY_GROUP_MAP
.
computeIfAbsent
(
key
,
k
->
new
CopyOnWriteArrayList
<>()).
add
(
inv
);
}
}
/**
* 添加单条库存到缓存(自动按维度分组)
* @param inventory 库存对象
*/
public
static
void
addInventory
(
Inventory
inventory
)
{
if
(
inventory
==
null
)
{
return
;
}
String
key
=
buildInventoryKey
(
inventory
);
INVENTORY_GROUP_MAP
.
computeIfAbsent
(
key
,
k
->
new
CopyOnWriteArrayList
<>()).
add
(
inventory
);
}
/**
* 更新缓存中的库存对象(按库存ID匹配)
* @param inventory 待更新的库存对象
*/
public
static
void
updateInventory
(
Inventory
inventory
)
{
if
(
inventory
==
null
||
StringUtils
.
isBlank
(
inventory
.
getId
()))
{
return
;
}
String
key
=
buildInventoryKey
(
inventory
);
List
<
Inventory
>
invList
=
INVENTORY_GROUP_MAP
.
get
(
key
);
if
(
CollectionUtils
.
isEmpty
(
invList
))
{
return
;
}
// 替换同ID的库存对象
for
(
int
i
=
0
;
i
<
invList
.
size
();
i
++)
{
if
(
inventory
.
getId
().
equals
(
invList
.
get
(
i
).
getId
()))
{
invList
.
set
(
i
,
inventory
);
break
;
}
}
}
/**
* 移除指定维度下的指定库存
* @param inventory 待移除的库存对象
*/
public
static
void
removeInventory
(
Inventory
inventory
)
{
if
(
inventory
==
null
||
StringUtils
.
isBlank
(
inventory
.
getId
()))
{
return
;
}
String
key
=
buildInventoryKey
(
inventory
);
List
<
Inventory
>
invList
=
INVENTORY_GROUP_MAP
.
get
(
key
);
if
(
CollectionUtils
.
isEmpty
(
invList
))
{
return
;
}
invList
.
removeIf
(
inv
->
inventory
.
getId
().
equals
(
inv
.
getId
()));
// 若维度下无库存,删除该维度Key
if
(
invList
.
isEmpty
())
{
INVENTORY_GROUP_MAP
.
remove
(
key
);
}
}
/**
* 按维度Key获取库存列表
* @param key 维度Key(物料ID_库位ID_库存类型)
* @return 同维度下的所有库存
*/
public
static
List
<
Inventory
>
getInventoryListByKey
(
String
key
)
{
return
INVENTORY_GROUP_MAP
.
getOrDefault
(
key
,
Collections
.
emptyList
());
}
/**
* 获取全量缓存(供扣减逻辑调用)
* @return 维度Key → 库存列表
*/
public
static
Map
<
String
,
List
<
Inventory
>>
getAllGroup
()
{
return
new
HashMap
<>(
INVENTORY_GROUP_MAP
);
// 返回拷贝,避免外部修改
}
/**
* 清空缓存
*/
public
static
void
clear
()
{
INVENTORY_GROUP_MAP
.
clear
();
}
// ========== 辅助方法 ==========
/**
* 构建库存维度Key:物料ID_库位ID_库存类型
*/
public
static
String
buildInventoryKey
(
Inventory
inventory
)
{
if
(
inventory
==
null
)
{
return
""
;
}
return
String
.
join
(
"_"
,
StringUtils
.
trimToEmpty
(
inventory
.
getMaterialId
()),
StringUtils
.
trimToEmpty
(
inventory
.
getLocationId
()),
Optional
.
ofNullable
(
inventory
.
getInventoryType
()).
map
(
String:
:
valueOf
).
orElse
(
""
)
);
}
/**
* 重载:手动构建维度Key
*/
public
static
String
buildInventoryKey
(
String
materialId
,
String
locationId
,
String
inventoryType
)
{
return
String
.
join
(
"_"
,
StringUtils
.
trimToEmpty
(
materialId
),
StringUtils
.
trimToEmpty
(
locationId
),
StringUtils
.
trimToEmpty
(
inventoryType
)
);
}
// ========== 兼容原有方法(避免改动业务层) ==========
@Deprecated
// 标记为过时,建议使用新方法
public
static
void
addInventory
(
String
key
,
Inventory
inventory
)
{
INVENTORY_
MAP
.
put
(
key
,
inventory
);
INVENTORY_
GROUP_MAP
.
computeIfAbsent
(
key
,
k
->
new
CopyOnWriteArrayList
<>()).
add
(
inventory
);
}
// 获取库存
@Deprecated
public
static
Inventory
getInventory
(
String
key
)
{
return
INVENTORY_MAP
.
get
(
key
);
List
<
Inventory
>
invList
=
INVENTORY_GROUP_MAP
.
get
(
key
);
return
CollectionUtils
.
isEmpty
(
invList
)
?
null
:
invList
.
get
(
0
);
}
// 清空缓存
public
static
void
clear
(
)
{
INVENTORY_
MAP
.
clear
(
);
@Deprecated
public
static
void
removeInventory
(
String
key
)
{
INVENTORY_
GROUP_MAP
.
remove
(
key
);
}
// 获取全部缓存(核心:供loadInventoryGroupMap直接读取)
public
static
Map
<
String
,
Inventory
>
getAll
()
{
return
INVENTORY_MAP
;
@Deprecated
public
static
void
removeInventory
(
String
key
,
String
inventoryId
)
{
List
<
Inventory
>
invList
=
INVENTORY_GROUP_MAP
.
get
(
key
);
if
(
CollectionUtils
.
isEmpty
(
invList
))
{
return
;
}
invList
.
removeIf
(
inv
->
inventoryId
.
equals
(
inv
.
getId
()));
if
(
invList
.
isEmpty
())
{
INVENTORY_GROUP_MAP
.
remove
(
key
);
}
}
@Deprecated
public
static
Map
<
String
,
Inventory
>
getAll
()
{
// 兼容原有逻辑:维度Key → 第一个库存对象(仅临时兼容)
Map
<
String
,
Inventory
>
oldMap
=
new
ConcurrentHashMap
<>();
for
(
Map
.
Entry
<
String
,
List
<
Inventory
>>
entry
:
INVENTORY_GROUP_MAP
.
entrySet
())
{
List
<
Inventory
>
invList
=
entry
.
getValue
();
if
(!
CollectionUtils
.
isEmpty
(
invList
))
{
oldMap
.
put
(
entry
.
getKey
(),
invList
.
get
(
0
));
}
}
return
oldMap
;
}
}
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论