背景描述
鋪貨的時候要對照bach那邊的庫存做校驗喊衫,不同蜂房要查看的sku列表是相同的,但是每個sku在每個蜂房的庫存都是不一樣的,要把每個蜂房的sku庫存情況以Map的形式存儲下來,以蜂房的code為key,sku的庫存為value地来,而sku的庫存也做成了map,以skuCode為key熙掺,sku對象未斑,形成<蜂房code,<skuCode,sku>>
這樣的數(shù)據(jù)結構。然后每個鋪貨點位找到對應的蜂房币绩,查看蜂房內(nèi)要鋪貨的sku庫存是否滿足鋪貨要求蜡秽,滿足就可以分貨,然后將對應sku的庫存扣除类浪,不滿足就不鋪貨载城。問題描述
今天發(fā)現(xiàn)了一個問題,運營人員說生成的鋪貨單的點位不夠费就,但是對應蜂房的庫存確實可以滿足鋪貨的诉瓦。問題分析
通過grep日志發(fā)現(xiàn),同一個蜂房下同一個sku的庫存扣減是不連續(xù)的。比如庫存數(shù)突然從224跳到160睬澡,那么中間的庫存被誰拿走了固额?猜測是因為別的點位(本應該去它對應的蜂房)也來拿取了蜂房的庫存。
通過review代碼發(fā)現(xiàn)了問題
初始化庫存的代碼如下:
Map<String, Sku> skuMap = skuReposityMap.get(shop.getEntrepotCode());
ArrayList<Sku> allSku = Lists.newArrayList();
allSku.addAll(Safes.of(template.getNormalList()));
allSku.addAll(Safes.of(template.getHotList()));
allSku.addAll(Safes.of(template.getColdList()));
allSku.addAll(Safes.of(template.getDeskList()));
allSku.addAll(Safes.of(template.getPlugList()));
for (Sku sku : allSku) {
//問題就出在這行代碼上
skuMap.put(sku.getCode(), sku);
}
skuReposityMap.put(shop.getEntrepotCode(), skuMap);
扣減庫存的代碼如下
private List<ShopSkuRelation> filterNecessary(Shop shop, List<ShopSkuRelation> goods, Map<String, Sku> inventory,
List<Sku> skuList) {
return goods.stream().filter(shopSkuRelation -> {
Sku sku = inventory.get(shopSkuRelation.getSkuCode());
Scale6Decimal originInventory = sku.getInventory();
logger.info("庫房:{},skuCode:{},庫存是:{}", shop.getEntrepotCode(), sku.getCode(), originInventory);
Scale6Decimal result = originInventory.minus(new Scale6Decimal(new BigDecimal(shopSkuRelation.getNum())));
logger.info("扣減庫存煞聪,shelfCode是:{},蜂房:{},skuCode是:{},庫存是:{},扣減num is {},結果是:{}", shop.getCode(),
shop.getEntrepotCode(), sku.getCode(), sku.getInventory(), shopSkuRelation.getNum(), result);
if (result.isNegative()) {
logger.info("skuCode:{},num is :{},repository is {},inventory is{},倉庫不滿足需求了", sku.getCode(),
shopSkuRelation.getNum(), shop.getEntrepotCode(), originInventory);
return false;
} else {
//修改庫存
sku.setInventory(result);
return true;
}
}).collect(Collectors.toList());
}
第一段是循環(huán)遍歷初始化庫房-sku庫存的數(shù)據(jù)結構斗躏,由于都是每個蜂房查詢的sku列表是相同的,這個地方拿到的sku都是從template中get的昔脯,然后放到不同的map中去啄糙。而在下面修改庫存的時候,其實修改的sku對象指向到的是同一份sku實例云稚,本來我們期望的是不同蜂房的sku庫存是相互隔離的隧饼,但是由于在初始化的時候,不同的蜂房使用了同一份sku静陈,因此就出現(xiàn)了不同的點位扣除是同一份sku的庫存
- 解決方案
在初始化的時候燕雁,template吐出來的sku集合是一個deep copy就好了,這樣就能保證每次遍歷拿到的sku是獨立的鲸拥,也能保證即使對sku進行結構性變化拐格,也不會影響到template。