Index: ssts-webservice/src/main/java/com/forgon/disinfectsystem/webservice/service/ServiceManagerImpl.java =================================================================== diff -u -r17086 -r17148 --- ssts-webservice/src/main/java/com/forgon/disinfectsystem/webservice/service/ServiceManagerImpl.java (.../ServiceManagerImpl.java) (revision 17086) +++ ssts-webservice/src/main/java/com/forgon/disinfectsystem/webservice/service/ServiceManagerImpl.java (.../ServiceManagerImpl.java) (revision 17148) @@ -3483,7 +3483,7 @@ */ public String deleteSterilizationRecord(JSONObject params){ String idStr =params.getString("ids"); - return sterilizationRecordManager.delete(idStr); + return JSONUtil.buildJsonObject(sterilizationRecordManager.delete(idStr)).toString(); } /** * 获取待发货手术预约单列表。如果科室编码为空(首次或者是选择的全部科室),则同时返回所有有待发货手术预约单的科室及对应的编码,以便于按科室过滤 Index: ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManager.java =================================================================== diff -u -r17043 -r17148 --- ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManager.java (.../GoodsStockManager.java) (revision 17043) +++ ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManager.java (.../GoodsStockManager.java) (revision 17148) @@ -3,6 +3,8 @@ import java.util.Collection; import java.util.List; +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.hibernate.BasePoManager; @@ -86,5 +88,19 @@ * @return */ public List getMaterialStock(Long wareHouseId,Long materialDefinitionId); + /** + * 计算集合中库存数量总和 + * @param goodsStocks + * @return + */ + public int calculateTotalAmount(Collection goodsStocks); + /** + * 向集合中添加指定仓库的器械包库存。只能适用于器械包。如果根据仓库和包实例关联包定义的祖先在集合中可以找到库存对象,则将数量添加到原来的对象中;否则创建对象 + * @param goodsStocks + * @param wareHouseId + * @param tousseDefinitionId + * @param amount + */ + public void addToList(Collection goodsStocks,TousseInstance tousseInstance,WareHouse wareHouse); } Index: ssts-basedata/src/main/java/com/forgon/disinfectsystem/entity/basedatamanager/toussedefinition/TousseInstance.java =================================================================== diff -u -r17027 -r17148 --- ssts-basedata/src/main/java/com/forgon/disinfectsystem/entity/basedatamanager/toussedefinition/TousseInstance.java (.../TousseInstance.java) (revision 17027) +++ ssts-basedata/src/main/java/com/forgon/disinfectsystem/entity/basedatamanager/toussedefinition/TousseInstance.java (.../TousseInstance.java) (revision 17148) @@ -569,6 +569,17 @@ public void setTousseDefinition(TousseDefinition tousseDefinition) { this.tousseDefinition = tousseDefinition; } + /** + * 获取关联包定义的祖先id。方法有做判空 + * @return + */ + @Transient + public Long getTousseDefinitionAncestorID(){ + if(tousseDefinition != null){ + return tousseDefinition.getAncestorID(); + } + return null; + } @Transient public String getTousseDefinitionName() { Index: ssts-web/src/test/java/test/forgon/disinfectsystem/packing/SterilizationRecordManagerTestsForCompleteSterileRecord.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/packing/SterilizationRecordManagerTestsForCompleteSterileRecord.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/packing/SterilizationRecordManagerTestsForCompleteSterileRecord.java (revision 17148) @@ -0,0 +1,346 @@ +package test.forgon.disinfectsystem.packing; +import static org.testng.Assert.*; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.testng.annotations.Test; + +import test.forgon.constant.Constants; +import test.forgon.disinfectsystem.AbstractCSSDTest; + +import com.forgon.directory.acegi.tools.AcegiHelper; +import com.forgon.disinfectsystem.basedatamanager.sterilisation.service.SterilisationManager; +import com.forgon.disinfectsystem.entity.basedatamanager.materialdefinition.MaterialDefinition; +import com.forgon.disinfectsystem.entity.basedatamanager.materialinstance.MaterialInstance; +import com.forgon.disinfectsystem.entity.basedatamanager.sterilisation.Sterilisation; +import com.forgon.disinfectsystem.entity.basedatamanager.sterilizer.Sterilizer; +import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseDefinition; +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.disinfectsystem.entity.sterilizationmanager.sterilizationrecord.SterilizationRecord; +import com.forgon.disinfectsystem.packing.service.PackingManager; +import com.forgon.disinfectsystem.sterilizationmanager.sterilizationrecord.service.SterilizationRecordManager; +import com.forgon.disinfectsystem.tousse.toussedefinition.service.TousseInstanceManager; +import com.forgon.runwithtrans.model.RunWithTransNewTask; + +/** + * 灭菌记录完成灭菌的测试用例 + * @author SYF + * @date 2015-10-22 + */ +public class SterilizationRecordManagerTestsForCompleteSterileRecord extends AbstractCSSDTest { + @Autowired + private SterilizationRecordManager sterilizationRecordManager; + @Autowired + private TousseInstanceManager tousseInstanceManager; + @Autowired + private PackingManager packingManager; + @Autowired + private SterilisationManager sterilisationManager; + /** + * 同一种包定义,包实例数量1000个 + */ + @Test + public void testCompleteSterilizationSameTousseDefinition(){ + //1.初始化基础数据 + initCSSDData(); + String orgUnitCode = AcegiHelper.getLoginUser() + .getOrgUnitCodingFromSupplyRoomConfig(); + WareHouse wareHouse = wareHouseManager.getDefaultWareHouseByUnitCode(orgUnitCode); + int count = 1000; + int barcodeStart = barcodeIndex; + SterilizationRecord sterilizationRecord = prepareTousse(orgUnitCode, 1, count); + + TousseInstance tousseInstance = tousseInstanceManager.getFirst("barcode", "01002" + String.format("%04d", barcodeStart)); + String sql = String.format("wareHouseId=%d and tousseDefinitionId=%d", wareHouse.getId(),tousseInstance.getTousseDefinition().getAncestorID()); + List goodsStocks = goodsStockManager.getByHql(sql); + int beforeStocks = goodsStockManager.calculateTotalAmount(goodsStocks); + + List rids = new ArrayList(); + rids.add(sterilizationRecord.getId()); + long b = Calendar.getInstance().getTimeInMillis(); + sterilizationRecordManager.completeSterilization(rids, orgUnitCode, + AcegiHelper.getLoginUser().getUserName(), "", false); + long a = Calendar.getInstance().getTimeInMillis(); + + System.out.println("time:" + (a - b)); + assertEquals(sterilizationRecord.getStatus(), SterilizationRecord.STERILIZATION_STATUS_END); + + for(int i = barcodeStart;i rids = new ArrayList(); + rids.add(sterilizationRecord.getId()); + long b = Calendar.getInstance().getTimeInMillis(); + sterilizationRecordManager.completeSterilization(rids, orgUnitCode, + AcegiHelper.getLoginUser().getUserName(), "", false); + long a = Calendar.getInstance().getTimeInMillis(); + + System.out.println("time:" + (a - b)); + assertEquals(sterilizationRecord.getStatus(), SterilizationRecord.STERILIZATION_STATUS_END); + + for(int i = barcodeStart;i goodsStocks = goodsStockManager.getByHql(sql); + assertEquals(goodsStocks.size(), 1); + int newStocks = goodsStockManager.calculateTotalAmount(goodsStocks); + assertEquals(newStocks, 1); + } + } + + /** + * 每种包定义50个,包定义共20个 + */ + @Test + public void testCompleteSterilizationMultiTousseDefinitionMultiTousseInstance(){ + //1.初始化基础数据 + initCSSDData(); + String orgUnitCode = AcegiHelper.getLoginUser() + .getOrgUnitCodingFromSupplyRoomConfig(); + WareHouse wareHouse = wareHouseManager.getDefaultWareHouseByUnitCode(orgUnitCode); + int barcodeStart = barcodeIndex; + SterilizationRecord sterilizationRecord = prepareTousse(orgUnitCode,20,50); + + List rids = new ArrayList(); + rids.add(sterilizationRecord.getId()); + long b = Calendar.getInstance().getTimeInMillis(); + sterilizationRecordManager.completeSterilization(rids, AcegiHelper.getLoginUser().getOrgUnitCodingFromSupplyRoomConfig(), + AcegiHelper.getLoginUser().getUserName(), "", false); + long a = Calendar.getInstance().getTimeInMillis(); + + System.out.println("time:" + (a - b)); + assertEquals(sterilizationRecord.getStatus(), SterilizationRecord.STERILIZATION_STATUS_END); + + for(int i = barcodeStart;i goodsStocks = goodsStockManager.getByHql(sql); + assertEquals(goodsStocks.size(), 1); + int newStocks = goodsStockManager.calculateTotalAmount(goodsStocks); + assertEquals(newStocks, 50); + } + } + + /** + * 多线程处理,共5个线程,每个线程创建10种包定义(分5张灭菌单,一张单2种包定义),每个包定义20个包实例。 + * @throws InterruptedException + */ + @Test + public void testCompleteSterilizationMultiThread() throws InterruptedException{ + runWithTransNewManager.runWith_TRANS_NEW(new RunWithTransNewTask() { + @Override + public void runTask() { + //1.初始化基础数据 + initCSSDData(); + //2.灭菌程序 + initSterilisation(); + + } + }); + String orgUnitCode = AcegiHelper.getLoginUser() + .getOrgUnitCodingFromSupplyRoomConfig(); + String user = AcegiHelper.getLoginUser().getUserName(); + int barcodeStart = barcodeIndex; + + class ThreadRoute implements Runnable{ + @Override + public void run() { + List rids = new ArrayList(); + runWithTransNewManager.runWith_TRANS_NEW(new RunWithTransNewTask(){ + @Override + public void runTask() { + SterilizationRecord sterilizationRecord1 = prepareTousse(orgUnitCode,2,20,1,SterilizationRecord.STERILIZATION_STATUS_INTERRUPT); + SterilizationRecord sterilizationRecord2 = prepareTousse(orgUnitCode,2,20,1,SterilizationRecord.STERILIZATION_STATUS_INTERRUPT); + SterilizationRecord sterilizationRecord3 = prepareTousse(orgUnitCode,2,20,3,SterilizationRecord.STERILIZATION_STATUS_BEGIN); + SterilizationRecord sterilizationRecord4 = prepareTousse(orgUnitCode,2,20,3,SterilizationRecord.STERILIZATION_STATUS_BEGIN); + SterilizationRecord sterilizationRecord5 = prepareTousse(orgUnitCode,2,20,3,SterilizationRecord.STERILIZATION_STATUS_BEGIN); + + rids.add(sterilizationRecord1.getId()); + rids.add(sterilizationRecord2.getId()); + rids.add(sterilizationRecord3.getId()); + rids.add(sterilizationRecord4.getId()); + rids.add(sterilizationRecord5.getId()); + }}); + + //模拟一个新的事务 + runWithTransNewManager.runWith_TRANS_NEW(new RunWithTransNewTask() { + @Override + public void runTask() { + + long b = Calendar.getInstance().getTimeInMillis(); + sterilizationRecordManager.completeSterilization(rids, orgUnitCode, + user, "", false); + long a = Calendar.getInstance().getTimeInMillis(); + + System.out.println("time:" + (a - b)); + Collection records = sterilizationRecordManager.getCollection(rids); + for(SterilizationRecord record : records){ + assertEquals(record.getStatus(), SterilizationRecord.STERILIZATION_STATUS_END); + } + } + }); + } + } + + Thread t1 = new Thread(new ThreadRoute()); + Thread t2 = new Thread(new ThreadRoute()); + Thread t3 = new Thread(new ThreadRoute()); + Thread t4 = new Thread(new ThreadRoute()); + Thread t5 = new Thread(new ThreadRoute()); + + t1.start(); + t2.start(); + t3.start(); + t4.start(); + t5.start(); + + t1.join(); + t2.join(); + t3.join(); + t4.join(); + t5.join(); + + WareHouse wareHouse = wareHouseManager.getDefaultWareHouseByUnitCode(orgUnitCode); + + for(int i = barcodeStart;i goodsStocks = goodsStockManager.getByHql(sql); + assertEquals(goodsStocks.size(), 1); + int newStocks = goodsStockManager.calculateTotalAmount(goodsStocks); + assertEquals(newStocks, 20); + } + } + private int barcodeIndex = 0; + + public synchronized int getBarcodeIndex() { + return barcodeIndex++; + } + private SterilizationRecord prepareTousse(String orgUnitCode,int toussedefCount,int tousseInstanceCount,int sterilisationIndex,String status){ + SterilizationRecord record = prepareTousse(orgUnitCode,toussedefCount,tousseInstanceCount); + record.setSterilizationType("灭菌程序" + sterilisationIndex); + record.setStatus(status); + sterilizationRecordManager.saveOrUpdate(record); + return record; + } + private SterilizationRecord prepareTousse(String orgUnitCode,int toussedefCount,int tousseInstanceCount) { + Sterilizer s = sterilizerManager.getSterilizerByDepartCoding(orgUnitCode).get(0); + + SterilizationRecord sterilizationRecord = new SterilizationRecord(); + sterilizationRecord.setStartDate(new Date()); + sterilizationRecord.setSterilizer(s); + sterilizationRecord.setOrgUnitCoding(orgUnitCode); + sterilizationRecord.setOrgUnitCoding(""); + sterilizationRecord.setStatus(SterilizationRecord.STERILIZATION_STATUS_BEGIN); + sterilizationRecord.setSterilizerName(""); + sterilizationRecord.setFrequency(2); + sterilizationRecordManager.saveOrUpdate(sterilizationRecord); + + List tousseInstances = new ArrayList(); + sterilizationRecord.setTousseInstanceList(tousseInstances); + + for(int i = 0;i()); + tousseDefinition1.getMaterialInstances().add(materialInstance1); + tousseDefinitionManager.saveOrUpdate(tousseDefinition1); + + for(int tousseIndex = 0;tousseIndex < tousseInstanceCount;++tousseIndex){ + TousseInstance tousseInstance2 = new TousseInstance(); + tousseInstance2.setTousseDefinition(tousseDefinition1); + tousseInstance2.setOrgUnitCoding(orgUnitCode); + tousseInstance2.setReviewer(""); + tousseInstance2.setReviewerCode(""); + tousseInstance2.setReviewTime(new Date()); + tousseInstance2.setDisinfectIdentification(""); + tousseInstance2.setDisinfectProgram(""); + tousseInstance2.setFluctuationPrice(123D); + tousseInstance2.setPackageType(""); + tousseInstance2.setTousseName(tousseDefinition1.getName()); + tousseInstance2.setStatus(TousseInstance.STATUS_STERILING); + tousseInstance2.setVirtualBasketSeqNum("001"); + tousseInstance2.setBarcode("01002" + String.format("%04d", getBarcodeIndex())); + tousseInstanceManager.saveOrUpdate(tousseInstance2); + tousseInstances.add(tousseInstance2); + } + } + return sterilizationRecord; + } + + private void initSterilisation(){ + for(int i=1;i <= 5;++i){ + Sterilisation sterilisation = new Sterilisation(); + sterilisation.setSterilisation("灭菌程序" + i); + sterilisation.setUseTime(1); + sterilisation.setSterilizationPurpose("器械包灭菌"); + sterilisationManager.saveOrUpdate(sterilisation); + } + } +} Index: ssts-web/src/test/resources/test/forgon/AllTests.xml =================================================================== diff -u -r17093 -r17148 --- ssts-web/src/test/resources/test/forgon/AllTests.xml (.../AllTests.xml) (revision 17093) +++ ssts-web/src/test/resources/test/forgon/AllTests.xml (.../AllTests.xml) (revision 17148) @@ -26,5 +26,7 @@ + + \ No newline at end of file Index: ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManagerImpl.java =================================================================== diff -u -r17090 -r17148 --- ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManagerImpl.java (.../GoodsStockManagerImpl.java) (revision 17090) +++ ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/goodsstock/service/GoodsStockManagerImpl.java (.../GoodsStockManagerImpl.java) (revision 17148) @@ -22,7 +22,6 @@ import com.forgon.tools.MathTools; import com.forgon.tools.db.DatabaseUtil; import com.forgon.tools.hibernate.BasePoManagerImpl; -import com.forgon.tools.hibernate.ObjectDao; import com.forgon.tools.string.StringTools; import com.forgon.tools.util.SqlUtils; @@ -106,9 +105,19 @@ return saveOrUpdateGoodsStock(goodsStockList,mode); } private void doInStock(List goodsStockList) { - String sql = null; GoodsStock goodsStock = null; - List goodsStockInDB = new ArrayList(); + Set wareHouseIds = new HashSet(); + Set tousseDefIds = new HashSet(); + for(GoodsStock gs : goodsStockList){ + if(DatabaseUtil.isPoIdValid(gs.getWareHouseId())){ + wareHouseIds.add(gs.getWareHouseId()); + } + if(DatabaseUtil.isPoIdValid(gs.getTousseDefinitionId())){ + tousseDefIds.add(gs.getTousseDefinitionId()); + } + } + List goodsStockInDB = getGoodsStock(wareHouseIds, tousseDefIds, true); + for(GoodsStock goodsStockTemp : goodsStockList){ if(goodsStockTemp.getAmount() == null || goodsStockTemp.getAmount() == 0){ throw new RuntimeException("入/退库单"+goodsStockTemp.getName()+"的数量不能为空或0"); @@ -126,12 +135,12 @@ 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){ - 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()); @@ -377,7 +386,7 @@ * @param id 要查找的库存记录的id * @return id所对应的库存记录.未找到则返回null */ - public GoodsStock find(Collection goodsStocks,Long id){ + private GoodsStock find(Collection goodsStocks,Long id){ GoodsStock goodsStockFind = CollectionUtils.find(goodsStocks,new Predicate(){ @Override public boolean evaluate(GoodsStock gs) { @@ -386,6 +395,26 @@ return goodsStockFind; } /** + * 在集合中查找器械包的库存。只要仓库id跟包定义id一样,并且类型是器械包,就返回 + * @param goodsStocks + * @param wareHouseId + * @param toussedefinitionId + * @return + */ + private GoodsStock findTousseGoodsStock(Collection goodsStocks,Long wareHouseId,Long toussedefinitionId){ + if(wareHouseId == null || toussedefinitionId == null || CollectionUtils.isEmpty(goodsStocks)){ + return null; + } + GoodsStock goodsStockFind = CollectionUtils.find(goodsStocks,new Predicate(){ + @Override + public boolean evaluate(GoodsStock gs) { + return gs != null && StringTools.equals(gs.getGoodsType(), GoodsStock.TYPE_TOUSSE) + && wareHouseId.equals(gs.getWareHouseId()) + && toussedefinitionId.equals(gs.getTousseDefinitionId()); + }}); + return goodsStockFind; + } + /** * 在集合中如果没有找到库存记录,则将库存记录添加到集合中。根据id进行比对查找 * @param goodsStocks * @param goodsStock @@ -398,11 +427,7 @@ } } } - /** - * 计算集合中库存数量总和 - * @param goodsStocks - * @return - */ + public int calculateTotalAmount(Collection goodsStocks){ int totalAmout = 0; if(CollectionUtils.isNotEmpty(goodsStocks)){ @@ -497,4 +522,26 @@ wareHouseIds.add(wareHouseId); return getGoodsStock(wareHouseIds, goodsDefId, toussedefIdOrMaterialDefId); } + + @Override + public void addToList(Collection goodsStocks, + TousseInstance tousseInstance, WareHouse wareHouse) { + if(tousseInstance == null || wareHouse == null || goodsStocks == null){ + return ; + } + GoodsStock find = findTousseGoodsStock(goodsStocks,wareHouse.getId(), + tousseInstance.getTousseDefinitionAncestorID()); + if(find == null){ + find = new GoodsStock(); + find.setGoodsType(GoodsStock.TYPE_TOUSSE); + find.setName(tousseInstance.getTousseName()); + find.setOrgUnitCode(wareHouse.getOrgUnitCode()); + find.setOrgUnitName(wareHouse.getOrgUnitName()); + find.setTousseDefinitionId(tousseInstance.getTousseDefinitionAncestorID()); + find.setWareHouseId(wareHouse.getId()); + find.setWareHouseName(wareHouse.getName()); + goodsStocks.add(find); + } + find.setAmount(MathTools.add(find.getAmount(), 1).intValue()); + } } Index: ssts-web/src/test/resources/test/forgon/disinfectsystem/packing/AllTests.xml =================================================================== diff -u -r16910 -r17148 --- ssts-web/src/test/resources/test/forgon/disinfectsystem/packing/AllTests.xml (.../AllTests.xml) (revision 16910) +++ ssts-web/src/test/resources/test/forgon/disinfectsystem/packing/AllTests.xml (.../AllTests.xml) (revision 17148) @@ -13,6 +13,7 @@ + \ No newline at end of file Index: ssts-web/src/test/java/test/forgon/disinfectsystem/goodsstock/service/GoodsStockManagerTests.java =================================================================== diff -u --- ssts-web/src/test/java/test/forgon/disinfectsystem/goodsstock/service/GoodsStockManagerTests.java (revision 0) +++ ssts-web/src/test/java/test/forgon/disinfectsystem/goodsstock/service/GoodsStockManagerTests.java (revision 17148) @@ -0,0 +1,214 @@ +package test.forgon.disinfectsystem.goodsstock.service; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.exception.GenericJDBCException; +import org.springframework.orm.hibernate4.HibernateJdbcException; +import org.springframework.orm.hibernate4.HibernateSystemException; +import org.springframework.test.annotation.Rollback; +import org.testng.annotations.Test; + +import com.forgon.disinfectsystem.basedatamanager.goodsstock.service.GoodsStockManager; +import com.forgon.disinfectsystem.entity.basedatamanager.warehouse.WareHouse; +import com.forgon.disinfectsystem.entity.goodsstock.GoodsStock; +import com.forgon.runwithtrans.model.RunWithTransNewTask; + +import test.forgon.constant.Constants; +import test.forgon.disinfectsystem.AbstractCSSDTest; +import static org.testng.Assert.*; + +public class GoodsStockManagerTests extends AbstractCSSDTest { + private Long tousseDefinitionId; + private Long wareHouseId; + /** + * 测试多线程环境下出库 + * @throws Exception + */ + @Test + @Rollback(false) + public void testSaveOrUpdateGoodsStockForOut() throws Exception{ + prepareOut(); + + Thread t1 = new Thread(new RunOutTask()); + Thread t2 = new Thread(new RunOutTask()); + Thread t3 = new Thread(new RunOutTask()); + Thread t4 = new Thread(new RunOutTask()); + t1.start(); + t2.start(); + t3.start(); + t4.start(); + + t1.join(); + t2.join(); + t3.join(); + t4.join(); + + List gds = goodsStockManager.getTousseStock(wareHouseId, tousseDefinitionId); + assertNotNull(gds); + assertEquals(gds.size(), 1); + assertEquals(gds.get(0).getAmount().intValue(),0); + + } + + private void initMyData() { + initCSSDData(); + + tousseDefinitionId = tousseDefinitionManager.getTousseDefinitionByName("Test开胸包").getAncestorID(); + WareHouse wh = wareHouseManager.getDefaultWareHouseByUnitCode(Constants.ORG_UNIT_CODE_CSSD); + wareHouseId = wh.getId(); + + cleanData(); + } + + /** + * 清除可能已经存在的数据 + */ + private void cleanData() { + List gds = goodsStockManager.getTousseStock(wareHouseId, tousseDefinitionId); + for(GoodsStock gd : gds){ + goodsStockManager.delete(gd); + } + gds = goodsStockManager.getTousseStock(wareHouseId, tousseDefinitionId); + assertEquals(gds.size(), 0); + } + + private GoodsStock newGoodsStock(int amount) { + GoodsStock gs = new GoodsStock(); + gs.setAmount(amount); + gs.setWareHouseId(wareHouseId); + gs.setTousseDefinitionId(tousseDefinitionId); + return gs; + } + + private void prepareOut() { + runWithTransNewManager.runWith_TRANS_NEW(new RunWithTransNewTask() { + @Override + public void runTask() { + initMyData(); + + GoodsStock gs = newGoodsStock(4*2);//入库8个; + goodsStockManager.save(gs); + } + }); + } + + private class RunOutTask implements Runnable{ + @Override + public void run() { + boolean success = false; + System.out.println(Thread.currentThread().getName() + "开始运行"); + while(!success){ + try{ + runWithTransNewManager.runWith_TRANS_NEW(new RunWithTransNewTaskImpl()); + success = true; + }catch(HibernateJdbcException e){ + success = false; + }catch(GenericJDBCException e){ + success = false; + }catch(HibernateSystemException e){ + success = false; + } + if(!success){ + System.out.println(Thread.currentThread().getName() + "超时,重试"); + } + } + System.out.println(Thread.currentThread().getName() + "结束运行"); + } + + class RunWithTransNewTaskImpl implements RunWithTransNewTask{ + @Override + public void runTask() { + List gsList = new ArrayList(); + gsList.add(newGoodsStock(1)); + gsList.add(newGoodsStock(1)); + goodsStockManager.saveOrUpdateGoodsStock(gsList, GoodsStockManager.MODE_OUTSTOCK); + System.out.println(Thread.currentThread().getName() + " 扣库存成功"); + +// for(int i = 0; i < 2;++i){ +// GoodsStock gs = newGoodsStock(1); +// goodsStockManager.saveOrUpdateGoodsStock(gs, GoodsStockManager.MODE_OUTSTOCK); +// System.out.println(Thread.currentThread().getName() + ":第" + i + "次扣库存成功"); +// } + } + } + } + /** + * 测试入库 + * @throws Exception + */ + @Test + @Rollback(false) + public void testSaveOrUpdateGoodsStockForIn() throws Exception{ + prepareIn(); + int threadCount = 90;//线程数量 + for(int amount = 1; amount < 5;++amount){ //一个线程一次保存的库存数量 + for(int i = 0;i < 5;++i){ //循环执行5次 + System.out.println("amount=" + amount + " threadCount=" + threadCount + " i=" + i); + Thread[] ts = new Thread[threadCount]; + + for(int j = 0;j gds = goodsStockManager.getTousseStock(wareHouseId, tousseDefinitionId); + assertNotNull(gds); + assertEquals(gds.size(), 1); //只有一条库存记录 + assertEquals(gds.get(0).getAmount().intValue(),threadCount * amount); //每个线程入库amount个 + runWithTransNewManager.runWith_TRANS_NEW(new RunWithTransNewTask() { + @Override + public void runTask() { + cleanData(); + } + }); + + } + } + } + private void prepareIn(){ + runWithTransNewManager.runWith_TRANS_NEW(new RunWithTransNewTask() { + @Override + public void runTask() { + initMyData(); + } + }); + } + /** + * 保存库存的多线程方法.线程一次执行插入数量为10的 + * @author kzh + * + */ + private class RunInTask implements Runnable{ + int amount; + /** + * @param amount 插入的库存记录的数量 + */ + public RunInTask(int amount){ + this.amount = amount; + } + @Override + public void run() { + System.out.println(Thread.currentThread().getName() + "开始运行"); + List list = new ArrayList(); + for(int i = 0;i < amount;++i){ + list.add(newGoodsStock(1)); + } + runWithTransNewManager.runWith_TRANS_NEW(new RunWithTransNewTask() { + @Override + public void runTask() { + goodsStockManager.saveOrUpdateGoodsStock(list, GoodsStockManager.MODE_INSTOCK); + } + }); + + System.out.println(Thread.currentThread().getName() + "结束运行"); + } + } +} Index: ssts-sterile/src/main/java/com/forgon/disinfectsystem/sterilizationmanager/sterilizationrecord/service/SterilizationRecordManager.java =================================================================== diff -u -r17114 -r17148 --- ssts-sterile/src/main/java/com/forgon/disinfectsystem/sterilizationmanager/sterilizationrecord/service/SterilizationRecordManager.java (.../SterilizationRecordManager.java) (revision 17114) +++ ssts-sterile/src/main/java/com/forgon/disinfectsystem/sterilizationmanager/sterilizationrecord/service/SterilizationRecordManager.java (.../SterilizationRecordManager.java) (revision 17148) @@ -14,11 +14,12 @@ import com.forgon.disinfectsystem.entity.sterilizationmanager.sterilizationrecord.SterilizationRecord; import com.forgon.disinfectsystem.entity.sterilizationmanager.sterilizationrecord.SterilizationRecordPic; import com.forgon.disinfectsystem.entity.sterilizationmanager.sterilizerrecord.SterilizerRecord; +import com.forgon.tools.hibernate.BasePoManager; /** * @author WangYi 2012-2-24 */ -public interface SterilizationRecordManager { +public interface SterilizationRecordManager extends BasePoManager { public void saveOrUpdate(SterilizationRecord sterilizationRecord); @@ -62,9 +63,9 @@ /** * 删除灭菌记录,修改灭菌记录中包实例的状态为已审核,修改ReviewedBasket关联的灭菌筐的状态为灭菌装载,修改ReviewedBasket关联的器械包的状态为已审核 * @param sterilizationRecordIdStr 灭菌记录的id,多个id以;分隔 - * @return 删除是否成功的描述信息,json格式 + * @return true,删除成功,false 删除失败 */ - public String delete(String sterilizationRecordIdStr); + public boolean delete(String sterilizationRecordIdStr); public List getAllSterilizationRecord(); Index: ssts-web/src/test/resources/test/forgon/disinfectsystem/goodsstock/service/AllTests.xml =================================================================== diff -u --- ssts-web/src/test/resources/test/forgon/disinfectsystem/goodsstock/service/AllTests.xml (revision 0) +++ ssts-web/src/test/resources/test/forgon/disinfectsystem/goodsstock/service/AllTests.xml (revision 17148) @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file Index: ssts-sterile/src/main/java/com/forgon/disinfectsystem/sterilizationmanager/sterilizationrecord/service/SterilizationRecordManagerImpl.java =================================================================== diff -u -r17114 -r17148 --- ssts-sterile/src/main/java/com/forgon/disinfectsystem/sterilizationmanager/sterilizationrecord/service/SterilizationRecordManagerImpl.java (.../SterilizationRecordManagerImpl.java) (revision 17114) +++ ssts-sterile/src/main/java/com/forgon/disinfectsystem/sterilizationmanager/sterilizationrecord/service/SterilizationRecordManagerImpl.java (.../SterilizationRecordManagerImpl.java) (revision 17148) @@ -75,6 +75,7 @@ import com.forgon.tools.Path; import com.forgon.tools.StrutsParamUtils; import com.forgon.tools.db.DatabaseUtil; +import com.forgon.tools.hibernate.BasePoManagerImpl; import com.forgon.tools.hibernate.ObjectDao; import com.forgon.tools.json.JSONUtil; import com.forgon.tools.string.StringTools; @@ -83,13 +84,11 @@ * @author WangYi 2012-2-24 */ -public class SterilizationRecordManagerImpl implements +public class SterilizationRecordManagerImpl extends BasePoManagerImpl implements SterilizationRecordManager { private Logger logger = Logger.getLogger(SterilizationRecordManagerImpl.class); - private ObjectDao objectDao; - private SerialNumManager serialNumManager; private SterilizerManager sterilizerManager; @@ -134,10 +133,6 @@ this.dateQueryAdapter = dateQueryAdapter; } - public void setObjectDao(ObjectDao objectDao) { - this.objectDao = objectDao; - } - public void setSerialNumManager(SerialNumManager serialNumManager) { this.serialNumManager = serialNumManager; } @@ -356,18 +351,23 @@ boolean isFirstSupplyRoomUser = supplyRoomConfig != null && supplyRoomConfig.getSupplyRoomType() == SupplyRoomConfig.SUPPLYROOM_TYPE_1; - Map tousseMap = new HashMap(); - Map> tousseListMap = new HashMap>(); +// Map tousseMap = new HashMap(); +// Map> tousseListMap = new HashMap>(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - for (Long sterilizationRecordId : sterilizationRecordIds) { - SterilizationRecord sterilizationRecord = getSterilizationRecordById(sterilizationRecordId); + List goodsStockList = new ArrayList(); + List records = getCollection("id", sterilizationRecordIds); + if(CollectionUtils.isEmpty(records)){ + return JSONUtil.buildJsonObject(false, "未找到对应的灭菌单"); + } + for (SterilizationRecord sterilizationRecord : records) { +// SterilizationRecord sterilizationRecord = getSterilizationRecordById(sterilizationRecordId); if (sterilizationRecord == null || !(sterilizationRecord.isSterilizationBegin() || sterilizationRecord.isSterilizationInterrupt()) ) {// 灭菌中和灭菌中断才能进行灭菌完成操作 continue; } if( sterilizationRecord.isSterilizationInterrupt() ){ // 如果是灭菌中断 找到相关的中断信息 记录继续灭菌时间和中断后操作类型 - updateInterruptRecordFinishType(sterilizationRecordId,SterilizationInterruptRecord.ITERRUPT_FINISH_FINISH); + updateInterruptRecordFinishType(sterilizationRecord.getId(),SterilizationInterruptRecord.ITERRUPT_FINISH_FINISH); } Sterilizer sterilizer = sterilizationRecord .getSterilizer(); @@ -420,7 +420,7 @@ } resetNoVirtualBasketStatus(sterilizationRecord); List allTousseInstancesOfSterile = getAllTousseInstancesOfSterile(sterilizationRecord,true); - List goodsStockList = new ArrayList(); + WareHouse defaultWareHouse = wareHouseManager.getDefaultWareHouseByUnitCode(orgUnitCode); // 更新器械包的状态 for (TousseInstance tousseInstance : allTousseInstancesOfSterile) { @@ -434,23 +434,14 @@ //只有当所属聚合包实例的id属性为空(即聚合包实例及不属于任何聚合包实例内的普通器械包实例)时才计算库存,比如聚合包内普通器械包不计算到库存中 if(needFinishConfirm == false && tousseInstance.getComboTousseInstanceId() == null){ // 不需要灭菌确认,灭菌完成时加库存 - GoodsStock goodsStock = TousseInstanceUtils.newGoodsStock(tousseInstance,defaultWareHouse); - goodsStockList.add(goodsStock); + goodsStockManager.addToList(goodsStockList, tousseInstance, defaultWareHouse); +// GoodsStock goodsStock = TousseInstanceUtils.newGoodsStock(tousseInstance,defaultWareHouse); +// goodsStockList.add(goodsStock); tousseInstanceManager.setToWarehouse(tousseInstance, defaultWareHouse); } tousseInstanceManager.saveOrUpdate(tousseInstance); } - //修改库存 - try { - //第1炉时有可能灭菌器械为空 - if(CollectionUtils.isNotEmpty(goodsStockList)){ - goodsStockManager.saveOrUpdateGoodsStock(goodsStockList, GoodsStockManager.MODE_INSTOCK); - } - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - throw new RuntimeException(e.getMessage()); - } + if (!isFirstSupplyRoomUser) { SupplyRoomConfig supplyRoomConfigParams = supplyRoomConfigManager.getSystemParamsObj(); //判断如果配置二级供应室是否自动发货不为否才自动发货,否则不自动发货 @@ -459,21 +450,21 @@ generateInvoiceForSecondSupplyRoom(sterilizationRecord); } } else { - for (TousseInstance tousseInstance : allTousseInstancesOfSterile) { - // 二级供应室不需要库存,只有供应室的人登录系统才记录库存 - if (tousseInstance.getForeignProxyItem_id() == null) {// 不是外部代理灭菌器械物品时,才需要更新库存 - String tousseName = tousseInstance.getTousseName(); - Integer tousseAmount = tousseMap.get(tousseName); - tousseMap.put(tousseName, (tousseAmount==null?0:tousseAmount)+1); - - List list = tousseListMap.get(tousseName); - if(list == null){ - list = new ArrayList(); - } - list.add(tousseInstance); - tousseListMap.put(tousseName, list); - } - } +// for (TousseInstance tousseInstance : allTousseInstancesOfSterile) { +// // 二级供应室不需要库存,只有供应室的人登录系统才记录库存 +// if (tousseInstance.getForeignProxyItem_id() == null) {// 不是外部代理灭菌器械物品时,才需要更新库存 +//// String tousseName = tousseInstance.getTousseName(); +//// Integer tousseAmount = tousseMap.get(tousseName); +//// tousseMap.put(tousseName, (tousseAmount==null?0:tousseAmount)+1); +// +//// List list = tousseListMap.get(tousseName); +//// if(list == null){ +//// list = new ArrayList(); +//// } +//// list.add(tousseInstance); +//// tousseListMap.put(tousseName, list); +// } +// } } if(StringUtils.isBlank(finishOperater)){ sterilizationRecord.setFinishOperater(AcegiHelper.getLoginUserFullName()); @@ -546,6 +537,17 @@ saveOrUpdate(sterilizationRecord); } + //修改库存 + try { + //第1炉时有可能灭菌器械为空 + if(CollectionUtils.isNotEmpty(goodsStockList)){ + goodsStockManager.saveOrUpdateGoodsStock(goodsStockList, GoodsStockManager.MODE_INSTOCK); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new RuntimeException(e.getMessage()); + } //更新库存(旧版本的库存不再使用,代码注释) //updateTousseStock(tousseMap); //updateFirstSupplyRoomStock(supplyRoomConfig,tousseMap,tousseListMap); @@ -584,8 +586,9 @@ //只有当所属聚合包实例的id属性为空(即聚合包实例及不属于任何聚合包实例内的普通器械包实例)时才计算库存,比如聚合包内普通器械包不计算到库存中 if(tousseInstance.getComboTousseInstanceId() == null){ // 添加库存 - GoodsStock goodsStock = TousseInstanceUtils.newGoodsStock(tousseInstance,defaultWareHouse); - goodsStockList.add(goodsStock); +// GoodsStock goodsStock = TousseInstanceUtils.newGoodsStock(tousseInstance,defaultWareHouse); +// goodsStockList.add(goodsStock); + goodsStockManager.addToList(goodsStockList, tousseInstance, defaultWareHouse); tousseInstanceManager.setToWarehouse(tousseInstance, defaultWareHouse); } } @@ -979,14 +982,14 @@ } } @Override - public String delete(String sterilizationRecordIdStr) { - JSONObject message = new JSONObject(); + public boolean delete(String sterilizationRecordIdStr) { + boolean success = false; try { if (StringUtils.isNotBlank(sterilizationRecordIdStr)) { - String[] str = sterilizationRecordIdStr.split(";"); - for (String id : str) { + Collection ids = StringTools.parseToLongs(sterilizationRecordIdStr, ";"); + Collection sterilizationRecords = getCollection(ids); + for (SterilizationRecord sterilizationRecord : sterilizationRecords) { // 修改包实例的状态,以审核;删除灭菌记录 - SterilizationRecord sterilizationRecord = getSterilizationRecordById(Long.valueOf(id)); if(sterilizationRecord == null){ continue; } @@ -1008,13 +1011,13 @@ } deleteSterilizationRecord(sterilizationRecord); } - message.put("success", true); + success = true; } } catch (Exception e) { - message.put("success", false); + success = false; e.printStackTrace(); } - return message.toString(); + return success; } /** * 保存或更新灭菌记录 @@ -2534,14 +2537,17 @@ private void updateInterruptRecordFinishType(Long sterilizationRecordId,String inerruptFinishType){ if(sterilizationRecordId == null || StringUtils.isBlank(inerruptFinishType) ) return ; - String sql = String.format("where po.sterilizationRecordId = %d and po.interruptFinishDate is null",sterilizationRecordId); - SterilizationInterruptRecord si = (SterilizationInterruptRecord)objectDao.getBySql(SterilizationInterruptRecord.class.getSimpleName(), sql); - if( si != null) - { - si.setInterruptOptType(inerruptFinishType); - si.setInterruptFinishDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); - objectDao.saveOrUpdate(si); - } + String sql = String.format("where sterilizationRecordId = %d and interruptFinishDate is null",sterilizationRecordId); +// SterilizationInterruptRecord si = (SterilizationInterruptRecord)objectDao.getBySql(SterilizationInterruptRecord.class.getSimpleName(), sql); +// if( si != null) +// { +// si.setInterruptOptType(inerruptFinishType); +// si.setInterruptFinishDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); +// objectDao.saveOrUpdate(si); +// } + objectDao.executeUpdate(" update " + SterilizationInterruptRecord.class.getSimpleName() + + " set interruptOptType = '" + inerruptFinishType + + "',interruptFinishDate='" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "' " + sql); } @Override Index: ssts-sterile/src/main/java/com/forgon/disinfectsystem/sterilizationmanager/sterilizationrecord/action/SterilizationRecordAction.java =================================================================== diff -u -r17005 -r17148 --- ssts-sterile/src/main/java/com/forgon/disinfectsystem/sterilizationmanager/sterilizationrecord/action/SterilizationRecordAction.java (.../SterilizationRecordAction.java) (revision 17005) +++ ssts-sterile/src/main/java/com/forgon/disinfectsystem/sterilizationmanager/sterilizationrecord/action/SterilizationRecordAction.java (.../SterilizationRecordAction.java) (revision 17148) @@ -285,15 +285,8 @@ */ public void deleteSterilizationRecord() { String idStr = StrutsParamUtils.getPraramValue("ids", ""); - String message = sterilizationRecordManager.delete(idStr); - HttpServletResponse httpServletResponse = StrutsParamUtils - .getResponse(); - httpServletResponse.setCharacterEncoding("UTF-8"); - try { - httpServletResponse.getWriter().print(message); - } catch (IOException e) { - e.printStackTrace(); - } + boolean success = sterilizationRecordManager.delete(idStr); + StrutsResponseUtils.output(success); } /**