Index: ssts-basedata/src/main/java/com/forgon/disinfectsystem/entity/invoicemanager/InvoiceItem.java =================================================================== diff -u -r27811 -r28435 --- ssts-basedata/src/main/java/com/forgon/disinfectsystem/entity/invoicemanager/InvoiceItem.java (.../InvoiceItem.java) (revision 27811) +++ ssts-basedata/src/main/java/com/forgon/disinfectsystem/entity/invoicemanager/InvoiceItem.java (.../InvoiceItem.java) (revision 28435) @@ -153,6 +153,13 @@ * 包定义id赋值时,包定义的材料数量 */ private Integer materialAmount; + + /** + * 唯一编码,用于批量插入invoiceItem表后,可以根据此uuid找到其对应的id(因为id是自增长的,插入后才会知道具体的值) + * 仅上面的一个用途,暂无其它业务意义,暂只用于优化后的发货用 + */ + private String uuid; + @Id @GeneratedValue(strategy = GenerationType.AUTO) public Long getId() { @@ -517,5 +524,13 @@ public void setMaterialAmount(Integer materialAmount) { this.materialAmount = materialAmount; } - + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + } Index: ssts-invoice/src/main/java/com/forgon/disinfectsystem/invoicemanager/service/InvoiceOptimizeManagerImpl.java =================================================================== diff -u -r28351 -r28435 --- ssts-invoice/src/main/java/com/forgon/disinfectsystem/invoicemanager/service/InvoiceOptimizeManagerImpl.java (.../InvoiceOptimizeManagerImpl.java) (revision 28351) +++ ssts-invoice/src/main/java/com/forgon/disinfectsystem/invoicemanager/service/InvoiceOptimizeManagerImpl.java (.../InvoiceOptimizeManagerImpl.java) (revision 28435) @@ -17,6 +17,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.UUID; import java.util.stream.Collectors; import net.sf.json.JSONArray; @@ -287,27 +288,29 @@ //根据条码集合取出条码对象 List barcodeDeviceList = barcodeManager.getCollectionForUpdate("barcode", barcodeList); - if(CollectionUtils.isEmpty(barcodeDeviceList)){ - throw new SystemException("所扫描的物品条码未找到条件对象"); + if(CollectionUtils.isEmpty(disposableGoodsBarcodeList) && CollectionUtils.isEmpty(barcodeDeviceList)){ + throw new SystemException("所扫描的物品条码未找到对应的条码对象"); } //条码对象map,key为条码、value为条码对象 - Map barcodeToBarcodeDeviceMap = - new LinkedHashMap(); - barcodeDeviceList.stream().forEach(barcodeDevice -> { - barcodeToBarcodeDeviceMap.put(barcodeDevice.getBarcode(), barcodeDevice); - }); - //记录根据条码查找不到条码对象的条码 - List barcodeNotMatchBarcodeDeviceList = new ArrayList(); - if(barcodeList.size() != barcodeDeviceList.size()){ - barcodeList.stream().forEach(barcode -> { - if(!barcodeToBarcodeDeviceMap.containsKey(barcode)){ - barcodeNotMatchBarcodeDeviceList.add(barcode); - } + if(CollectionUtils.isNotEmpty(barcodeDeviceList)){ + Map barcodeToBarcodeDeviceMap = + new LinkedHashMap(); + barcodeDeviceList.stream().forEach(barcodeDevice -> { + barcodeToBarcodeDeviceMap.put(barcodeDevice.getBarcode(), barcodeDevice); }); - if(CollectionUtils.isNotEmpty(barcodeNotMatchBarcodeDeviceList)){ - throw new SystemException(String.format("以下条码系统不存在:【%s】" - ,StringUtils.join(barcodeNotMatchBarcodeDeviceList,","))); + //记录根据条码查找不到条码对象的条码 + List barcodeNotMatchBarcodeDeviceList = new ArrayList(); + if(barcodeList.size() != barcodeDeviceList.size()){ + barcodeList.stream().forEach(barcode -> { + if(!barcodeToBarcodeDeviceMap.containsKey(barcode)){ + barcodeNotMatchBarcodeDeviceList.add(barcode); + } + }); + if(CollectionUtils.isNotEmpty(barcodeNotMatchBarcodeDeviceList)){ + throw new SystemException(String.format("以下条码系统不存在:【%s】" + ,StringUtils.join(barcodeNotMatchBarcodeDeviceList,","))); + } } } @@ -353,10 +356,6 @@ List expensiveDisposablegoodsList = new ArrayList(); //3.条码实例类型为一次性物品批次对象 List disposableGoodsBatchList = new ArrayList(); - /* - * 非法条码集合 - */ - List invalidBarcodeDeviceList = new ArrayList(); //代理灭菌单id对应包实例集合的map.key为代理灭菌单id,value为包实例集合 Map> proxyDisinfectionIdToTousseListMap = @@ -389,6 +388,14 @@ //消毒物品祖先包定义id集合 List disinfectTdAncestorIdList = new ArrayList(); + + /* + * 非法条码集合 + */ + List invalidBarcodeDeviceList = new ArrayList(); + if(barcodeDeviceList == null){ + barcodeDeviceList = new ArrayList(); + } //遍历所有的待发货条码实例对象(唯一条码包实例、固定条码包实例、高值耗材实例、一次性物品批次定义) barcodeDeviceList.stream().forEach(barcodeDevice -> { if(barcodeDevice instanceof TousseInstance){ @@ -599,19 +606,20 @@ } /* - * 3.判断一次性物品高值耗材的一次性物品定义的类型是否不为高值耗材及所属仓库、状态、失效期等是否满足 - * 如不满足,则抛出相关的异常 - * 如满足则返回相关的结果 - */ - validateExpensiveDisposableGoods(expensiveDisposablegoodsList, barcodeToSendAmountMap, sourceWarehouseId, currentDateTime); - - /* * 4.判断一次性物品批次定义的一次性物品定义的类型是否不为普通物品,及失效期、所在仓库的库存等是否满足 * 并锁定对应的标识及返回各批次对应的标识与应发数量的map,后面用这些标识来发货 */ //一次性物品批次定义map(key为一次性物品批次定义id、value为一次性物品批次定义) Map idToDisposableGoodsBatchMap = new LinkedHashMap(); + + /* + * 3.判断一次性物品高值耗材的一次性物品定义的类型是否不为高值耗材及所属仓库、状态、失效期等是否满足 + * 如不满足,则抛出相关的异常 + * 如满足则返回相关的结果 + */ + validateExpensiveDisposableGoods(expensiveDisposablegoodsList, barcodeToSendAmountMap, sourceWarehouseId, currentDateTime,idToDisposableGoodsBatchMap); + Map> batchToIdentificationAmountMap = validateDisposableGoodsBatchAndLockIdentification(disposableGoodsBatchList, barcodeToSendAmountMap, sourceWarehouseId, currentDateTime,idToDisposableGoodsBatchMap); @@ -620,7 +628,7 @@ * 并锁定对应的标识及返回物品定义对应的标识与应发数量的map,后面用这些标识来发货 */ Map> disposableGoodsToIdentificationAmountMap = - validateDisposableGoodsAmountAndLockIdentification(disposableGoodsList, barcodeToSendAmountMap,batchToIdentificationAmountMap, sourceWarehouseId, currentDateTime); + validateDisposableGoodsAmountAndLockIdentification(disposableGoodsList, barcodeToSendAmountMap,batchToIdentificationAmountMap, sourceWarehouseId, currentDateTime,idToDisposableGoodsBatchMap); //聚合包实例对应子包实例集合的map:key为聚合包实例,value为子包实例集合 Map> comboTousseToSubTousseListMap = @@ -854,14 +862,15 @@ /*if(!invoicePlanList.contains(invoicePlan)){ invoicePlanList.add(invoicePlan); }*/ - List> tousseItemMapList = invoicePlanToTousseItemMapListMap.get(invoicePlan); - if(tousseItemMapList == null){ - tousseItemMapList = new ArrayList>(); + //申请项对应的发货对象map的list集合 + List> tousseItemToObjectMapList = invoicePlanToTousseItemMapListMap.get(invoicePlan); + if(tousseItemToObjectMapList == null){ + tousseItemToObjectMapList = new ArrayList>(); } Map tousseItemToObjectMap = new LinkedHashMap(); tousseItemToObjectMap.put(tousseItem, expensiveDgList); - tousseItemMapList.add(tousseItemToObjectMap); - invoicePlanToTousseItemMapListMap.put(invoicePlan, tousseItemMapList); + tousseItemToObjectMapList.add(tousseItemToObjectMap); + invoicePlanToTousseItemMapListMap.put(invoicePlan, tousseItemToObjectMapList); }); } //2.处理申请项对应标识对象与发货数量map的map @@ -875,14 +884,15 @@ if(!invoicePlanList.contains(invoicePlan)){ invoicePlanList.add(invoicePlan); }*/ - List> tousseItemList = invoicePlanToTousseItemMapListMap.get(invoicePlan); - if(tousseItemList == null){ - tousseItemList = new ArrayList>(); + //申请项对应的发货对象map的list集合 + List> tousseItemToObjectMapList = invoicePlanToTousseItemMapListMap.get(invoicePlan); + if(tousseItemToObjectMapList == null){ + tousseItemToObjectMapList = new ArrayList>(); } Map tousseItemToObjectMap = new LinkedHashMap(); tousseItemToObjectMap.put(tousseItem, identiToAmountMapList); - tousseItemList.add(tousseItemToObjectMap); - invoicePlanToTousseItemMapListMap.put(invoicePlan, tousseItemList); + tousseItemToObjectMapList.add(tousseItemToObjectMap); + invoicePlanToTousseItemMapListMap.put(invoicePlan, tousseItemToObjectMapList); }); } //3.处理申请项对应包实例集合的map @@ -895,14 +905,15 @@ if(!invoicePlanList.contains(invoicePlan)){ invoicePlanList.add(invoicePlan); }*/ - List> tousseItemList = invoicePlanToTousseItemMapListMap.get(invoicePlan); - if(tousseItemList == null){ - tousseItemList = new ArrayList>(); + //申请项对应的发货对象map的list集合 + List> tousseItemToObjectMapList = invoicePlanToTousseItemMapListMap.get(invoicePlan); + if(tousseItemToObjectMapList == null){ + tousseItemToObjectMapList = new ArrayList>(); } Map tousseItemToObjectMap = new LinkedHashMap(); tousseItemToObjectMap.put(tousseItem, tousseInstanceList); - tousseItemList.add(tousseItemToObjectMap); - invoicePlanToTousseItemMapListMap.put(invoicePlan, tousseItemList); + tousseItemToObjectMapList.add(tousseItemToObjectMap); + invoicePlanToTousseItemMapListMap.put(invoicePlan, tousseItemToObjectMapList); }); } @@ -1202,12 +1213,22 @@ * @param barcodeToSendAmountMap 条码对应发货数量的map * @param sourceWarehouseId 源仓库 * @param now 当前时间 + * @param idToDisposableGoodsBatchMap id对应一次性物品批次定义的map * @return */ private void validateExpensiveDisposableGoods( List expensiveDisposablegoodsList, - Map barcodeToSendAmountMap , long sourceWarehouseId,Date now){ + Map barcodeToSendAmountMap , long sourceWarehouseId,Date now,Map idToDisposableGoodsBatchMap){ if(CollectionUtils.isNotEmpty(expensiveDisposablegoodsList)){ + List dgList = objectDao.getCollection(DisposableGoodsBatch.class.getSimpleName(), "id", + expensiveDisposablegoodsList.stream().map(edg -> { + return edg.getDisposableGoodsBatchStock().getDisposableGoodsBatchId(); + }).distinct().collect(Collectors.toList())); + if(CollectionUtils.isNotEmpty(dgList)){ + dgList.stream().forEach(dg -> { + idToDisposableGoodsBatchMap.put(dg.getId(), dg); + }); + } //高值耗材条码对应一次性物品定义id的map Map expensiveDisposablegoodsBarcodeToDisposableGoodsIdMap = new LinkedHashMap(); @@ -1243,7 +1264,7 @@ if(CollectionUtils.isEmpty(disposableGoodsOfEgList)){ throw new SystemException("未找到相关的一次性物品定义."); } - if(disposableGoodsOfEgList.size() != expensiveDisposablegoodsBarcodeToDisposableGoodsIdMap.size()){ + if(disposableGoodsOfEgList.size() != expensiveDisposablegoodsBarcodeToDisposableGoodsIdMap.values().stream().distinct().collect(Collectors.toList()).size()){ throw new SystemException("部分高值耗材的一次性物品定义已被删除"); } disposableGoodsOfEgList.stream().forEach(disposableGoods -> { @@ -1375,7 +1396,7 @@ private Map> validateDisposableGoodsAmountAndLockIdentification( List disposableGoodsList,Map barcodeToSendAmountMap, Map> alreadyMatchedBatchToIdentiAmountMap, - long sourceWarehouseId,Date now){ + long sourceWarehouseId,Date now,Map idToDisposableGoodsBatchMap){ if(CollectionUtils.isNotEmpty(disposableGoodsList)){ //一次性物品定义对应"标识对象对应匹配数量map"的map Map> disposableGoodsToIdentificationAmountMap = @@ -1423,13 +1444,16 @@ if(CollectionUtils.isEmpty(batchList)){ throw new SystemException("所有一次性物品的未失效的批次都未找到"); } + batchList.stream().forEach(batch -> { + idToDisposableGoodsBatchMap.put(batch.getId(), batch); + }); //判断一次性物品批次的标识表数量是否够发货数量(然后用内存排序方式对标识号按其批次的失效期先后排序) //查该当前仓库下这些一次性物品定义下有库存数量的标识数据(批次未过期)、alreadyFullMatchIdentificationIdList @SuppressWarnings("unchecked") List identificationList = objectDao.findByCondition_ForUpdate(DisposableGoodsIdentification.class.getSimpleName(), - String.format(" where warehouseID=% and amount > 0 and %s and %s and %s", + String.format(" where warehouseID=%s and amount > 0 and %s and %s", sourceWarehouseId, SqlUtils.getNonStringFieldInLargeCollectionsPredicate("batchStock.disposableGoodsBatchId", batchList.stream().map(DisposableGoodsBatch::getId).collect(Collectors.toList())), @@ -1444,7 +1468,6 @@ batchList.stream().collect(Collectors.groupingBy(DisposableGoodsBatch::getDiposableGoods)); //批次的顺序(key为批次id,value为对应的顺序号) Map batchIdToOrderMap = new LinkedHashMap(); - Map idToDisposableGoodsBatchMap = new LinkedHashMap(); batchList.stream().forEach(batch -> { int mapSize = batchIdToOrderMap.size(); batchIdToOrderMap.put(batch.getId(), mapSize); @@ -1481,10 +1504,13 @@ identificationList.stream().forEach(idft -> { Long identificationId = idft.getId(); Entry entryAlreadyMatched = idToMatchedIdentificationAmountMap.get(identificationId); - DisposableGoodsIdentification matchedIdentification = entryAlreadyMatched.getKey(); - Integer matchedAmount = entryAlreadyMatched.getValue(); - //当前遍历的标识的可用于匹配的剩余数量 - int restAmount = MathTools.sub(matchedIdentification.getAmount(), matchedAmount).intValue(); + int restAmount = idft.getAmount().intValue(); + if(entryAlreadyMatched != null){ + DisposableGoodsIdentification matchedIdentification = entryAlreadyMatched.getKey(); + Integer matchedAmount = entryAlreadyMatched.getValue(); + //当前遍历的标识的可用于匹配的剩余数量 + restAmount = MathTools.sub(matchedIdentification.getAmount(), matchedAmount).intValue(); + } if(restAmount <= 0){ return; } @@ -1513,6 +1539,7 @@ } disposableGoodsToIdentificationAmountMap.put(dg, identificationToAmount); //如果所有批次对应匹配的标识数量都已经满足发货了,则不再循环.目前lambda不支持原for循环的return,break等。。。。 + }); return disposableGoodsToIdentificationAmountMap; } @@ -3492,7 +3519,7 @@ String invoicePlanCondition = buildInvoicePlanCondition(invoicePlanId, departCoding, invoiceGroupByConfig,invoicePlanList, invoiceOrigin, afterRecyclingTousseDeliver,false, hideUnprintedDisposableGoodsInvoicePlan); - String queryCondition = String.format("where %s and (isTerminated or isTerminated <> 1) and sendOutAmount < amount and %s)", + String queryCondition = String.format("where %s and (isTerminated is null or isTerminated <> 1) and sendOutAmount < amount and %s)", invoicePlanCondition, SqlUtils.getNonStringFieldInLargeCollectionsPredicate("po.disposableGoodsId", dgIdToEdgListMap.keySet()) @@ -3513,23 +3540,21 @@ //去除重复 tousseItemList = tousseItemList.stream().distinct().collect(Collectors.toList()); if(CollectionUtils.isNotEmpty(tousseItemList)){ - List restList = null; + List restList = + dgIdToEdgListMap.values().stream().reduce((list1,list2) -> { + List mergeList = new ArrayList(); + if(CollectionUtils.isNotEmpty(list1)){ + mergeList.addAll(list1); + } + if(CollectionUtils.isNotEmpty(list2)){ + mergeList.addAll(list2); + } + return mergeList; + }).orElse(new ArrayList()); + //遍历申请项 for(TousseItem tousseItem : tousseItemList){ - restList = - dgIdToEdgListMap.values().stream().reduce((list1,list2) -> { - List mergeList = new ArrayList(); - if(CollectionUtils.isNotEmpty(list1)){ - mergeList.addAll(list1); - } - if(CollectionUtils.isNotEmpty(list2)){ - mergeList.addAll(list2); - } - return mergeList; - }).orElse(null); - if(CollectionUtils.isNotEmpty(restList)){ - break; - } + //需要发货的数量 int needSendAmount = MathTools.sub(tousseItem.getAmount(), tousseItem.getSendOutAmount()).intValue(); if(needSendAmount <= 0){ @@ -3539,14 +3564,24 @@ Long disposableGoodsId = tousseItem.getDisposableGoodsId(); List edgList = dgIdToEdgListMap.get(disposableGoodsId); if(CollectionUtils.isNotEmpty(edgList)){ + int edgSize = edgList.size(); List needMatchList = new ArrayList(); - List senEdgList = edgList.subList(0, (needSendAmount-1)); + List senEdgList = edgList.subList(0, Math.min(needSendAmount, edgSize)); needMatchList.addAll(senEdgList); tousseItemMatchExpensiveDisposableGoodsListMap.put(tousseItem, needMatchList); - edgList.removeAll(senEdgList); } } - if(CollectionUtils.isNotEmpty(restList)){ + if(CollectionUtils.isNotEmpty(CollectionUtils.subtract(restList, + tousseItemMatchExpensiveDisposableGoodsListMap.values().stream().reduce((list1,list2) -> { + List mergeList = new ArrayList(); + if(CollectionUtils.isNotEmpty(list1)){ + mergeList.addAll(list1); + } + if(CollectionUtils.isNotEmpty(list2)){ + mergeList.addAll(list2); + } + return mergeList; + }).orElse(new ArrayList())))){ throw new SystemException(String.format("以下条码的高值耗材未找到对应发货的申请单,可能已被发货或终止.%s", StringUtils.join(restList.stream().map(ExpensiveDisposablegoods::getBarcode).collect(Collectors.toList()),","))); } @@ -3910,7 +3945,7 @@ barcodeList.add(dg.getBarcode()); idToDisposableGoodsMap.put(dg.getId(), dg); }); - Map> tousseItemMatchTousseInstanceList = + Map> tousseItemMatchIdentiToAmountMapMap = new LinkedHashMap>(); //发货的申请单类型 List invoicePlanList = @@ -3965,7 +4000,7 @@ if(alreadyMatchedAmount != null && alreadyMatchedAmount >= barcodeNeedSendAmount){ continue; } - //每个一次性物品对应的标识与 + //每个一次性物品对应的标识与关联数量的map Map identiToAmountMapFromStock = disposableGoodsToIdentificationAmountMap.get(dg); //剩余待匹配的发货数量 int restWaitMatchSendAmount = needSendAmount; @@ -3978,7 +4013,7 @@ newMatchIdentiToAmountMap.put(entry.getKey(), restWaitMatchSendAmount); entry.setValue(amount-restWaitMatchSendAmount); restWaitMatchSendAmount = 0; - alreadyMatchedAmount += restWaitMatchSendAmount; + alreadyMatchedAmount = MathTools.add(alreadyMatchedAmount, restWaitMatchSendAmount).intValue(); break; } int matchAmount = (restWaitMatchSendAmount-amount); @@ -3987,7 +4022,7 @@ alreadyMatchedAmount += matchAmount; } barcodeAlreadyMatchedSendAmountMap.put(barcode, alreadyMatchedAmount); - tousseItemMatchTousseInstanceList.put(tousseItem, newMatchIdentiToAmountMap); + tousseItemMatchIdentiToAmountMapMap.put(tousseItem, newMatchIdentiToAmountMap); } //如果所有的标识数量都已匹配完申请项时,不再往后循环申请项,跳出循环。否则继续循环后面的tousseItem @@ -3997,7 +4032,7 @@ } } } - return tousseItemMatchTousseInstanceList; + return tousseItemMatchIdentiToAmountMapMap; } return null; } @@ -4402,8 +4437,8 @@ + "disposableGoodsStockId,disposableGoodsType,disposableGoodsType2," + "invoiceID,invoicePlanID,middlePackageAmount,middlePackageUnit," + "settlementDiscountPrice,settlementPrice,subjectCode,tousseDefinitionId,tousseName," - + "tousseType,transferScale,type,wareHouseId,wareHouseName,invoice_id,materialAmount) " - + "values (%s ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", + + "tousseType,transferScale,type,wareHouseId,wareHouseName,invoice_id,materialAmount,expensiveDGBarcode) " + + "values (%s ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", InvoiceItem.class.getSimpleName(),idColumnName,idColumnValue); //申请项map(key为属性名、value为属性值)集合 List> invoiceItemMapList = new ArrayList>(); @@ -4489,17 +4524,17 @@ for(Entry> subEntry : value.entrySet()){ Long batchId = subEntry.getKey(); DisposableGoodsBatch batch = idToDisposableGoodsBatchMap.get(batchId); - DisposableGoods dg = batch.getDiposableGoods(); + /*DisposableGoods dg = batch.getDiposableGoods();*/ List edgList = subEntry.getValue(); if(CollectionUtils.isEmpty(edgList)){ continue; } - Double settlementPrice = 0D; + /*Double settlementPrice = 0D; for(ExpensiveDisposablegoods edg : edgList){ settlementPrice = MathTools.add(edg.getPrice(), settlementPrice).doubleValue(); - } - invoiceItemMap = new LinkedHashMap(); - invoiceItemMap.put("amount", edgList.size()); + }*/ + + /*invoiceItemMap.put("amount", edgList.size()); invoiceItemMap.put("barcode", batch.getBarcode()); invoiceItemMap.put("batchNumber", batch.getBatchNumber()); invoiceItemMap.put("diposable", Constants.STR_YES); @@ -4520,12 +4555,15 @@ invoiceItemMap.put("tousseName", dg.getShowName()); invoiceItemMap.put("tousseType", DisposableGoods.TYPE_NAME); invoiceItemMap.put("transferScale", dg.getTransferScale()); - invoiceItemMap.put("type", Invoice.TYPE_APPLICATION); + invoiceItemMap.put("type", InvoiceItem.TYPE_APPLICATION); invoiceItemMap.put("wareHouseId", params.optLong("sourceWarehouseId")); invoiceItemMap.put("wareHouseName", params.optString("sourceWarehouseName")); invoiceItemMap.put("invoice_id", invoice.getId()); - invoiceItemMap.put("materialAmount", 0); - invoiceItemMapList.add(invoiceItemMap); + invoiceItemMap.put("materialAmount", 0);*/ + for(ExpensiveDisposablegoods expensiveDisposablegoods : edgList){ + invoiceItemMap = buildInvoiceItemMapForExpensiveDisposableGoods(invoice, tousseItem,batch, expensiveDisposablegoods, params, InvoiceItem.TYPE_APPLICATION,UUID.randomUUID().toString()); + invoiceItemMapList.add(invoiceItemMap); + } } } } @@ -4534,22 +4572,37 @@ tousseItemToIdentiToAmountMapMap.entrySet()) { TousseItem tousseItem = entry.getKey(); Invoice invoice = invoicePlanToInvoiceMap.get(tousseItem.getInvoicePlan()); - Map value = entry.getValue(); - if(MapUtils.isEmpty(value)){ + Map identiToAmountMapOfTousseItem = entry.getValue(); + if(MapUtils.isEmpty(identiToAmountMapOfTousseItem)){ continue; } - for(Entry subEntry : value.entrySet()){ - DisposableGoodsIdentification identification = subEntry.getKey(); - DisposableGoodsBatchStock batchStock = identification.getBatchStock(); - Long batchId = batchStock.getDisposableGoodsBatchId(); - DisposableGoodsBatch batch = idToDisposableGoodsBatchMap.get(batchId); - DisposableGoods dg = batch.getDiposableGoods(); - Integer amount = subEntry.getValue(); - if(amount <= 0){ - continue; + //按批次对标识进行分组构造map(key为批次id,value为标识对应数量的map) + Map> batchIdToIdentiToAmountMapMap = + new LinkedHashMap>(); + for(Entry identiToAmountEntry : identiToAmountMapOfTousseItem.entrySet()){ + DisposableGoodsIdentification identification = identiToAmountEntry.getKey(); + Long batchId = identification.getBatchStock().getDisposableGoodsBatchId(); + Map identiToAmountMap = batchIdToIdentiToAmountMapMap.get(batchId); + if(identiToAmountMap == null){ + identiToAmountMap = new HashMap(); } - invoiceItemMap = new LinkedHashMap(); - invoiceItemMap.put("amount", amount); + identiToAmountMap.put(identification, identiToAmountEntry.getValue()); + batchIdToIdentiToAmountMapMap.put(batchId, identiToAmountMap); + } + + for(Entry> batchIdToIdentiToAmountMapEntry : batchIdToIdentiToAmountMapMap.entrySet()){ + Long batchId = batchIdToIdentiToAmountMapEntry.getKey(); + Map identiToAmountMapOfBatchId = batchIdToIdentiToAmountMapEntry.getValue(); + if(MapUtils.isEmpty(identiToAmountMapOfBatchId)){ + break; + } + DisposableGoodsBatch batch = idToDisposableGoodsBatchMap.get(batchId); + invoiceItemMap = buildInvoiceItemMapForNotExpensiveDisposableGoods(invoice, tousseItem, + batch,identiToAmountMapOfBatchId, params, InvoiceItem.TYPE_APPLICATION, UUID.randomUUID().toString()); + invoiceItemMapList.add(invoiceItemMap); + /*DisposableGoods dg = batch.getDiposableGoods();*/ + + /*invoiceItemMap.put("amount", amount); invoiceItemMap.put("barcode", batch.getBarcode()); invoiceItemMap.put("batchNumber", batch.getBatchNumber()); //invoiceItemMap.put("comboTousseInstanceId", ); @@ -4558,7 +4611,7 @@ invoiceItemMap.put("disposableGoodsBatchStockId", batchStock.getId()); invoiceItemMap.put("disposableGoodsId", dg.getId()); //invoiceItemMap.put("disposableGoodsStockId", ); - invoiceItemMap.put("disposableGoodsType", DisposableGoods.TYPE_EXPENSIVEDIPOSABLEGOODS); + invoiceItemMap.put("disposableGoodsType", DisposableGoods.TYPE_DIPOSABLEGOODS); invoiceItemMap.put("disposableGoodsType2", dg.getType()); invoiceItemMap.put("invoiceID", invoice.getId()); invoiceItemMap.put("invoicePlanID", tousseItem.getInvoicePlan().getId()); @@ -4571,12 +4624,11 @@ invoiceItemMap.put("tousseName", dg.getShowName()); invoiceItemMap.put("tousseType", DisposableGoods.TYPE_NAME); invoiceItemMap.put("transferScale", dg.getTransferScale()); - invoiceItemMap.put("type", Invoice.TYPE_APPLICATION); + invoiceItemMap.put("type", InvoiceItem.TYPE_APPLICATION); invoiceItemMap.put("wareHouseId", params.optLong("sourceWarehouseId")); invoiceItemMap.put("wareHouseName", params.optString("sourceWarehouseName")); invoiceItemMap.put("invoice_id", invoice.getId()); - invoiceItemMap.put("materialAmount", 0); - invoiceItemMapList.add(invoiceItemMap); + invoiceItemMap.put("materialAmount", 0);*/ } } } @@ -4595,14 +4647,14 @@ if(CollectionUtils.isEmpty(tiList)){ continue; } - double settlementPrice = 0.0d; + /*double settlementPrice = 0.0d; double settlementDiscountPrice = 0.0d; for (TousseInstance tousseInstance : tiList) { settlementPrice = MathTools.add(settlementPrice, tousseInstance.getPrice()).doubleValue(); settlementDiscountPrice = MathTools.add(settlementDiscountPrice, tousseInstance.getDiscountPrice()).doubleValue(); - } - invoiceItemMap = new LinkedHashMap(); - invoiceItemMap.put("amount", tiList.size()); + }*/ + invoiceItemMap = buildInvoiceItemMapForTousseIntance(invoice,tousseItem,td,tiList,params,InvoiceItem.TYPE_APPLICATION); + /*invoiceItemMap.put("amount", tiList.size()); //invoiceItemMap.put("barcode", ); //invoiceItemMap.put("batchNumber", ); invoiceItemMap.put("ancestorId", td.getAncestorID()); @@ -4624,11 +4676,11 @@ invoiceItemMap.put("tousseName", td.getName()); invoiceItemMap.put("tousseType", td.getTousseType()); //invoiceItemMap.put("transferScale", dg.getTransferScale()); - invoiceItemMap.put("type", Invoice.TYPE_APPLICATION); + invoiceItemMap.put("type", InvoiceItem.TYPE_APPLICATION); invoiceItemMap.put("wareHouseId", params.optLong("sourceWarehouseId")); invoiceItemMap.put("wareHouseName", params.optString("sourceWarehouseName")); invoiceItemMap.put("invoice_id", invoice.getId()); - invoiceItemMap.put("materialAmount", 2);//后面再调整 + invoiceItemMap.put("materialAmount", 2);*///后面再调整 invoiceItemMapList.add(invoiceItemMap); } } @@ -4753,6 +4805,7 @@ }else{ ps.setInt(28, materialAmount); } + ps.setString(29, (String)invoiceItemMap.get("expensiveDGBarcode")); } @Override @@ -4851,6 +4904,157 @@ } /** + * 构造高值材料的发货项map,用于高值材料发货及器械包实例发货时扣减包内的高值耗材时的两个场景调用 + * @param invoice 发货单 + * @param tousseItem 申请项 + * @param batch 批次对象 + * @param edg 高值耗材实例 + * @param params 发货参数 + * @param invoiceItemType 类型 + * @param uuid 唯一标识,用于批量插入后根据uuid找到对应的id + * @return + */ + private Map buildInvoiceItemMapForExpensiveDisposableGoods(Invoice invoice,TousseItem tousseItem, + DisposableGoodsBatch batch,ExpensiveDisposablegoods edg,JSONObject params,String invoiceItemType,String uuid){ + DisposableGoods dg = batch.getDiposableGoods(); + Map invoiceItemMap = new LinkedHashMap(); + invoiceItemMap.put("amount", 1); + invoiceItemMap.put("barcode", batch.getBarcode()); + invoiceItemMap.put("batchNumber", batch.getBatchNumber()); + invoiceItemMap.put("diposable", Constants.STR_YES); + invoiceItemMap.put("disposableGoodsBatchId", batch.getId()); + invoiceItemMap.put("disposableGoodsId", dg.getId()); + invoiceItemMap.put("disposableGoodsType", DisposableGoods.TYPE_EXPENSIVEDIPOSABLEGOODS); + invoiceItemMap.put("disposableGoodsType2", dg.getType()); + invoiceItemMap.put("invoiceID", invoice.getId()); + //如果申请项不空时 + if(tousseItem != null){ + invoiceItemMap.put("invoicePlanID", tousseItem.getInvoicePlan().getId()); + } + invoiceItemMap.put("middlePackageAmount", 1); + invoiceItemMap.put("middlePackageUnit", dg.getMiddlePackageUnit()); + invoiceItemMap.put("settlementDiscountPrice", edg.getPrice()); + invoiceItemMap.put("settlementPrice", edg.getPrice()); + invoiceItemMap.put("tousseName", dg.getShowName()); + invoiceItemMap.put("tousseType", DisposableGoods.TYPE_NAME); + invoiceItemMap.put("transferScale", dg.getTransferScale()); + invoiceItemMap.put("type", invoiceItemType); + invoiceItemMap.put("wareHouseId", params.optLong("sourceWarehouseId")); + invoiceItemMap.put("wareHouseName", params.optString("sourceWarehouseName")); + invoiceItemMap.put("invoice_id", invoice.getId()); + invoiceItemMap.put("materialAmount", 0); + invoiceItemMap.put("expensiveDGBarcode", edg.getBarcode()); + //唯一标识,用于批量插入后根据uuid找到对应的id + invoiceItemMap.put("uuid", uuid); + return invoiceItemMap; + } + + /** + * 构造包实例的发货项map,用于包实例发货时的场景调用 + * @param invoice 发货单 + * @param tousseItem 申请项 + * @param batch 批次对象 + * @param identiToAmountMap 一次性物品标识对应数据的entry + * @param params 发货参数 + * @param invoiceItemType 类型 + * @param uuid 唯一标识,用于批量插入后根据uuid找到对应的id + * @return + */ + private Map buildInvoiceItemMapForNotExpensiveDisposableGoods(Invoice invoice,TousseItem tousseItem, + DisposableGoodsBatch batch,Map identiToAmountMap,JSONObject params,String invoiceItemType,String uuid){ + Integer amount = 0; + double settlementPrice = 0.0d; + DisposableGoods dg = batch.getDiposableGoods(); + DisposableGoodsBatchStock batchStock = null; + if(MapUtils.isNotEmpty(identiToAmountMap)){ + for(Entry identiToAmountEntry : identiToAmountMap.entrySet()){ + amount += identiToAmountEntry.getValue(); + DisposableGoodsIdentification identification = identiToAmountEntry.getKey(); + if(batchStock == null){ + batchStock = identification.getBatchStock(); + } + settlementPrice = MathTools.add(settlementPrice, MathTools.mul(identification.getPrice(), amount)).doubleValue(); + } + } + Map invoiceItemMap = new LinkedHashMap(); + invoiceItemMap.put("amount", amount); + invoiceItemMap.put("barcode", batch.getBarcode()); + invoiceItemMap.put("batchNumber", batch.getBatchNumber()); + //invoiceItemMap.put("comboTousseInstanceId", ); + invoiceItemMap.put("diposable", Constants.STR_YES); + invoiceItemMap.put("disposableGoodsBatchId", batch.getId()); + invoiceItemMap.put("disposableGoodsBatchStockId", batchStock.getId()); + invoiceItemMap.put("disposableGoodsId", dg.getId()); + //invoiceItemMap.put("disposableGoodsStockId", ); + invoiceItemMap.put("disposableGoodsType", DisposableGoods.TYPE_DIPOSABLEGOODS); + invoiceItemMap.put("disposableGoodsType2", dg.getType()); + invoiceItemMap.put("invoiceID", invoice.getId()); + //如果申请项不空时 + if(tousseItem != null){ + invoiceItemMap.put("invoicePlanID", tousseItem.getInvoicePlan().getId()); + } + invoiceItemMap.put("middlePackageAmount", MathTools.div(amount, dg.getTransferScale()).intValue()); + invoiceItemMap.put("middlePackageUnit", dg.getMiddlePackageUnit()); + invoiceItemMap.put("settlementDiscountPrice", settlementPrice); + invoiceItemMap.put("settlementPrice", settlementPrice); + //invoiceItemMap.put("subjectCode", ); + //invoiceItemMap.put("tousseDefinitionId", edgList.size()); + invoiceItemMap.put("tousseName", dg.getShowName()); + invoiceItemMap.put("tousseType", DisposableGoods.TYPE_NAME); + invoiceItemMap.put("transferScale", dg.getTransferScale()); + invoiceItemMap.put("type", invoiceItemType); + invoiceItemMap.put("wareHouseId", params.optLong("sourceWarehouseId")); + invoiceItemMap.put("wareHouseName", params.optString("sourceWarehouseName")); + invoiceItemMap.put("invoice_id", invoice.getId()); + invoiceItemMap.put("materialAmount", 0); + //唯一标识,用于批量插入后根据uuid找到对应的id + invoiceItemMap.put("uuid", uuid); + return invoiceItemMap; + } + + /** + * 构造包实例的发货项map,用于包实例发货时的场景调用 + * @param invoice 发货单 + * @param tousseItem 申请项 + * @param td 包定义 + * @param tiList 包实例集合 + * @param params 发货参数 + * @param invoiceItemType 发货项类型:值有申领发货、自动扣减等 + * @return + */ + private Map buildInvoiceItemMapForTousseIntance(Invoice invoice,TousseItem tousseItem, + TousseDefinition td,List tiList,JSONObject params,String invoiceItemType){ + double settlementPrice = 0.0d; + double settlementDiscountPrice = 0.0d; + int materialAmount = 0; + for (TousseInstance tousseInstance : tiList) { + settlementPrice = MathTools.add(settlementPrice, tousseInstance.getPrice()).doubleValue(); + settlementDiscountPrice = MathTools.add(settlementDiscountPrice, tousseInstance.getDiscountPrice()).doubleValue(); + materialAmount = MathTools.add(materialAmount, tousseInstance.getMaterialAmount()).intValue(); + } + Map invoiceItemMap = new LinkedHashMap(); + invoiceItemMap.put("amount", tiList.size()); + invoiceItemMap.put("ancestorId", td.getAncestorID()); + invoiceItemMap.put("diposable", Constants.STR_NO); + invoiceItemMap.put("invoiceID", invoice.getId()); + //如果申请项不空时 + if(tousseItem != null){ + invoiceItemMap.put("invoicePlanID", tousseItem.getInvoicePlan().getId()); + } + invoiceItemMap.put("settlementDiscountPrice", settlementDiscountPrice); + invoiceItemMap.put("settlementPrice", settlementPrice); + invoiceItemMap.put("tousseDefinitionId", td.getId()); + invoiceItemMap.put("tousseName", td.getName()); + invoiceItemMap.put("tousseType", td.getTousseType()); + invoiceItemMap.put("type", invoiceItemType); + invoiceItemMap.put("wareHouseId", params.optLong("sourceWarehouseId")); + invoiceItemMap.put("wareHouseName", params.optString("sourceWarehouseName")); + invoiceItemMap.put("invoice_id", invoice.getId()); + invoiceItemMap.put("materialAmount", materialAmount); + return invoiceItemMap; + } + + /** * 批量插入一次性物品业务表数据 * @param invoiceToInvoiceItemListMap * @param tousseItemToIdentiToAmountMapMap @@ -4923,15 +5127,21 @@ && StringUtils.equals(invoiceItem.getTousseType(), tousseItem.getTousseType()); }).collect(Collectors.toList()); if(CollectionUtils.isNotEmpty(invoiceItemListOfTousseItem)){ - InvoiceItem invoiceItem = invoiceItemListOfTousseItem.get(0); for(Entry> batchIdToEdgListEntry : batchIdToEdgListMap.entrySet()){ Long batchId = batchIdToEdgListEntry.getKey(); DisposableGoodsBatch batch = idToDisposableGoodsBatchMap.get(batchId); List edgList = batchIdToEdgListEntry.getValue(); if(CollectionUtils.isNotEmpty(edgList)){ for (ExpensiveDisposablegoods expensiveDisposablegoods : edgList) { - Map map = new LinkedHashMap(); - map.put("amount", 1); + InvoiceItem invoiceItem = invoiceItemListOfTousseItem.stream().filter(ii -> { + return StringUtils.equals(ii.getExpensiveDGBarcode(), expensiveDisposablegoods.getBarcode()); + }).findFirst().orElse(null); + if(invoiceItem == null){ + throw new SystemException(String.format("未找到%s的发货项", expensiveDisposablegoods.getBarcode())); + } + Map map = buildDiposableGoodsItemMapForExpensiveDisposableGoods(invoice, invoiceItem, null, + expensiveDisposablegoods, batch,targetBatchIdToDisposableGoodsBatchStockMap, InvoiceItem.TYPE_APPLICATION); + /*map.put("amount", 1); map.put("barcode", batch.getBarcode()); map.put("batch", batch.getBatchNumber()); map.put("fluctuationPrice", expensiveDisposablegoods.getPrice()); @@ -4947,7 +5157,7 @@ map.put("expensiveDGBarcode", expensiveDisposablegoods.getBarcode()); map.put("type", InvoiceItem.TYPE_APPLICATION); map.put("name", batch.getDiposableGoods().getShowName()); - //map.put("targetIdentificationId", value); + //map.put("targetIdentificationId", value);*/ mapList.add(map); } } @@ -4983,11 +5193,13 @@ DisposableGoodsIdentification identi = identiToAmountEntry.getKey(); Long batchId = identi.getDisposableGoodsBatchID(); DisposableGoodsBatch batch = idToDisposableGoodsBatchMap.get(batchId); - Long dgId = batch.getDiposableGoods().getId(); + /*Long dgId = batch.getDiposableGoods().getId();*/ Integer amount = identiToAmountEntry.getValue(); if(amount != null && amount.intValue() > 0){ - Map map = new LinkedHashMap(); - map.put("amount", identiToAmountEntry.getValue()); + Map map = buildDiposableGoodsItemMapForNotExpensiveDisposableGoods(invoice, invoiceItem, null, + identi, batch, sourceBatchIdToDisposableGoodsBatchStockMap, sourceDgIdToDisposableGoodsStockMap, + ancestorIdToIdentificationMap, identiToAmountEntry, InvoiceItem.TYPE_APPLICATION); +/* map.put("amount", identiToAmountEntry.getValue()); map.put("barcode", batch.getBarcode()); map.put("batch", batch.getBatchNumber()); map.put("fluctuationPrice", identi.getPrice()); @@ -5006,7 +5218,7 @@ if(targetIdentification != null){ map.put("targetIdentificationId", targetIdentification.getId()); } - map.put("name", batch.getDiposableGoods().getShowName()); + map.put("name", batch.getDiposableGoods().getShowName());*/ mapList.add(map); } } @@ -5109,6 +5321,90 @@ } /** + * 构造高耗耗材的一次性物品项map,用于高耗耗材发货、器械包发货扣减包内耗材两处场景调用 + * @param invoice 发货单 + * @param invoiceItem 发货项 + * @param invoiceItemUUID 发货项的UUID + * @param expensiveDisposablegoods 高值耗材实例 + * @param batch 批次定义 + * @param targetBatchIdToDisposableGoodsBatchStockMap 目标"批次定义对应批次库存"map + * @param invoiceItemType 业务项类型 + * @return + */ + private Map buildDiposableGoodsItemMapForExpensiveDisposableGoods(Invoice invoice, InvoiceItem invoiceItem,String invoiceItemUUID, + ExpensiveDisposablegoods expensiveDisposablegoods,DisposableGoodsBatch batch, + Map targetBatchIdToDisposableGoodsBatchStockMap,String invoiceItemType){ + Map map = new LinkedHashMap(); + Long batchId = batch.getId(); + map.put("amount", 1); + map.put("barcode", batch.getBarcode()); + map.put("batch", batch.getBatchNumber()); + map.put("fluctuationPrice", expensiveDisposablegoods.getPrice()); + map.put("price", expensiveDisposablegoods.getPrice()); + map.put("invoice_id", invoice.getId()); + if(invoiceItem != null && DatabaseUtil.isPoIdValid(invoiceItem.getId())){ + map.put("invoiceItemID", invoiceItem.getId()); + } + map.put("invoiceItemUUID", invoiceItemUUID); + map.put("disposableGoodsBatchID", batchId); + map.put("disposableGoodsBatchStockID", targetBatchIdToDisposableGoodsBatchStockMap.get(batchId).getId()); + map.put("disposableGoodsID", expensiveDisposablegoods.getDisposableGoodsID()); + map.put("disposableGoodsStockID", expensiveDisposablegoods.getDisposableGoodsStockID()); + map.put("expensiveDisposablegoodsId", expensiveDisposablegoods.getId()); + map.put("expensiveDGBarcode", expensiveDisposablegoods.getBarcode()); + map.put("type", invoiceItemType); + map.put("name", batch.getDiposableGoods().getShowName()); + return map; + } + + /** + * 构造高耗耗材的一次性物品项map,用于一次性物品批次发货、器械包发货扣减包内耗材两处场景调用 + * @param invoice 发货单 + * @param invoiceItem 发货项 + * @param invoiceItemUUID 发货项的UUID + * @param identi 发货的一次性物品标识 + * @param batch 批次定义 + * @param sourceBatchIdToDisposableGoodsBatchStockMap 一次性物品源批次id对应批次库存的map + * @param sourceDgIdToDisposableGoodsStockMap 一次性物品源定义id对应库存的map + * @param ancestorIdToIdentificationMap + * @param identiToAmountEntry 标识对应扣减数量的entry + * @param invoiceItemType 业务项类型 + * @return + */ + private Map buildDiposableGoodsItemMapForNotExpensiveDisposableGoods(Invoice invoice, InvoiceItem invoiceItem,String invoiceItemUUID, + DisposableGoodsIdentification identi,DisposableGoodsBatch batch,Map sourceBatchIdToDisposableGoodsBatchStockMap, + Map sourceDgIdToDisposableGoodsStockMap,Map ancestorIdToIdentificationMap, + Entry identiToAmountEntry,String invoiceItemType){ + Map map = new LinkedHashMap(); + Long batchId = batch.getId(); + Long dgId = batch.getDiposableGoods().getId(); + map.put("amount", identiToAmountEntry.getValue()); + map.put("barcode", batch.getBarcode()); + map.put("batch", batch.getBatchNumber()); + map.put("fluctuationPrice", identi.getPrice()); + map.put("price", identi.getPrice()); + map.put("invoice_id", invoice.getId()); + map.put("identificationID", identi.getId()); + if(invoiceItem != null && DatabaseUtil.isPoIdValid(invoiceItem.getId())){ + map.put("invoiceItemID", invoiceItem.getId()); + } + map.put("invoiceItemUUID", invoiceItemUUID); + map.put("disposableGoodsBatchID", batchId); + map.put("disposableGoodsBatchStockID", sourceBatchIdToDisposableGoodsBatchStockMap.get(batchId).getId()); + map.put("disposableGoodsID", dgId); + map.put("disposableGoodsStockID", sourceDgIdToDisposableGoodsStockMap.get(dgId).getId()); + map.put("type", invoiceItemType); + if(ancestorIdToIdentificationMap != null){ + DisposableGoodsIdentification targetIdentification = ancestorIdToIdentificationMap.get(identi.getId()); + if(targetIdentification != null){ + map.put("targetIdentificationId", targetIdentification.getId()); + } + } + map.put("name", batch.getDiposableGoods().getShowName()); + return map; + } + + /** * 批量修改器械包实例表数据 * @param invoiceToInvoiceItemListMap * @param tousseItemToTdToTiListMapMap @@ -6633,7 +6929,7 @@ * @param tousseInstanceList 包实例集合 * @param disposableGoodsStorageAdjustVoTotalList 需要回写的对象 */ - /*private void tousseInstanceAutoDeduction( + private void tousseInstanceAutoDeduction( Map>> tousseItemToTdToTiListMapMap, Map invoicePlanToInvoiceMap, OrgUnit orgUnit,WareHouse targetWarehouse,JSONObject params,Date currentDateTime, @@ -6644,7 +6940,7 @@ //需要扣减包内一次性物品库存的map,key为发货单对象,value为包定义对应包实例集合的map Map>> invoiceToTdToTiListMapMapForOutStock = new HashMap>>(); - //包定义(消毒物品为包实例对应的包定义)对应的一次性物品库存扣减数量 + //包定义(消毒物品为包实例对应的包定义)对应的一次性物品库存扣减数量(包括所有待扣减耗材库存的包) Map> tdToDgToOutStockAmountMapMap = new HashMap>(); tousseItemToTdToTiListMapMap.entrySet().stream().forEach(entry -> { @@ -6687,79 +6983,166 @@ } }); if(MapUtils.isNotEmpty(invoiceToTdToTiListMapMapForOutStock)){ + List identificationList = new ArrayList(); + List expensiveDisposablegoodsList = new ArrayList(); + Map idToDisposableGoodsMap = new HashMap(); + Map idToDisposableGoodsStockMap = new HashMap(); + Map dgIdToDisposableGoodsStockMap = new HashMap(); + Map idToDisposableGoodsBatchMap = new HashMap(); + Map idToDisposableGoodsBatchStockMap = new HashMap(); + Map batchIdToDisposableGoodsBatchStockMap = new HashMap(); + //锁定要扣减的一次性物品相关的数据(为高值耗材则锁定高值耗材实例、否则锁定标识表数据) + lockAndFetchDisposableGoodsRelativeOutStockData(invoiceToTdToTiListMapMapForOutStock, tdToDgToOutStockAmountMapMap, + params.optLong("sourceWarehouseId"), identificationList, expensiveDisposablegoodsList, + idToDisposableGoodsMap,idToDisposableGoodsStockMap,idToDisposableGoodsBatchMap,idToDisposableGoodsBatchStockMap, + dgIdToDisposableGoodsStockMap,batchIdToDisposableGoodsBatchStockMap); + List> invoiceItemMapList = new ArrayList>(); List> diposableGoodsItemMapList = new ArrayList>(); + + //剩余待扣减的高值耗材实例与标识数据,即可扣减的高值耗材实例与标识数据(key为一次性物品定义id,value为高值耗 材实例集合) + Map> restWaitOutStockDgIdToExpensiveDisposablegoodsListMap = new HashMap>(); + Map> restWaitOutStockDgIdToIdentiToAmountMapMap = + new HashMap>(); + expensiveDisposablegoodsList.forEach(expensiveDisposablegoods -> { + Long dgId = expensiveDisposablegoods.getDisposableGoodsBatchStock().getDiposableGoods().getDisposableGoodsID(); + List edgList = restWaitOutStockDgIdToExpensiveDisposablegoodsListMap.get(dgId); + if(edgList == null){ + edgList = new ArrayList(); + } + edgList.add(expensiveDisposablegoods); + restWaitOutStockDgIdToExpensiveDisposablegoodsListMap.put(dgId, edgList); + }); + identificationList.stream().forEach(identification -> { + Long amount = identification.getAmount(); + Long dgId = identification.getBatchStock().getDiposableGoods().getDisposableGoodsID(); + Map identiToAmountMap = restWaitOutStockDgIdToIdentiToAmountMapMap.get(dgId); + if(identiToAmountMap == null){ + identiToAmountMap = new HashMap(); + } + identiToAmountMap.put(identification, amount.intValue()); + restWaitOutStockDgIdToIdentiToAmountMapMap.put(dgId, identiToAmountMap); + }); + + //本次发货用于扣减的高值耗材及标识数据 (后续进行高值耗材实例状态、各库存数据的更新 + List edgListForInvoiceOutStock = new ArrayList(); + Map identificationToOutStockAmountMapForInvoiceOutStock = new HashMap(); + //uuid的集合 + List invoiceItemUUIDList = new ArrayList(); invoiceToTdToTiListMapMapForOutStock.entrySet().stream().forEach(entry -> { Invoice invoice = entry.getKey(); Map> tdToTiListMap = entry.getValue(); tdToTiListMap.entrySet().stream().forEach(entry2 -> { + List tiList = entry2.getValue(); + if(CollectionUtils.isEmpty(tiList)){ + return; + } + int tiAmount = tiList.size(); + TousseDefinition td = entry2.getKey(); //一次性物品对应的扣减数量map Map dgToOutStockAmountMap = tdToDgToOutStockAmountMapMap.get(td); - List tiList = entry2.getValue(); - Map invoiceItemMap = new LinkedHashMap(); - invoiceItemMap.put("amount", tiList.size()); - //invoiceItemMap.put("barcode", ); - //invoiceItemMap.put("batchNumber", ); - invoiceItemMap.put("ancestorId", td.getAncestorID()); - invoiceItemMap.put("diposable", Constants.STR_NO); - //invoiceItemMap.put("disposableGoodsBatchId", batchId); - //invoiceItemMap.put("disposableGoodsBatchStockId", ); - //invoiceItemMap.put("disposableGoodsId", dg.getId()); - //invoiceItemMap.put("disposableGoodsStockId", ); - //invoiceItemMap.put("disposableGoodsType", DisposableGoods.TYPE_EXPENSIVEDIPOSABLEGOODS); - //invoiceItemMap.put("disposableGoodsType2", dg.getType()); - invoiceItemMap.put("invoiceID", invoice.getId()); - invoiceItemMap.put("invoicePlanID", invoice.getInvoicePlan().getId()); - //invoiceItemMap.put("middlePackageAmount", MathTools.div(edgList.size(), dg.getTransferScale()).intValue()); - //invoiceItemMap.put("middlePackageUnit", dg.getMiddlePackageUnit()); - invoiceItemMap.put("settlementDiscountPrice", settlementDiscountPrice); - invoiceItemMap.put("settlementPrice", settlementPrice); - //invoiceItemMap.put("subjectCode", ); - invoiceItemMap.put("tousseDefinitionId", td.getId()); - invoiceItemMap.put("tousseName", td.getName()); - invoiceItemMap.put("tousseType", td.getTousseType()); - //invoiceItemMap.put("transferScale", dg.getTransferScale()); - invoiceItemMap.put("type", Invoice.TYPE_APPLICATION); - invoiceItemMap.put("wareHouseId", params.optLong("sourceWarehouseId")); - invoiceItemMap.put("wareHouseName", params.optString("sourceWarehouseName")); - invoiceItemMap.put("invoice_id", invoice.getId()); - invoiceItemMap.put("materialAmount", 2);//后面再调整 - invoiceItemMapList.add(invoiceItemMap); - Map diposableGoodsItemMap = new LinkedHashMap(); - diposableGoodsItemMap.put("amount", identiToAmountEntry.getValue()); - diposableGoodsItemMap.put("barcode", batch.getBarcode()); - diposableGoodsItemMap.put("batch", batch.getBatchNumber()); - diposableGoodsItemMap.put("fluctuationPrice", identi.getPrice()); - diposableGoodsItemMap.put("price", identi.getPrice()); - diposableGoodsItemMap.put("invoice_id", invoice.getId()); - diposableGoodsItemMap.put("identificationID", identi.getId()); - diposableGoodsItemMap.put("invoiceItemID", invoiceItem.getId()); - diposableGoodsItemMap.put("disposableGoodsBatchID", batchId); - diposableGoodsItemMap.put("disposableGoodsBatchStockID", sourceBatchIdToDisposableGoodsBatchStockMap.get(batchId).getId()); - diposableGoodsItemMap.put("disposableGoodsID", dgId); - diposableGoodsItemMap.put("disposableGoodsStockID", sourceDgIdToDisposableGoodsStockMap.get(dgId).getId()); -// map.put("expensiveDisposablegoodsId", expensiveDisposablegoods.getId()); -// map.put("expensiveDGBarcode", expensiveDisposablegoods.getBarcode()); - diposableGoodsItemMap.put("type", InvoiceItem.TYPE_APPLICATION); - DisposableGoodsIdentification targetIdentification = ancestorIdToIdentificationMap.get(identi.getId()); - if(targetIdentification != null){ - diposableGoodsItemMap.put("targetIdentificationId", targetIdentification.getId()); - } - diposableGoodsItemMap.put("name", batch.getDiposableGoods().getShowName()); - diposableGoodsItemMapList.add(diposableGoodsItemMap); + //遍历器械包对应要扣减的一次性物品(高值耗材:发货项及业务项粒度均到高值耗材实例这层;非高值耗材:发货项粒度到批次、业务项粒度到标识) + dgToOutStockAmountMap.entrySet().stream().forEach(entryDgToOutStockAmount -> { + DisposableGoods dg = entryDgToOutStockAmount.getKey(); + Integer outStockAmount = entryDgToOutStockAmount.getValue() * tiAmount; + Long dgId = dg.getId(); + //高值耗材 + if(dg.expensiveDiposablegoods()){ + List edgList = restWaitOutStockDgIdToExpensiveDisposablegoodsListMap.get(dgId); + if(edgList.size() < outStockAmount){ + throw new SystemException(String.format("【%s】库存不足,需扣减数量%s,可扣减数量%s", + dg.getShowName(), outStockAmount, edgList.size())); + } + List outStockEdgList = new ArrayList(); + List fetchEdgList = edgList.subList(0, outStockAmount); + outStockEdgList.addAll(fetchEdgList); + edgList.removeAll(fetchEdgList); + restWaitOutStockDgIdToExpensiveDisposablegoodsListMap.put(dgId, outStockEdgList); + outStockEdgList.stream().forEach(expensiveDisposablegoods -> { + DisposableGoodsBatchStock batchStock = expensiveDisposablegoods.getDisposableGoodsBatchStock(); + DisposableGoodsBatch batch = idToDisposableGoodsBatchMap.get(batchStock.getDisposableGoodsBatchId()); + String invoiceItemUUID = UUID.randomUUID().toString(); + //添加发货项的map + invoiceItemMapList.add(buildInvoiceItemMapForExpensiveDisposableGoods(invoice, null, batch, expensiveDisposablegoods, params, InvoiceItem.TYPE_AUTO_DEDUCTION,invoiceItemUUID)); + //添加一次性物品业务项的map + diposableGoodsItemMapList.add(buildDiposableGoodsItemMapForExpensiveDisposableGoods(invoice, null , invoiceItemUUID, expensiveDisposablegoods, batch, + null, InvoiceItem.TYPE_AUTO_DEDUCTION)); + invoiceItemUUIDList.add(invoiceItemUUID); + edgListForInvoiceOutStock.add(expensiveDisposablegoods); + }); + }else{ + //非高值耗材 + Map identiToAmountMap = restWaitOutStockDgIdToIdentiToAmountMapMap.get(dgId); + int alreayOutStockAmount = 0; + int restOutStockAmount = outStockAmount; + String invoiceItemUUID = UUID.randomUUID().toString(); + //批次定义对应的"标识对应扣减数量map"的map + Map> batchToIdentiToAmountMapMap = + new LinkedHashMap>(); + for(Entry identiToAmountEntry : identiToAmountMap.entrySet()){ + DisposableGoodsIdentification identification = identiToAmountEntry.getKey(); + DisposableGoodsBatch batch = idToDisposableGoodsBatchMap.get(identification.getBatchStock().getId()); + Map identiToAmountMapOfBatch = batchToIdentiToAmountMapMap.get(batch); + if(identiToAmountMapOfBatch != null){ + identiToAmountMapOfBatch = new LinkedHashMap(); + } + identiToAmountMapOfBatch.put(identification,identiToAmountEntry.getValue()); + batchToIdentiToAmountMapMap.put(batch, identiToAmountMapOfBatch); + } + for(Entry> batchToIdentiToAmountMapEntry : batchToIdentiToAmountMapMap.entrySet()){ + DisposableGoodsBatch batch = batchToIdentiToAmountMapEntry.getKey(); + Map identiToAmountMapOfBatch = batchToIdentiToAmountMapEntry.getValue(); + boolean finishLoop = false; + for(Entry identiToAmountEntryOfBatch : identiToAmountMapOfBatch.entrySet()){ + DisposableGoodsIdentification identification = identiToAmountEntryOfBatch.getKey(); + Integer amount = identiToAmountEntryOfBatch.getValue(); + if(amount >= restOutStockAmount){ + alreayOutStockAmount += restOutStockAmount; + restOutStockAmount = 0; + identiToAmountMap.put(identification, amount - restOutStockAmount); + identificationToOutStockAmountMapForInvoiceOutStock.put(identification, restOutStockAmount); + diposableGoodsItemMapList.add(buildDiposableGoodsItemMapForNotExpensiveDisposableGoods(invoice, null, invoiceItemUUID, identification, batch, + batchIdToDisposableGoodsBatchStockMap, dgIdToDisposableGoodsStockMap, + null, identiToAmountEntryOfBatch, InvoiceItem.TYPE_AUTO_DEDUCTION)); + finishLoop = true; + break; + }else{ + restOutStockAmount = restOutStockAmount - amount; + alreayOutStockAmount += amount; + identiToAmountMap.put(identification, 0); + identificationToOutStockAmountMapForInvoiceOutStock.put(identification, amount); + diposableGoodsItemMapList.add(buildDiposableGoodsItemMapForNotExpensiveDisposableGoods(invoice, null, invoiceItemUUID, identification, batch, + batchIdToDisposableGoodsBatchStockMap, dgIdToDisposableGoodsStockMap, + null, identiToAmountEntryOfBatch, InvoiceItem.TYPE_AUTO_DEDUCTION)); + } + } + //添加发货项的map + invoiceItemMapList.add(buildInvoiceItemMapForNotExpensiveDisposableGoods(invoice, null, batch, identiToAmountMapOfBatch, params, InvoiceItem.TYPE_AUTO_DEDUCTION, invoiceItemUUID)); + invoiceItemUUIDList.add(invoiceItemUUID); + if(finishLoop){ + break; + } + } + if(alreayOutStockAmount < outStockAmount){ + throw new SystemException(String.format("【%s】库存不足,需扣减数量%s,可扣减数量%s", + dg.getShowName(), outStockAmount, alreayOutStockAmount)); + } + } + }); }); }); + //插入发货项及一次性物品业务项数据 if(CollectionUtils.isNotEmpty(invoiceItemMapList)){ String insertIntoInvoiceItemBatchSql = String.format( "insert into %s(%s amount,ancestorId,barcode,batchNumber,comboTousseInstanceId," + "diposable,disposableGoodsBatchId,disposableGoodsBatchStockId,disposableGoodsId," + "disposableGoodsStockId,disposableGoodsType,disposableGoodsType2," + "invoiceID,invoicePlanID,middlePackageAmount,middlePackageUnit," + "settlementDiscountPrice,settlementPrice,subjectCode,tousseDefinitionId,tousseName," - + "tousseType,transferScale,type,wareHouseId,wareHouseName,invoice_id,materialAmount) " - + "values (%s ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", + + "tousseType,transferScale,type,wareHouseId,wareHouseName,invoice_id,materialAmount,expensiveDGBarcode,uuid) " + + "values (%s ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", InvoiceItem.class.getSimpleName(),idColumnName,idColumnValue); jdbcTemplate.batchUpdate(insertIntoInvoiceItemBatchSql, new BatchPreparedStatementSetter() { @@ -6880,116 +7263,364 @@ }else{ ps.setInt(28, materialAmount); } + ps.setString(29, (String)invoiceItemMap.get("expensiveDGBarcode")); + ps.setString(30, (String)invoiceItemMap.get("uuid")); } @Override public int getBatchSize() { return invoiceItemMapList.size(); } }); - } - if(CollectionUtils.isNotEmpty(diposableGoodsItemMapList)){ - String insertIntoDiposableGoodsItemBatchSql = String.format( - "insert into %s(%s amount,barcode,batch,fluctuationPrice,name,price,invoice_id," - + "identificationID,invoiceItemID,disposableGoodsBatchID,disposableGoodsBatchStockID," - + "disposableGoodsID,disposableGoodsStockID,expensiveDisposablegoodsId,expensiveDGBarcode," - + "tousseInstanceId,type,targetIdentificationId) values (%s ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", - DiposableGoodsItem.class.getSimpleName(),idColumnName,idColumnValue); + + //根据uuid查找出刚刚入库的invoiceItem,从而取到对应的id + String queryInvoiceItemSql = String.format("select id,uuid from %s where %s", InvoiceItem.class.getSimpleName(), + SqlUtils.getStringFieldInLargeCollectionsPredicate("uuid", invoiceItemUUIDList)); + List> invoiceItemResultMapResultList = jdbcTemplate.queryForList(queryInvoiceItemSql); + //uuid对应发货项id的map + Map uuidToInvoiceItemIdMap = new HashMap(); + if(CollectionUtils.isNotEmpty(invoiceItemResultMapResultList)){ + for (Map invoiceItemMapResult : invoiceItemResultMapResultList) { + uuidToInvoiceItemIdMap.put((String)invoiceItemMapResult.get("uuid"),(Long)invoiceItemMapResult.get("id")); + } + } - jdbcTemplate.batchUpdate(insertIntoDiposableGoodsItemBatchSql, new BatchPreparedStatementSetter() { + if(CollectionUtils.isNotEmpty(diposableGoodsItemMapList)){ + String insertIntoDiposableGoodsItemBatchSql = String.format( + "insert into %s(%s amount,barcode,batch,fluctuationPrice,name,price,invoice_id," + + "identificationID,invoiceItemID,disposableGoodsBatchID,disposableGoodsBatchStockID," + + "disposableGoodsID,disposableGoodsStockID,expensiveDisposablegoodsId,expensiveDGBarcode," + + "tousseInstanceId,type,targetIdentificationId) values (%s ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", + DiposableGoodsItem.class.getSimpleName(),idColumnName,idColumnValue); - @Override - public void setValues(PreparedStatement ps, int i) throws SQLException { - Map map = diposableGoodsItemMapList.get(i); - ps.setInt(1, (Integer)map.get("amount")); - ps.setString(2, (String)map.get("barcode")); - ps.setString(3, (String)map.get("batch")); - Double fluctuationPrice = (Double)map.get("fluctuationPrice"); - if(fluctuationPrice != null){ - ps.setDouble(4, fluctuationPrice); - }else{ - ps.setNull(4, Types.DOUBLE); + jdbcTemplate.batchUpdate(insertIntoDiposableGoodsItemBatchSql, new BatchPreparedStatementSetter() { + + @Override + public void setValues(PreparedStatement ps, int i) throws SQLException { + Map map = diposableGoodsItemMapList.get(i); + ps.setInt(1, (Integer)map.get("amount")); + ps.setString(2, (String)map.get("barcode")); + ps.setString(3, (String)map.get("batch")); + Double fluctuationPrice = (Double)map.get("fluctuationPrice"); + if(fluctuationPrice != null){ + ps.setDouble(4, fluctuationPrice); + }else{ + ps.setNull(4, Types.DOUBLE); + } + ps.setString(5, (String)map.get("name")); + Double price = (Double)map.get("price"); + if(price != null){ + ps.setDouble(6, price); + }else{ + ps.setNull(6, Types.DOUBLE); + } + Long invoiceId = (Long)map.get("invoice_id"); + if(invoiceId != null){ + ps.setLong(7, invoiceId); + }else{ + ps.setNull(7, Types.BIGINT); + } + Long identificationID = (Long)map.get("identificationID"); + if(identificationID != null){ + ps.setLong(8, identificationID); + }else{ + ps.setNull(8, Types.BIGINT); + } + Long invoiceItemID = (Long)map.get("invoiceItemID"); + if(invoiceItemID == null){ + invoiceItemID = uuidToInvoiceItemIdMap.get(map.get("uuid")); + } + if(invoiceItemID != null){ + ps.setLong(9, invoiceItemID); + }else{ + ps.setNull(9, Types.BIGINT); + } + Long disposableGoodsBatchID = (Long)map.get("disposableGoodsBatchID"); + if(disposableGoodsBatchID != null){ + ps.setLong(10, disposableGoodsBatchID); + }else{ + ps.setNull(10, Types.BIGINT); + } + Long disposableGoodsBatchStockID = (Long)map.get("disposableGoodsBatchStockID"); + if(disposableGoodsBatchStockID != null){ + ps.setLong(11, disposableGoodsBatchStockID); + }else{ + ps.setNull(11, Types.BIGINT); + } + Long disposableGoodsID = (Long)map.get("disposableGoodsID"); + if(disposableGoodsID != null){ + ps.setLong(12, disposableGoodsID); + }else{ + ps.setNull(12, Types.BIGINT); + } + Long disposableGoodsStockID = (Long)map.get("disposableGoodsStockID"); + if(disposableGoodsStockID != null){ + ps.setLong(13, disposableGoodsStockID); + }else{ + ps.setNull(13, Types.BIGINT); + } + Long expensiveDisposablegoodsId = (Long)map.get("expensiveDisposablegoodsId"); + if(expensiveDisposablegoodsId != null){ + ps.setLong(14, expensiveDisposablegoodsId); + }else{ + ps.setNull(14, Types.BIGINT); + } + ps.setString(15, (String)map.get("expensiveDGBarcode")); + Long tousseInstanceId = (Long)map.get("tousseInstanceId"); + if(tousseInstanceId != null){ + ps.setLong(16, tousseInstanceId); + }else{ + ps.setNull(16, Types.BIGINT); + } + ps.setString(17, (String)map.get("type")); + Long targetIdentificationId = (Long)map.get("targetIdentificationId"); + if(targetIdentificationId != null){ + ps.setLong(18, targetIdentificationId); + }else{ + ps.setNull(18, Types.BIGINT); + } } - ps.setString(5, (String)map.get("name")); - Double price = (Double)map.get("price"); - if(price != null){ - ps.setDouble(6, price); - }else{ - ps.setNull(6, Types.DOUBLE); + + @Override + public int getBatchSize() { + // TODO Auto-generated method stub + return diposableGoodsItemMapList.size(); } - Long invoiceId = (Long)map.get("invoice_id"); - if(invoiceId != null){ - ps.setLong(7, invoiceId); - }else{ - ps.setNull(7, Types.BIGINT); - } - Long identificationID = (Long)map.get("identificationID"); - if(identificationID != null){ - ps.setLong(8, identificationID); - }else{ - ps.setNull(8, Types.BIGINT); - } - Long invoiceItemID = (Long)map.get("invoiceItemID"); - if(invoiceItemID != null){ - ps.setLong(9, invoiceItemID); - }else{ - ps.setNull(9, Types.BIGINT); - } - Long disposableGoodsBatchID = (Long)map.get("disposableGoodsBatchID"); - if(disposableGoodsBatchID != null){ - ps.setLong(10, disposableGoodsBatchID); - }else{ - ps.setNull(10, Types.BIGINT); - } - Long disposableGoodsBatchStockID = (Long)map.get("disposableGoodsBatchStockID"); - if(disposableGoodsBatchStockID != null){ - ps.setLong(11, disposableGoodsBatchStockID); - }else{ - ps.setNull(11, Types.BIGINT); - } - Long disposableGoodsID = (Long)map.get("disposableGoodsID"); - if(disposableGoodsID != null){ - ps.setLong(12, disposableGoodsID); - }else{ - ps.setNull(12, Types.BIGINT); - } - Long disposableGoodsStockID = (Long)map.get("disposableGoodsStockID"); - if(disposableGoodsStockID != null){ - ps.setLong(13, disposableGoodsStockID); - }else{ - ps.setNull(13, Types.BIGINT); - } - Long expensiveDisposablegoodsId = (Long)map.get("expensiveDisposablegoodsId"); - if(expensiveDisposablegoodsId != null){ - ps.setLong(14, expensiveDisposablegoodsId); - }else{ - ps.setNull(14, Types.BIGINT); - } - ps.setString(15, (String)map.get("expensiveDGBarcode")); - Long tousseInstanceId = (Long)map.get("tousseInstanceId"); - if(tousseInstanceId != null){ - ps.setLong(16, tousseInstanceId); - }else{ - ps.setNull(16, Types.BIGINT); - } - ps.setString(17, (String)map.get("type")); - Long targetIdentificationId = (Long)map.get("targetIdentificationId"); - if(targetIdentificationId != null){ - ps.setLong(18, targetIdentificationId); - }else{ - ps.setNull(18, Types.BIGINT); - } + }); + } + } + + //高值耗材料实例的状态修改:由已入库改为已领用,并记录对应批次库存及库存的扣减数量 + Map batchStockToAdjustAmountMap = new HashMap(); + Map stockToAdjustAmountMap = new HashMap(); + if(CollectionUtils.isNotEmpty(edgListForInvoiceOutStock)){ + edgListForInvoiceOutStock.forEach(edg -> { + DisposableGoodsBatchStock batchStock = edg.getDisposableGoodsBatchStock(); + batchStockToAdjustAmountMap.put(batchStock, MathTools.add(batchStockToAdjustAmountMap.get(batchStock), 1).intValue()); + DisposableGoodsStock stock = batchStock.getDiposableGoods(); + stockToAdjustAmountMap.put(stock, MathTools.add(stockToAdjustAmountMap.get(stock), 1).intValue()); + }); + jdbcTemplate.update(String.format("update %s set status='%s' where %s", + ExpensiveDisposablegoods.class.getSimpleName(),ExpensiveDisposablegoods.STATUS_IN_WAREHOUSE, + SqlUtils.getNonStringFieldInLargeCollectionsPredicate("id", edgListForInvoiceOutStock.stream().map(ExpensiveDisposablegoods::getId).collect(Collectors.toList())))); + } + if(MapUtils.isNotEmpty(identificationToOutStockAmountMapForInvoiceOutStock)){ + identificationToOutStockAmountMapForInvoiceOutStock.entrySet().forEach(entry -> { + DisposableGoodsBatchStock batchStock = entry.getKey().getBatchStock(); + Integer adjustAmount = entry.getValue(); + batchStockToAdjustAmountMap.put(batchStock, MathTools.add(batchStockToAdjustAmountMap.get(batchStock), adjustAmount).intValue()); + DisposableGoodsStock stock = batchStock.getDiposableGoods(); + stockToAdjustAmountMap.put(stock, MathTools.add(stockToAdjustAmountMap.get(stock), adjustAmount).intValue()); + }); + } + + //对批次库存及库存进行相应的扣减调整 + if(MapUtils.isNotEmpty(batchStockToAdjustAmountMap)){ + String updateDisposableGoodsStockDecreaseBatchSql = String.format( + "update %s set storage=storage-? where id=?", + DisposableGoodsBatchStock.class.getSimpleName()); + jdbcTemplate.batchUpdate(updateDisposableGoodsStockDecreaseBatchSql, new BatchPreparedStatementSetter() { + + @Override + public void setValues(PreparedStatement ps, int i) throws SQLException { + Entry entry = CollectionUtils.get(batchStockToAdjustAmountMap.entrySet(), i); + ps.setLong(1, entry.getKey().getId()); + ps.setLong(2, entry.getValue()); } @Override public int getBatchSize() { // TODO Auto-generated method stub - return diposableGoodsItemMapList.size(); + return CollectionUtils.size(batchStockToAdjustAmountMap); } }); } + if(MapUtils.isNotEmpty(stockToAdjustAmountMap)){ + String updateDisposableGoodsStockIncreaseBatchSql = String.format( + "update %s set amount=? where id=?", + DisposableGoodsStock.class.getSimpleName()); + jdbcTemplate.batchUpdate(updateDisposableGoodsStockIncreaseBatchSql, new BatchPreparedStatementSetter() { + + @Override + public void setValues(PreparedStatement ps, int i) throws SQLException { + Entry entry = CollectionUtils.get(stockToAdjustAmountMap.entrySet(), i); + ps.setLong(1, entry.getKey().getId()); + ps.setLong(2, entry.getValue()); + } + + @Override + public int getBatchSize() { + // TODO Auto-generated method stub + return stockToAdjustAmountMap.size(); + } + }); + } } } - }*/ + } + /** + * 锁定要扣减的一次性物品相关的数据(为高值耗材则锁定高值耗材实例、否则锁定标识表数据) + * @param invoiceToTdToTiListMapMapForOutStock 发货单对应“包定义对应所发的包实例map”的map + * @param tdToDgToOutStockAmountMapMap 包定义对应“一次性物品定义对应需扣减数据map”的map + * @param warehouseId 发货的仓库id + * @param identificationList 一次性物品标识数量 + * @param expensiveDisposablegoodsList 高值耗材集合 + * @param idToDisposableGoodsMap + * @param idToDisposableGoodsStockMap + * @param idToDisposableGoodsBatchMap + * @param idToDisposableGoodsBatchStockMap + * @param dgIdToDisposableGoodsStockMap + * @param batchIdToDisposableGoodsBatchStockMap + */ + private void lockAndFetchDisposableGoodsRelativeOutStockData(Map>> invoiceToTdToTiListMapMapForOutStock, + Map> tdToDgToOutStockAmountMapMap,Long warehouseId, + List identificationList, List expensiveDisposablegoodsList, + Map idToDisposableGoodsMap ,Map idToDisposableGoodsStockMap , + Map idToDisposableGoodsBatchMap , Map idToDisposableGoodsBatchStockMap, + Map dgIdToDisposableGoodsStockMap,Map batchIdToDisposableGoodsBatchStockMap){ + //高值耗材物品的扣减总数量 + Map expensiveDisposableGoodsToOutStockMap = new HashMap(); + //非高值耗材物品的扣减总数量 + Map notExpensiveDisposableGoodsToOutStockMap = new HashMap(); + + invoiceToTdToTiListMapMapForOutStock.entrySet().stream().forEach(entry -> { + Map> tdToTiListMap = entry.getValue(); + tdToTiListMap.entrySet().stream().forEach(entry2 -> { + List tiList = entry2.getValue(); + int tiSize = CollectionUtils.size(tiList); + if(CollectionUtils.isEmpty(tiList)){ + return; + } + TousseDefinition td = entry2.getKey(); + //一次性物品对应的扣减数量map + Map dgToOutStockAmountMap = tdToDgToOutStockAmountMapMap.get(td); + if(tiSize > 1){ + dgToOutStockAmountMap.entrySet().forEach(entry1 -> { + //将一次性物品定义拆分出高值耗材与非高值耗材 + DisposableGoods dg = entry1.getKey(); + Long dgId = dg.getId(); + idToDisposableGoodsMap.put(dgId, dg); + Integer needOutStockAmount = entry1.getValue(); + if(dg.expensiveDiposablegoods()){ + expensiveDisposableGoodsToOutStockMap.put(dgId, MathTools.add(expensiveDisposableGoodsToOutStockMap.get(dgId), needOutStockAmount * tiSize).intValue()); + }else{ + notExpensiveDisposableGoodsToOutStockMap.put(dgId, MathTools.add(notExpensiveDisposableGoodsToOutStockMap.get(dgId), needOutStockAmount * tiSize).intValue()); + } + }); + } + }); + }); + + if(MapUtils.isNotEmpty(expensiveDisposableGoodsToOutStockMap)){ + //1.先判断各一次性物品的库存数量是否够扣减,如果不够则进行提示 + String querySqlGroupByDisposableGoodsId = String.format("select dgb.diposablegoods_id,count(0) cnt from %s po " + + "join %s dgbs on po.batchStock_id=dgbs.id " + + "join %s dgb on dgb.id=dgbs.disposableGoodsBatchID " + + "where po.warehouseID=%s and status='%s' and dgb.expDate > %s " + + "and %s " + + "group by dgb.diposablegoods_id", ExpensiveDisposablegoods.class.getSimpleName(), + DisposableGoodsBatchStock.class.getSimpleName(),DisposableGoodsBatch.class.getSimpleName(), + warehouseId,ExpensiveDisposablegoods.STATUS_IN_WAREHOUSE,dateQueryAdapter.dateAdapter(new Date()), + SqlUtils.getNonStringFieldInLargeCollectionsPredicate("dgb.diposablegoods_id", + expensiveDisposableGoodsToOutStockMap.keySet() + )); + List> resultMapList = jdbcTemplate.queryForList(querySqlGroupByDisposableGoodsId); + if(CollectionUtils.isEmpty(resultMapList)){ + throw new SystemException("所有要扣减的耗材库存不足"); + } + //将查询到的一次性物品库存与要扣减的一次性物品数量进行一一对比,如果库存数小于待发货时,则抛出异常 + resultMapList.stream().forEach(map -> { + Long disposableGoodsId = ((Number)map.get("diposablegoods_id")).longValue(); + Integer storage = ((Number)map.get("cnt")).intValue(); + Integer totalOutStockAmount = notExpensiveDisposableGoodsToOutStockMap.get(disposableGoodsId); + if(storage < notExpensiveDisposableGoodsToOutStockMap.get(disposableGoodsId)){ + throw new SystemException(String.format("【%s】总的需扣减数量为%s,库存数量为%s,库存不足", + idToDisposableGoodsMap.get(disposableGoodsId).getShowName() , totalOutStockAmount, storage)); + } + }); + + //2.查询出可用于发货的高值耗材实例 + String queryCondition = String.format("where warehouseID=%s and status='%s' and po.disposableGoodsBatchStock.expDate > %s and %s ", + warehouseId, ExpensiveDisposablegoods.STATUS_IN_WAREHOUSE,dateQueryAdapter.dateAdapter(new Date()), + SqlUtils.getNonStringFieldInLargeCollectionsPredicate("po.disposableGoodsBatchStock.diposableGoods.disposableGoodsID", + expensiveDisposableGoodsToOutStockMap.keySet())); + String orderBy = " order by po.disposableGoodsBatchStock.expDate "; + List edgList = objectDao.getBySql_ForUpdate2(ExpensiveDisposablegoods.class.getSimpleName(), queryCondition + orderBy); + if(CollectionUtils.isEmpty(edgList)){ + throw new SystemException("所有要扣减的耗材库存不足"); + } + expensiveDisposablegoodsList.addAll(edgList); + } + + if(MapUtils.isNotEmpty(notExpensiveDisposableGoodsToOutStockMap)){ + //1.先判断各一次性物品的库存数量是否够扣减,如果不够则进行提示 + String querySqlGroupByDisposableGoodsId = String.format("select dgb.diposablegoods_id,sum(po.amount) cnt from %s po " + + "join %s dgbs on po.batch_id=dgbs.id " + + "join %s dgb on dgb.id=dgbs.disposableGoodsBatchID " + + "where po.warehouseID=%s and po.amount > 0 and dgb.expDate > %s " + + "and %s " + + "group by dgb.diposablegoods_id", DisposableGoodsIdentification.class.getSimpleName(), + DisposableGoodsBatchStock.class.getSimpleName(),DisposableGoodsBatch.class.getSimpleName(), + warehouseId,dateQueryAdapter.dateAdapter(new Date()), + SqlUtils.getNonStringFieldInLargeCollectionsPredicate("dgb.diposablegoods_id", notExpensiveDisposableGoodsToOutStockMap.keySet() + )); + List> resultMapList = jdbcTemplate.queryForList(querySqlGroupByDisposableGoodsId); + if(CollectionUtils.isEmpty(resultMapList)){ + throw new SystemException("所有要扣减的耗材库存不足"); + } + //将查询到的一次性物品库存与要扣减的一次性物品数量进行一一对比,如果库存数小于待发货时,则抛出异常 + resultMapList.stream().forEach(map -> { + Long disposableGoodsId = ((Number)map.get("diposablegoods_id")).longValue(); + Integer storage = ((Number)map.get("cnt")).intValue(); + Integer totalOutStockAmount = notExpensiveDisposableGoodsToOutStockMap.get(disposableGoodsId); + if(storage < notExpensiveDisposableGoodsToOutStockMap.get(disposableGoodsId)){ + throw new SystemException(String.format("【%s】总的需扣减数量为%s,库存数量为%s,库存不足", + idToDisposableGoodsMap.get(disposableGoodsId).getShowName() , totalOutStockAmount, storage)); + } + }); + //2.查询出可用于发货的一次性物品标识 + String queryCondition = String.format("where warehouseID=%s and amount > 0 and po.disposableGoodsBatchStock.expDate > %s and %s order by batchStock.expDate", + warehouseId, dateQueryAdapter.dateAdapter(new Date()), + SqlUtils.getNonStringFieldInLargeCollectionsPredicate("po.batchStock.diposableGoods.disposableGoodsID", + notExpensiveDisposableGoodsToOutStockMap.keySet())); + List diList = objectDao.getBySql_ForUpdate2(DisposableGoodsIdentification.class.getSimpleName(), queryCondition); + if(CollectionUtils.isEmpty(diList)){ + throw new SystemException("所有要扣减的耗材库存不足"); + } + identificationList.addAll(diList); + } + + List disposableGoodsBatchStockList = new ArrayList(); + if(CollectionUtils.isNotEmpty(expensiveDisposablegoodsList)){ + disposableGoodsBatchStockList.addAll(expensiveDisposablegoodsList.stream().map(ExpensiveDisposablegoods::getDisposableGoodsBatchStock).collect(Collectors.toList())); + } + if(CollectionUtils.isNotEmpty(identificationList)){ + disposableGoodsBatchStockList.addAll(identificationList.stream().map(DisposableGoodsIdentification::getBatchStock).collect(Collectors.toList())); + } + //去掉重复元素 + disposableGoodsBatchStockList = disposableGoodsBatchStockList.stream().distinct().collect(Collectors.toList()); + if(CollectionUtils.isNotEmpty(disposableGoodsBatchStockList)){ + //对list集合按id分组生成map + disposableGoodsBatchStockList.stream().forEach(disposableGoodsBatchStock -> { + idToDisposableGoodsBatchStockMap.put(disposableGoodsBatchStock.getId(),disposableGoodsBatchStock); + batchIdToDisposableGoodsBatchStockMap.put(disposableGoodsBatchStock.getDisposableGoodsBatchId(),disposableGoodsBatchStock); + }); + List disposableGoodsBatchIdList = + disposableGoodsBatchStockList.stream().map(DisposableGoodsBatchStock::getDisposableGoodsBatchId).collect(Collectors.toList()); + @SuppressWarnings("unchecked") + List disposableGoodsBatchList = objectDao.getCollection(DisposableGoodsBatch.class.getSimpleName(), "id", disposableGoodsBatchIdList); + disposableGoodsBatchList.stream().forEach(disposableGoodsBatch -> { + idToDisposableGoodsBatchMap.put(disposableGoodsBatch.getId(),disposableGoodsBatch); + }); + + List disposableGoodsStockList = + disposableGoodsBatchStockList.stream().map(DisposableGoodsBatchStock::getDiposableGoods).collect(Collectors.toList()); + disposableGoodsStockList.stream().forEach(disposableGoodsStock -> { + idToDisposableGoodsStockMap.put(disposableGoodsStock.getId(),disposableGoodsStock); + dgIdToDisposableGoodsStockMap.put(disposableGoodsStock.getDisposableGoodsID(),disposableGoodsStock); + }); + } + } + } \ No newline at end of file