Index: ssts-basedata/src/main/java/com/forgon/disinfectsystem/entity/basedatamanager/toussedefinition/TousseDefinition.java =================================================================== diff -u -r14440 -r14485 --- ssts-basedata/src/main/java/com/forgon/disinfectsystem/entity/basedatamanager/toussedefinition/TousseDefinition.java (.../TousseDefinition.java) (revision 14440) +++ ssts-basedata/src/main/java/com/forgon/disinfectsystem/entity/basedatamanager/toussedefinition/TousseDefinition.java (.../TousseDefinition.java) (revision 14485) @@ -814,6 +814,14 @@ return false; } /** + * 判断是否是外来器械拆分小包 + * @return + */ + @Transient + public boolean isSplit(){ + return StringTools.equals(tousseType, PACKAGE_TYPE_SPLIT); + } + /** * 判断是否是整包清洗 * @return */ Index: ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManagerImpl.java =================================================================== diff -u -r14452 -r14485 --- ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManagerImpl.java (.../GoodsStockManagerImpl.java) (revision 14452) +++ ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManagerImpl.java (.../GoodsStockManagerImpl.java) (revision 14485) @@ -59,22 +59,24 @@ return map; } /** - * 获取仓库下的物品名称的库存集合。此方法可能会多返回一些记录,但这是些记录并不是你想要的。 + * 获取仓库下的物品名称的库存集合,目前只有外来器械拆分小包才会调用这个方法,所以在此方法里面限制物品类型为器械包,不处理材料的数据。 + * 此方法可能会多返回一些记录,但这是些记录并不是你想要的。 *

如要获取仓库1下的张三和仓库2下的李四,应该只会有两条记录返回。但是此方法的实现,可能还会返回仓库1下的李四和仓库2下的张三 + * @param amountBigZero 是否只获取数量大于0的记录。对于发货,应该只要查数量大于0的库存记录,但是入库可能需要查库存等于0的记录 * @param wareHouseIds * @param goodsNames - * @param amountBigZero 是否只获取数量大于0的记录。对于发货,应该只要查数量大于0的库存记录,但是入库可能需要查库存等于0的记录 * @return */ @SuppressWarnings("unchecked") - private List getGoodsStock(Collection wareHouseIds,Collection goodsNames,boolean amountBigZero){ + private List getGoodsStock(boolean amountBigZero,Collection wareHouseIds,Collection goodsNames){ String namePredicate = SqlUtils.getStringFieldInCollectionsPredicate("name", goodsNames); String idPredicate = SqlUtils.getNonStringFieldInCollectionsPredicate("wareHouseId", wareHouseIds); String amountPredicate = " 1=1 "; if(amountBigZero){ amountPredicate = " amount > 0 "; } - String sql = " where 1=1 and " + idPredicate + " and " + namePredicate + " and " + amountPredicate; + String sql = " where 1=1 and " + idPredicate + " and " + namePredicate + " and " + amountPredicate + + " and goodsType='" + GoodsStock.TYPE_TOUSSE + "'"; List list = objectDao.getBySql_ForUpdate2(GoodsStock.class.getSimpleName(), sql); return list; } @@ -87,13 +89,10 @@ * @return */ @SuppressWarnings("unchecked") - private List getGoodsStock(Collection wareHouseIds,Collection goodsDefId,boolean toussedefIdOrMaterialDefId,boolean amountBigZero){ + private List getGoodsStock(Collection wareHouseIds,Collection goodsDefId,boolean toussedefIdOrMaterialDefId){ String wareHouseIdPredicate = SqlUtils.getNonStringFieldInCollectionsPredicate("wareHouseId", wareHouseIds); String goodsDefIdPredicate = ""; String amountPredicate = " 1=1 "; - if(amountBigZero){ - amountPredicate = " amount > 0 "; - } if(toussedefIdOrMaterialDefId){ goodsDefIdPredicate = SqlUtils.getNonStringFieldInCollectionsPredicate("tousseDefinitionId", goodsDefId); }else{ @@ -127,16 +126,30 @@ private void doInStock(List goodsStockList) { String sql = null; GoodsStock goodsStock = null; + List goodsStockInDB = new ArrayList(); for(GoodsStock goodsStockTemp : goodsStockList){ if(goodsStockTemp.getAmount() == null || goodsStockTemp.getAmount() == 0){ throw new RuntimeException("入/退库单"+goodsStockTemp.getName()+"的数量不能为空或0"); } //如果为器械包 if(DatabaseUtil.isPoIdValid(goodsStockTemp.getTousseDefinitionId())){ - sql = " where 1=1 and wareHouseId = " + goodsStockTemp.getWareHouseId() + " and tousseDefinitionId = " + goodsStockTemp.getTousseDefinitionId(); - //判断库存数量是否大于退/出库数量 - goodsStock = (GoodsStock)objectDao.getBySql(GoodsStock.class.getSimpleName(), sql); + //先从list中找 + goodsStock = CollectionUtils.find(goodsStockInDB, new Predicate(){ + @Override + public boolean evaluate(GoodsStock gs) { + if(gs.getWareHouseId().equals(goodsStockTemp.getWareHouseId()) + && gs.getTousseDefinitionId().equals(goodsStockTemp.getTousseDefinitionId())){ + return true; + } + return false; + } + }); if(goodsStock == null){ + sql = " where 1=1 and wareHouseId = " + goodsStockTemp.getWareHouseId() + " and tousseDefinitionId = " + goodsStockTemp.getTousseDefinitionId(); + //判断库存数量是否大于退/出库数量 + goodsStock = (GoodsStock)objectDao.getBySql(GoodsStock.class.getSimpleName(), sql); + } + if(goodsStock == null){ goodsStock = new GoodsStock(); goodsStock.setWareHouseId(goodsStockTemp.getWareHouseId()); goodsStock.setWareHouseName(goodsStockTemp.getWareHouseName()); @@ -148,9 +161,11 @@ goodsStock.setOrgUnitName(goodsStockTemp.getOrgUnitName()); goodsStock.setAmount(goodsStockTemp.getAmount()); objectDao.saveOrUpdate(goodsStock); + goodsStockInDB.add(goodsStock); } else { goodsStock.setAmount(goodsStock.getAmount() + goodsStockTemp.getAmount()); - objectDao.saveOrUpdate(goodsStock); + addIfNotFind(goodsStockInDB, goodsStock); + //objectDao.saveOrUpdate(goodsStock); } }else if(DatabaseUtil.isPoIdValid(goodsStockTemp.getMaterialDefinitionId())){ goodsStock = goodsStockTemp; @@ -160,6 +175,10 @@ throw new RuntimeException("入/退库单器械包id与材料id不能同时为空"); } } + //一次写入数据库 + for(GoodsStock gs : goodsStockInDB){ + objectDao.saveOrUpdate(gs); + } } /** @@ -173,8 +192,8 @@ Map idTousseDefinitionMap = getIDTousseDefinitionMap(goodsStockList); Set wareHouseIds = new HashSet(); - Set goodsNames = new HashSet(); Set tousseDefIds = new HashSet(); + Set goodsNames = new HashSet(); Set materialDefIds = new HashSet(); for(GoodsStock gs : goodsStockList){ wareHouseIds.add(gs.getWareHouseId()); @@ -186,55 +205,45 @@ materialDefIds.add(gs.getMaterialDefinitionId()); } } - List goodsStockListInDb = getGoodsStock(wareHouseIds, goodsNames,true); - List toussedefGoodsStockListInDb = getGoodsStock(wareHouseIds, tousseDefIds, true,true); - List materialDefGoodsStockListInDb = getGoodsStock(wareHouseIds,materialDefIds,false,true); + List tousseNameStockListInDb = getGoodsStock(true,wareHouseIds, goodsNames); + List toussedefGoodsStockListInDb = getGoodsStock(wareHouseIds, tousseDefIds, true); + List materialDefGoodsStockListInDb = getGoodsStock(wareHouseIds,materialDefIds,false); + List toUpdateGoodsStock = new ArrayList(); //需要更新库存数量的库存记录 for(GoodsStock goodsStockTemp : goodsStockList){ if(goodsStockTemp.getAmount() == null || goodsStockTemp.getAmount() == 0){ throw new RuntimeException("入/退库单"+goodsStockTemp.getName()+"的数量不能为空或0"); } if(DatabaseUtil.isPoIdValid(goodsStockTemp.getTousseDefinitionId())){ TousseDefinition td = idTousseDefinitionMap.get(goodsStockTemp.getTousseDefinitionId()); - //如果包定义为消毒物品、外来器械包、自定义器械包、外部代理灭菌、外来器械拆分小包等,则按器械包名称查询库存并进行扣减 if(td != null){ - if(TousseDefinition.PACKAGE_TYPE_DISINFECTION.equals(td.getTousseType()) - || TousseDefinition.PACKAGE_TYPE_FOREIGN.equals(td.getTousseType()) - || TousseDefinition.PACKAGE_TYPE_CUSTOM.equals(td.getTousseType()) - || TousseDefinition.PACKAGE_TYPE_FOREIGNPROXY.equals(td.getTousseType()) - || TousseDefinition.PACKAGE_TYPE_SPLIT.equals(td.getTousseType())){ - //先查询库存是否足够 - List list = goodsStockListInDb.stream().filter( - gs->gs.getWareHouseId().equals(goodsStockTemp.getWareHouseId()) - && StringTools.equals(gs.getName(), goodsStockTemp.getName()) + if(td.isSplit()){ + //如果包定义为外来器械拆分小包等,则按器械包名称查询库存并进行扣减 + List list = tousseNameStockListInDb.stream().filter( + gs->StringTools.equals(gs.getName(), goodsStockTemp.getName()) + && gs.getWareHouseId().equals(goodsStockTemp.getWareHouseId()) && gs.getAmount() > 0).collect(Collectors.toList()); - int amount = 0; - if(CollectionUtils.isNotEmpty(list)){ - for(GoodsStock gs : list){ - amount = MathTools.add(amount, gs.getAmount()).intValue(); - } - } - if(amount < goodsStockTemp.getAmount()){ + int totalAmount = calculateTotalAmount(list); + int needAmount = goodsStockTemp.getAmount(); + if(totalAmount < needAmount){ throw new RuntimeException(goodsStockTemp.getName() + "的库存数量小于出库或退库数量,不能出库或退库"); - } else { - int needOutAmount = goodsStockTemp.getAmount(); - for(GoodsStock stock : list){ - //如果能够扣完,则跳出 - if(stock.getAmount() >= needOutAmount){ - stock.setAmount(stock.getAmount() - needOutAmount); - objectDao.saveOrUpdate(stock); - break; - } - //否则当前库存扣完,直至扣至需要扣完的为止 - needOutAmount -= stock.getAmount(); - stock.setAmount(0); - objectDao.saveOrUpdate(stock); + } + + for(GoodsStock gs : list){ + if(gs.getAmount() >= needAmount){ + gs.setAmount(MathTools.sub(gs.getAmount(), needAmount).intValue()); + addIfNotFind(toUpdateGoodsStock,gs); + break; + }else{ + needAmount = MathTools.sub(needAmount, gs.getAmount()).intValue(); + gs.setAmount(0); + addIfNotFind(toUpdateGoodsStock,gs); } } + }else{ - //如果为器械包、敷料包时则按包定义id查询并扣减库存 + //按包定义祖先id查询并扣减库存 GoodsStock goodsStock = CollectionUtils.find(toussedefGoodsStockListInDb,new Predicate(){ - @Override public boolean evaluate(GoodsStock goodsStock) { return goodsStockTemp.getWareHouseId().equals(goodsStock.getWareHouseId()) @@ -247,24 +256,19 @@ throw new RuntimeException(goodsStockTemp.getName() + "的库存数量小于出库或退库数量,不能出库或退库"); } else { goodsStock.setAmount(goodsStock.getAmount() - goodsStockTemp.getAmount()); - objectDao.saveOrUpdate(goodsStock); + addIfNotFind(toUpdateGoodsStock,goodsStock); } } }else{ throw new RuntimeException("未找到"+goodsStockTemp.getName()+"的器械包定义"); } - }else if(goodsStockTemp.getMaterialDefinitionId() != null && goodsStockTemp.getMaterialDefinitionId() != 0){ + }else if(DatabaseUtil.isPoIdValid(goodsStockTemp.getMaterialDefinitionId())){ //先判断该材料所有库存总和是否大于需扣减的数量 List list = materialDefGoodsStockListInDb.stream().filter( gs->gs.getWareHouseId().equals(goodsStockTemp.getWareHouseId()) && gs.getMaterialDefinitionId().equals(goodsStockTemp.getMaterialDefinitionId()) && gs.getAmount() > 0).collect(Collectors.toList()); - int totalAmount = 0; - if(CollectionUtils.isNotEmpty(list)){ - for(GoodsStock gs : list){ - totalAmount = MathTools.add(totalAmount, gs.getAmount()).intValue(); - } - } + int totalAmount = calculateTotalAmount(list); int needReturnAmount = goodsStockTemp.getAmount(); if(totalAmount < needReturnAmount){ @@ -273,17 +277,23 @@ for(GoodsStock goodsStock : list){ if(goodsStock.getAmount() >= needReturnAmount){ goodsStock.setAmount(goodsStock.getAmount() - needReturnAmount); - objectDao.saveOrUpdate(goodsStock); + addIfNotFind(toUpdateGoodsStock,goodsStock); break; } needReturnAmount -= goodsStock.getAmount(); goodsStock.setAmount(0); - objectDao.saveOrUpdate(goodsStock); + addIfNotFind(toUpdateGoodsStock,goodsStock); } } else { throw new RuntimeException("入/退库单器械包id与材料id不能同时为空"); } } + //最后一次更新需要更新的库存记录 + if(CollectionUtils.isNotEmpty(toUpdateGoodsStock)){ + for(GoodsStock gs : toUpdateGoodsStock){ + objectDao.saveOrUpdate(gs); + } + } } /** @@ -306,5 +316,47 @@ result = (List)objectDao.findBySql(GoodsStock.class.getSimpleName(), sql); return result; } - + /** + * 在集合中查找指定id的库存记录,找到返回原记录,未找到,返回null + * @param goodsStocks 库存记录集合 + * @param id 要查找的库存记录的id + * @return id所对应的库存记录.未找到则返回null + */ + public GoodsStock find(Collection goodsStocks,Long id){ + GoodsStock goodsStockFind = CollectionUtils.find(goodsStocks,new Predicate(){ + @Override + public boolean evaluate(GoodsStock gs) { + return id.equals(gs.getId()); + }}); + return goodsStockFind; + } + /** + * 在集合中如果没有找到库存记录,则将库存记录添加到集合中。根据id进行比对查找 + * @param goodsStocks + * @param goodsStock + */ + private void addIfNotFind(Collection goodsStocks,GoodsStock goodsStock){ + if(goodsStock != null){ + GoodsStock goodsStockFind = find(goodsStocks,goodsStock.getId()); + if(goodsStockFind == null){ + goodsStocks.add(goodsStock); + } + } + } + /** + * 计算集合中库存数量总和 + * @param goodsStocks + * @return + */ + public int calculateTotalAmount(Collection goodsStocks){ + int totalAmout = 0; + if(CollectionUtils.isNotEmpty(goodsStocks)){ + for(GoodsStock gs : goodsStocks){ + if(gs != null){ + totalAmout = MathTools.add(totalAmout, gs.getAmount()).intValue(); + } + } + } + return totalAmout; + } } Index: ssts-basedata/src/main/java/com/forgon/disinfectsystem/entity/goodsstock/GoodsStock.java =================================================================== diff -u -r14222 -r14485 --- ssts-basedata/src/main/java/com/forgon/disinfectsystem/entity/goodsstock/GoodsStock.java (.../GoodsStock.java) (revision 14222) +++ ssts-basedata/src/main/java/com/forgon/disinfectsystem/entity/goodsstock/GoodsStock.java (.../GoodsStock.java) (revision 14485) @@ -54,7 +54,7 @@ private String goodsType; /** - * 器械包定义id,不是祖先id + * 器械包定义id,记录的是祖先id,包定义的ancestorID字段 */ private Long tousseDefinitionId; Index: ssts-web/src/test/java/test/forgon/disinfectsystem/packing/InvoicePlanManagerTests.java =================================================================== diff -u -r13055 -r14485 --- ssts-web/src/test/java/test/forgon/disinfectsystem/packing/InvoicePlanManagerTests.java (.../InvoicePlanManagerTests.java) (revision 13055) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/packing/InvoicePlanManagerTests.java (.../InvoicePlanManagerTests.java) (revision 14485) @@ -146,7 +146,7 @@ goodsStockManager.saveOrUpdateGoodsStock(list, GoodsStockManager.MODE_INSTOCK); GoodsStock getStock = new GoodsStock(); getStock.setWareHouseId(wareHouse1.getId()); - getStock.setTousseDefinitionId(td.getId()); + getStock.setTousseDefinitionId(td.getAncestorID()); List retlist = goodsStockManager.getGoodsStockList(getStock); assertNotNull(retlist); Index: ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/toussedefinition/service/TousseInstanceUtils.java =================================================================== diff -u -r14027 -r14485 --- ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/toussedefinition/service/TousseInstanceUtils.java (.../TousseInstanceUtils.java) (revision 14027) +++ ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/toussedefinition/service/TousseInstanceUtils.java (.../TousseInstanceUtils.java) (revision 14485) @@ -234,7 +234,7 @@ goodsStock.setName(tousseInstance.getTousseName()); goodsStock.setOrgUnitCode(wareHouse.getOrgUnitCode()); goodsStock.setOrgUnitName(wareHouse.getOrgUnitName()); - goodsStock.setTousseDefinitionId(tousseInstance.getTousseDefinition().getId()); + goodsStock.setTousseDefinitionId(tousseInstance.getTousseDefinition().getAncestorID()); goodsStock.setWareHouseId(wareHouse.getId()); goodsStock.setWareHouseName(wareHouse.getName()); return goodsStock; Index: ssts-recyclingapplication/src/main/java/com/forgon/disinfectsystem/recyclingapplication/service/RecyclingApplicationManagerImpl.java =================================================================== diff -u -r14480 -r14485 --- ssts-recyclingapplication/src/main/java/com/forgon/disinfectsystem/recyclingapplication/service/RecyclingApplicationManagerImpl.java (.../RecyclingApplicationManagerImpl.java) (revision 14480) +++ ssts-recyclingapplication/src/main/java/com/forgon/disinfectsystem/recyclingapplication/service/RecyclingApplicationManagerImpl.java (.../RecyclingApplicationManagerImpl.java) (revision 14485) @@ -3701,7 +3701,7 @@ } List stockList = new ArrayList(); GoodsStock stock = new GoodsStock(); - stock.setTousseDefinitionId(td.getId()); + stock.setTousseDefinitionId(td.getAncestorID()); stock.setAmount(amount); stock.setGoodsType(GoodsStock.TYPE_TOUSSE); stock.setName(td.getName()); @@ -3847,7 +3847,7 @@ } List stockList = new ArrayList(); GoodsStock stock = new GoodsStock(); - stock.setTousseDefinitionId(td.getId()); + stock.setTousseDefinitionId(td.getAncestorID()); stock.setAmount(amount); stock.setGoodsType(GoodsStock.TYPE_TOUSSE); stock.setName(td.getName());