Index: ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManager.java =================================================================== diff -u -r14913 -r15095 --- ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManager.java (.../GoodsStockManager.java) (revision 14913) +++ ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManager.java (.../GoodsStockManager.java) (revision 15095) @@ -52,5 +52,19 @@ */ public List getGoodsStock(Collection wareHouseIds, Collection goodsDefId,boolean toussedefIdOrMaterialDefId); + /** + * 查找仓库下器械包的库存 + * @param wareHouseId 仓库id + * @param tousseDefinitionId 器械包定义id + * @return + */ + public List getTousseStock(Long wareHouseId,Long tousseDefinitionId); + /** + * 查询仓库下材料的库存 + * @param wareHouseId 仓库id + * @param materialDefinitionId 材料定义id + * @return + */ + public List getMaterialStock(Long wareHouseId,Long materialDefinitionId); } Index: ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManagerImpl.java =================================================================== diff -u -r14913 -r15095 --- ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManagerImpl.java (.../GoodsStockManagerImpl.java) (revision 14913) +++ ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManagerImpl.java (.../GoodsStockManagerImpl.java) (revision 15095) @@ -1,12 +1,10 @@ package com.forgon.disinfectsystem.basedatamanager.goodsstock.service; -import java.math.BigDecimal; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -16,12 +14,12 @@ import org.apache.commons.collections4.Predicate; import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseDefinition; -import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseDefinitionMaterial; +import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseInstance; +import com.forgon.disinfectsystem.entity.basedatamanager.warehouse.WareHouse; import com.forgon.disinfectsystem.entity.goodsstock.GoodsStock; import com.forgon.tools.MathTools; import com.forgon.tools.db.DatabaseUtil; import com.forgon.tools.hibernate.ObjectDao; -import com.forgon.tools.string.StringTools; import com.forgon.tools.util.SqlUtils; /** @@ -64,29 +62,7 @@ } return map; } - /** - * 获取仓库下的物品名称的库存集合,目前只有外来器械拆分小包才会调用这个方法,所以在此方法里面限制物品类型为器械包,不处理材料的数据。 - * 此方法可能会多返回一些记录,但这是些记录并不是你想要的。 - *

如要获取仓库1下的张三和仓库2下的李四,应该只会有两条记录返回。但是此方法的实现,可能还会返回仓库1下的李四和仓库2下的张三 - * @param amountBigZero 是否只获取数量大于0的记录。对于发货,应该只要查数量大于0的库存记录,但是入库可能需要查库存等于0的记录 - * @param wareHouseIds - * @param goodsNames - * @return - */ @SuppressWarnings("unchecked") - 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 - + " and goodsType='" + GoodsStock.TYPE_TOUSSE + "'"; - List list = objectDao.getBySql_ForUpdate2(GoodsStock.class.getSimpleName(), sql); - return list; - } - @SuppressWarnings("unchecked") public List getGoodsStock(Collection wareHouseIds,Collection goodsDefId,boolean toussedefIdOrMaterialDefId){ String wareHouseIdPredicate = SqlUtils.getNonStringFieldInCollectionsPredicate("wareHouseId", wareHouseIds); String goodsDefIdPredicate = ""; @@ -208,7 +184,6 @@ materialDefIds.add(gs.getMaterialDefinitionId()); } } - List tousseNameStockListInDb = getGoodsStock(true,wareHouseIds, goodsNames); List toussedefGoodsStockListInDb = getGoodsStock(wareHouseIds, tousseDefIds, true); List materialDefGoodsStockListInDb = getGoodsStock(wareHouseIds,materialDefIds,false); List toUpdateGoodsStock = new ArrayList(); //需要更新库存数量的库存记录 @@ -220,47 +195,26 @@ if(DatabaseUtil.isPoIdValid(goodsStockTemp.getTousseDefinitionId())){ TousseDefinition td = idTousseDefinitionMap.get(goodsStockTemp.getTousseDefinitionId()); if(td != null){ - 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 totalAmount = calculateTotalAmount(list); - int needAmount = goodsStockTemp.getAmount(); - if(totalAmount < needAmount){ - throw new RuntimeException(goodsStockTemp.getName() + "的库存数量小于出库或退库数量,不能出库或退库"); - } - - 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); - } - } - + + //按包定义祖先id查询并扣减库存 + GoodsStock goodsStock = CollectionUtils.find(toussedefGoodsStockListInDb,new Predicate(){ + @Override + public boolean evaluate(GoodsStock goodsStock) { + return goodsStockTemp.getWareHouseId().equals(goodsStock.getWareHouseId()) + && goodsStockTemp.getTousseDefinitionId().equals(goodsStock.getTousseDefinitionId()); + }}); + //判断库存数量是否大于退/出库数量 + if(goodsStock == null){ + int amount = getTousseInstanceStock(goodsStockTemp.getWareHouseId(),goodsStockTemp.getTousseDefinitionId()); + goodsStock = saveTousseStock(goodsStockTemp.getWareHouseId(),td, amount); + toussedefGoodsStockListInDb.add(goodsStock); + } else if(goodsStock.getAmount() < goodsStockTemp.getAmount()){ + int amount = getTousseInstanceStock(goodsStockTemp.getWareHouseId(),goodsStockTemp.getTousseDefinitionId()); + goodsStock.setAmount(amount); + addIfNotFind(toUpdateGoodsStock,goodsStock); }else{ - //按包定义祖先id查询并扣减库存 - GoodsStock goodsStock = CollectionUtils.find(toussedefGoodsStockListInDb,new Predicate(){ - @Override - public boolean evaluate(GoodsStock goodsStock) { - return goodsStockTemp.getWareHouseId().equals(goodsStock.getWareHouseId()) - && goodsStockTemp.getTousseDefinitionId().equals(goodsStock.getTousseDefinitionId()); - }}); - //判断库存数量是否大于退/出库数量 - if(goodsStock == null){ - throw new RuntimeException("未找到"+goodsStockTemp.getName()+"的库存数据,不能出库或退库"); - } else if(goodsStock.getAmount() < goodsStockTemp.getAmount()){ - throw new RuntimeException(goodsStockTemp.getName() + "的库存数量小于出库或退库数量,不能出库或退库"); - } else { - goodsStock.setAmount(goodsStock.getAmount() - goodsStockTemp.getAmount()); - addIfNotFind(toUpdateGoodsStock,goodsStock); - } + goodsStock.setAmount(goodsStock.getAmount() - goodsStockTemp.getAmount()); + addIfNotFind(toUpdateGoodsStock,goodsStock); } }else{ throw new RuntimeException("未找到"+goodsStockTemp.getName()+"的器械包定义"); @@ -304,20 +258,14 @@ * @param goodsStock 可以查询的属性有仓库id,器械包或材料定义id等 * @return */ + @Deprecated public List getGoodsStockList(GoodsStock goodsStock){ - List result = null; - String sql = " where 1=1 "; - if(goodsStock.getWareHouseId() != null && goodsStock.getWareHouseId() != 0){ - sql += " and wareHouseId = " + goodsStock.getWareHouseId(); + if(DatabaseUtil.isPoIdValid(goodsStock.getTousseDefinitionId())){ + return getTousseStock(goodsStock.getWareHouseId(), goodsStock.getTousseDefinitionId()); + }else if(DatabaseUtil.isPoIdValid(goodsStock.getMaterialDefinitionId())){ + return getMaterialStock(goodsStock.getWareHouseId(), goodsStock.getMaterialDefinitionId()); } - if(goodsStock.getTousseDefinitionId() != null && goodsStock.getTousseDefinitionId() != 0){ - sql += " and tousseDefinitionId = " + goodsStock.getTousseDefinitionId(); - }else if(goodsStock.getMaterialDefinitionId() != null && goodsStock.getMaterialDefinitionId() != 0){ - sql += " and materialDefinitionId = " + goodsStock.getMaterialDefinitionId(); - } - //判断库存数量是否大于退/出库数量 - result = (List)objectDao.findBySql(GoodsStock.class.getSimpleName(), sql); - return result; + return null; } /** * 在集合中查找指定id的库存记录,找到返回原记录,未找到,返回null @@ -362,4 +310,77 @@ } return totalAmout; } + /** + * 在指定仓库保存一条器械包的库存记录 + * @param wareHouseId 仓库id + * @param td 器械包定义.是根据GoodsStock中记录的tousseDefinitionId查找到的包定义 + * @return 保存到数据库中的库存对象 + */ + private GoodsStock saveTousseStock(Long wareHouseId,TousseDefinition td,int amount){ + WareHouse wareHouse = (WareHouse)objectDao.getByProperty(WareHouse.class.getSimpleName(), "id", wareHouseId); + if(td == null || wareHouse == null){ + return null; + } + GoodsStock gs = new GoodsStock(); + gs.setGoodsType(GoodsStock.TYPE_TOUSSE); + gs.setName(td.getName()); + gs.setOrgUnitCode(wareHouse.getOrgUnitCode()); + gs.setOrgUnitName(wareHouse.getOrgUnitName()); + gs.setTousseDefinitionId(td.getId()); + gs.setWareHouseId(wareHouseId); + gs.setWareHouseName(wareHouse.getName()); + gs.setAmount(amount); + objectDao.saveOrUpdate(gs); + return gs; + } + /** + * 获取能够入库的器械包的状态条件 + * @return + */ + private String canInstockTosseStatusPredicate(){ + List status = new LinkedList(); + status.add(TousseInstance.STATUS_DISINFECTED); + status.add(TousseInstance.STATUS_STERILED); + return SqlUtils.getStringFieldInCollectionsPredicate("po.status", status); + } + /** + * 获取器械包实例的数量。其中器械包实例根据包定义的祖先id去查找,祖先id相同,都认为是同一个包实例,即使包定义的材料不同。 + * @param wareHouseId 包实例的仓库 + * @param tousseDefinitionId 包实例的祖先id + * @return 返回器械包实例的数量 + */ + private int getTousseInstanceStock(Long wareHouseId,Long tousseDefinitionId){ + if(!DatabaseUtil.isPoIdValid(wareHouseId) || !DatabaseUtil.isPoIdValid(tousseDefinitionId)){ + return 0; + } + + StringBuilder sql = new StringBuilder(); + sql.append(" where po.wareHouseId=" ); + sql.append(wareHouseId); + sql.append(" and po.tousseDefinition.ancestorID="); + sql.append(tousseDefinitionId); + sql.append(" and "); + sql.append(canInstockTosseStatusPredicate()); + + return objectDao.countObjectBySql(TousseInstance.class.getSimpleName(), sql.toString()); + } + + @Override + public List getTousseStock(Long wareHouseId, + Long tousseDefinitionId) { + if(!DatabaseUtil.isPoIdValid(wareHouseId) || !DatabaseUtil.isPoIdValid(tousseDefinitionId)){ + return null; + } + String sql = String.format("where wareHouseId = %d and tousseDefinitionId = %d", wareHouseId,tousseDefinitionId); + return (List)objectDao.findBySql(GoodsStock.class.getSimpleName(), sql); + } + @Override + public List getMaterialStock(Long wareHouseId, + Long materialDefinitionId) { + if(!DatabaseUtil.isPoIdValid(wareHouseId) || !DatabaseUtil.isPoIdValid(materialDefinitionId)){ + return null; + } + String sql = String.format("where wareHouseId = %d and materialDefinitionId = %d", wareHouseId,materialDefinitionId); + return (List)objectDao.findBySql(GoodsStock.class.getSimpleName(), sql); + } } Index: ssts-tousse/src/main/java/com/forgon/disinfectsystem/tousse/toussedefinition/service/TousseInstanceManagerImpl.java =================================================================== diff -u -r15078 -r15095 --- ssts-tousse/src/main/java/com/forgon/disinfectsystem/tousse/toussedefinition/service/TousseInstanceManagerImpl.java (.../TousseInstanceManagerImpl.java) (revision 15078) +++ ssts-tousse/src/main/java/com/forgon/disinfectsystem/tousse/toussedefinition/service/TousseInstanceManagerImpl.java (.../TousseInstanceManagerImpl.java) (revision 15095) @@ -184,7 +184,7 @@ (List)objectDao.getHibernateSession().createQuery("from TousseInstance where status not in ('"+TousseInstance.STATUS_USED+"','"+TousseInstance.STATUS_RECYCLED+"','"+TousseInstance.STATUS_DISCARD+"') and validUntil < :validUntil").setDate("validUntil", new java.sql.Timestamp(new Date().getTime())).list(); discardTousseInstance(outdateTousseInstanceList,"失效期过期定时废弃处理"); } - + public void discardTousseInstance(Collection tousseInstances,String wasteReason) { if(CollectionUtils.isNotEmpty(tousseInstances)){ //更新器械包库存 @@ -208,10 +208,8 @@ GoodsStock goodsStock = TousseInstanceUtils.newGoodsStock(tousseInstance); //所在位置,所属仓库等属性也清空 - tousseInstance.setLocation(null); - tousseInstance.setLocationForDisplay(null); - tousseInstance.setWareHouseId(null); - tousseInstance.setWareHouseName(null); + clearLocation(tousseInstance); + clearWarehouseInfo(tousseInstance); tousseInstance.setStatus(TousseInstance.STATUS_DISCARD); objectDao.saveOrUpdate(tousseInstance); goodsStockList.add(goodsStock); @@ -221,22 +219,18 @@ } } } - public void discardTousseInstance(TousseInstance tousseInstance,String operateUser,String wasteReason,Date wasteDate){ if(tousseInstance == null){ return; } tousseInstance.setOperateUser(operateUser); tousseInstance.setWasteReason(wasteReason); - tousseInstance.setWasteDate(wasteDate); + tousseInstance.setWasteDate(wasteDate); GoodsStock goodsStock = TousseInstanceUtils.newGoodsStock(tousseInstance); //所在位置,所属仓库等属性也清空 - tousseInstance.setLocation(null); - tousseInstance.setLocationForDisplay(null); - tousseInstance.setWareHouseId(null); - tousseInstance.setWareHouseName(null); - + clearLocation(tousseInstance); + clearWarehouseInfo(tousseInstance); //如果状态为已装配、已审核,则包实例关联的篮筐实例属性清空,器械包实例将不扣减库存 if(TousseInstance.STATUS_PACKED.equals(tousseInstance.getStatus()) || TousseInstance.STATUS_REVIEWED.equals(tousseInstance.getStatus())