Index: ssts-returngoods/src/main/java/com/forgon/disinfectsystem/returngoodsrecord/action/ReturnGoodsRecordAction.java =================================================================== diff -u -r37339 -r37391 --- ssts-returngoods/src/main/java/com/forgon/disinfectsystem/returngoodsrecord/action/ReturnGoodsRecordAction.java (.../ReturnGoodsRecordAction.java) (revision 37339) +++ ssts-returngoods/src/main/java/com/forgon/disinfectsystem/returngoodsrecord/action/ReturnGoodsRecordAction.java (.../ReturnGoodsRecordAction.java) (revision 37391) @@ -626,6 +626,8 @@ List newReturnTousseItems = new ArrayList(); returnGoodsRecord.setReturnGoodsItems(newReturnTousseItems); + //设置退货记录的处理科室编码为当前用户所属科室编码 + returnGoodsRecord.setHandleDepartCode(AcegiHelper.getLoginUser().getCurrentOrgUnitCode()); // 拿到页面的退货明细 // 格式为:ID@#包名@#数量@#是否重新发货@#是否重新装配@#条码...@;ID@#包名@#数量@#是否重新发货@#是否重新装配@#条码... Index: ssts-storagelocation/src/main/resources/rebel.xml =================================================================== diff -u --- ssts-storagelocation/src/main/resources/rebel.xml (revision 0) +++ ssts-storagelocation/src/main/resources/rebel.xml (revision 37391) @@ -0,0 +1,9 @@ + + + + + + + + + Index: ssts-storagelocation/build.gradle =================================================================== diff -u --- ssts-storagelocation/build.gradle (revision 0) +++ ssts-storagelocation/build.gradle (revision 37391) @@ -0,0 +1,20 @@ +ext.moduleName = 'ssts-storagelocation' + + +jar { + manifest { + attributes 'Implementation-Title': 'SSTS storagelocation', + 'Implementation-Version': version + } +} + +dependencies { + + //compile group: 'com.forgon', name: 'forgon-tools', version:'2.0.0' + //compile group: 'com.forgon', name: 'forgon-core', version:'2.0.0' + //compile group: 'com.forgon', name: 'ssts-basedata', version:'2.0.0' + //compile group: 'com.forgon', name: 'ssts-diposablegoods', version:'2.0.0' + //compile group: 'com.forgon', name: 'ssts-tousse', version:'2.0.0' + //compile group: 'com.forgon', name: 'ssts-print', version:'2.0.0' + +} Index: ssts-storagelocation/src/main/java/com/forgon/disinfectsystem/basedatamanager/storagelocation/goodsaccess/action/StorageLocationGoodsAccessAction.java =================================================================== diff -u --- ssts-storagelocation/src/main/java/com/forgon/disinfectsystem/basedatamanager/storagelocation/goodsaccess/action/StorageLocationGoodsAccessAction.java (revision 0) +++ ssts-storagelocation/src/main/java/com/forgon/disinfectsystem/basedatamanager/storagelocation/goodsaccess/action/StorageLocationGoodsAccessAction.java (revision 37391) @@ -0,0 +1,107 @@ +package com.forgon.disinfectsystem.basedatamanager.storagelocation.goodsaccess.action; + +import net.sf.json.JSONObject; + +import org.apache.struts2.convention.annotation.Action; +import org.apache.struts2.convention.annotation.Namespace; +import org.apache.struts2.convention.annotation.ParentPackage; + +import com.forgon.disinfectsystem.basedatamanager.storagelocation.goodsaccess.service.StorageLocationGoodsAccessManager; +import com.forgon.tools.StrutsParamUtils; +import com.forgon.tools.StrutsResponseUtils; +import com.forgon.tools.json.JSONUtil; + +/** + * 库位物品存取的接口BJDXZLYY-44 + */ +@ParentPackage(value = "default") +@Namespace(value = "/disinfectSystem") +@Action(value = "storageLocationGoodsAccessAction") +public class StorageLocationGoodsAccessAction { + + private StorageLocationGoodsAccessManager storageLocationGoodsAccessManager; + + public void setStorageLocationGoodsAccessManager(StorageLocationGoodsAccessManager storageLocationGoodsAccessManager) { + this.storageLocationGoodsAccessManager = storageLocationGoodsAccessManager; + } + + /** + * 从库位存入/取出器械包实例 + * @param barcodes 刚扫描到的条码 + * @param storageBarcode 库位条码 + * @param extraParam 库存记录id + * @param status 状态(放入/取出) + * @return + */ + public void scanBarcodeAndAddTousseToStorage () { + String result = JSONUtil.buildJsonObject(true).toString(); + try { + String barcode = StrutsParamUtils.getPraramValue("barcode", ""); + String storageBarcode = StrutsParamUtils.getPraramValue("storageBarcode", ""); + String status = StrutsParamUtils.getPraramValue("status", ""); + result = storageLocationGoodsAccessManager.scanBarcodeAndAddTousseToStorage(barcode, storageBarcode, status); + } catch (Exception e) { + e.printStackTrace(); + result = JSONUtil.buildJsonObject(false, e.getMessage()).toString(); + } + StrutsResponseUtils.output(result); + } + + /** + * 【库位查看】页面扫描条码接口 + */ + public void scanBarcode(){ + JSONObject result = JSONUtil.buildJsonObject(true); + try { + //器械包实例条码或者库位条码 + String barcode = StrutsParamUtils.getPraramValue("barcode", ""); + //库位条码 + String storageBarcode = StrutsParamUtils.getPraramValue("storageBarcode", ""); + //取出/存入 + String status = StrutsParamUtils.getPraramValue("status", ""); + JSONObject data = storageLocationGoodsAccessManager.scanBarcode(barcode, storageBarcode, status); + result = JSONUtil.buildJsonObject(true, data); + } catch (Exception e) { + e.printStackTrace(); + result = JSONUtil.buildJsonObject(false, e.getMessage()); + } + StrutsResponseUtils.output(result); + } + + /** + * 【库位查看】页面物品存入接口 + */ + public void storageLocationItemStorage(){ + JSONObject result = JSONUtil.buildJsonObject(true, "存入成功!"); + try { + //器械包实例Id + String tousseInstanceIds = StrutsParamUtils.getPraramValue("tousseInstanceIds", ""); + //库位条码 + Long storageLocationId = StrutsParamUtils.getPraramLongValue("storageLocationId", null); + storageLocationGoodsAccessManager.storageLocationItemStorage(tousseInstanceIds, storageLocationId); + } catch (Exception e) { + e.printStackTrace(); + result = JSONUtil.buildJsonObject(false, "存入失败:" + e.getMessage()); + } + StrutsResponseUtils.output(result); + } + + /** + * 【库位查看】页面物品存入接口 + */ + public void storageLocationItemRetrieval(){ + JSONObject result = JSONUtil.buildJsonObject(true, "取出成功!"); + try { + //器械包实例Id + String tousseInstanceIds = StrutsParamUtils.getPraramValue("tousseInstanceIds", ""); + //库位条码 + Long storageLocationId = StrutsParamUtils.getPraramLongValue("storageLocationId", null); + storageLocationGoodsAccessManager.storageLocationItemRetrieval(tousseInstanceIds, storageLocationId); + } catch (Exception e) { + e.printStackTrace(); + result = JSONUtil.buildJsonObject(false, "取出失败:" + e.getMessage()); + } + StrutsResponseUtils.output(result); + } + +} Index: ssts-invoice/src/main/java/com/forgon/disinfectsystem/invoicemanager/service/InvoiceManager.java =================================================================== diff -u -r36118 -r37391 --- ssts-invoice/src/main/java/com/forgon/disinfectsystem/invoicemanager/service/InvoiceManager.java (.../InvoiceManager.java) (revision 36118) +++ ssts-invoice/src/main/java/com/forgon/disinfectsystem/invoicemanager/service/InvoiceManager.java (.../InvoiceManager.java) (revision 37391) @@ -10,6 +10,8 @@ import com.forgon.disinfectsystem.entity.assestmanagement.ExpensiveGoodsGodownEntry; import com.forgon.disinfectsystem.entity.basedatamanager.signRecord.SignRecord; +import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseInstance; +import com.forgon.disinfectsystem.entity.basedatamanager.warehouse.StorageLocation; import com.forgon.disinfectsystem.entity.invoicemanager.DiposableGoodsItem; import com.forgon.disinfectsystem.entity.invoicemanager.Invoice; import com.forgon.disinfectsystem.entity.invoicemanager.TimeQuantum; @@ -385,5 +387,13 @@ * @return */ public JSONObject getDisposableGoodsStockByDepartCodingOrInvoicePlanId(Long warehouseId , String disposableGoodsBarcode); + + /** + * 当前登录科室把已灭菌、已消毒的器械包从当前登录科室的库位中取出时,需要由供应室自定义发货到当前登录科室 + * @param tousseInstances + * @param storageLocation + */ + public void autoInvoiceTousseInstanceAfterTakeOutStorage(String currentOrgUnitCode, List tousseInstances, + StorageLocation storageLocation); } Index: ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/warehouse/service/StorageLocationManager.java =================================================================== diff -u -r36801 -r37391 --- ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/warehouse/service/StorageLocationManager.java (.../StorageLocationManager.java) (revision 36801) +++ ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/warehouse/service/StorageLocationManager.java (.../StorageLocationManager.java) (revision 37391) @@ -182,4 +182,12 @@ */ public List loadStorageLocationByOrgUnitCode(String orgUnitCode, String spell); + /** + * 加载科室或者仓库或者库位下的第一个可放入物品的库位(叶子节点) + * @param objId + * @param type + * @return + */ + public StorageLocation loadFirstStorageLocation(String objId, String type); + } Index: ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/warehouse/service/StorageLocationManagerImpl.java =================================================================== diff -u -r36801 -r37391 --- ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/warehouse/service/StorageLocationManagerImpl.java (.../StorageLocationManagerImpl.java) (revision 36801) +++ ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/warehouse/service/StorageLocationManagerImpl.java (.../StorageLocationManagerImpl.java) (revision 37391) @@ -223,6 +223,60 @@ return jsonArray.toString(); } + @SuppressWarnings("unchecked") + @Override + public StorageLocation loadFirstStorageLocation(String id, String storageLocationType){ + if(StringUtils.isBlank(storageLocationType) || !DatabaseUtil.isPoIdValid(id)){ + throw new RuntimeException("参数异常!"); + } + + String parentIdSql = String.format(" and po.id not in (select parentId from %s) order by po.wareHouseId, po.id ", StorageLocation.class.getSimpleName()); + if ("orgUnit".equals(storageLocationType)) { + OrgUnit orgUnit = (OrgUnit) objectDao.getById(OrgUnit.class.getSimpleName(), id); + if(orgUnit == null){ + throw new RuntimeException("参数异常!"); + } + //查询科室下的第一个仓库的第一个库位 + String sql = String.format("select po from %s po where po.orgUnitCode = '%s' %s ", + StorageLocation.class.getSimpleName(), + orgUnit.getOrgUnitCoding(), + parentIdSql); + List list = objectDao.findByHql(sql); + if(CollectionUtils.isEmpty(list)){ + return null; + } + return list.get(0); + } + if ("storage".equals(storageLocationType)) { + //查询科室下的第一个仓库的第一个库位 + String sql = String.format("select po from %s po where po.wareHouseId = %s %s ", + StorageLocation.class.getSimpleName(), + id, + parentIdSql); + List list = objectDao.findByHql(sql); + if(CollectionUtils.isEmpty(list)){ + return null; + } + return list.get(0); + } + if ("storageLocation".equals(storageLocationType)){ + StorageLocation storageLocation = (StorageLocation) objectDao.getById(StorageLocation.class.getSimpleName(), id); + if(storageLocation == null){ + return null; + } + while(true){ + Long parentId = storageLocation.getId(); + List childStorageLocationList = objectDao.findByProperty(StorageLocation.class.getSimpleName(), "parentId", parentId); + if(CollectionUtils.isEmpty(childStorageLocationList)){ + return storageLocation; + } + storageLocation = childStorageLocationList.get(0); + } + + } + return null; + } + /** * 根据仓库ID查找库位 * @param id Index: ssts-storagelocation/src/main/java/com/forgon/disinfectsystem/basedatamanager/storagelocation/goodsaccess/service/StorageLocationGoodsAccessManager.java =================================================================== diff -u --- ssts-storagelocation/src/main/java/com/forgon/disinfectsystem/basedatamanager/storagelocation/goodsaccess/service/StorageLocationGoodsAccessManager.java (revision 0) +++ ssts-storagelocation/src/main/java/com/forgon/disinfectsystem/basedatamanager/storagelocation/goodsaccess/service/StorageLocationGoodsAccessManager.java (revision 37391) @@ -0,0 +1,43 @@ +package com.forgon.disinfectsystem.basedatamanager.storagelocation.goodsaccess.service; + +import net.sf.json.JSONObject; + +/** + * 库位物品存取的managerBJDXZLYY-44 + * + */ +public interface StorageLocationGoodsAccessManager { + + /** + * 库位物品存取的接口 + * @param barcode + * @param storageBarcode + * @param status + * @return + */ + public String scanBarcodeAndAddTousseToStorage(String barcode, String storageBarcode, String status); + + /** + * 【库位查看】页面扫描条码接口 + * @param barcode 包实例或者库位条码 + * @param storageBarcode 库位条码 + * @param status 取出/存入 + * @return + */ + public JSONObject scanBarcode(String barcode, String storageBarcode, String status); + + /** + * 【库位查看】页面物品存入接口 + * @param tousseInstanceIds 器械包实例ID + * @param storageLocationId 库位ID + */ + public void storageLocationItemStorage(String tousseInstanceIds, Long storageLocationId); + + /** + * 【库位查看】页面物品取出接口 + * @param tousseInstanceIds 器械包实例ID + * @param storageLocationId 库位ID + */ + public void storageLocationItemRetrieval(String tousseInstanceIds, Long storageLocationId); + +} Index: ssts-web/src/main/webapp/WEB-INF/spring/applicationContext-disinfectsystem-service.xml =================================================================== diff -u -r37357 -r37391 --- ssts-web/src/main/webapp/WEB-INF/spring/applicationContext-disinfectsystem-service.xml (.../applicationContext-disinfectsystem-service.xml) (revision 37357) +++ ssts-web/src/main/webapp/WEB-INF/spring/applicationContext-disinfectsystem-service.xml (.../applicationContext-disinfectsystem-service.xml) (revision 37391) @@ -2976,4 +2976,15 @@ + + + + + + + + + \ No newline at end of file Index: ssts-tousse/src/main/java/com/forgon/disinfectsystem/tousse/toussedefinition/service/TousseInstanceManagerImpl.java =================================================================== diff -u -r37351 -r37391 --- ssts-tousse/src/main/java/com/forgon/disinfectsystem/tousse/toussedefinition/service/TousseInstanceManagerImpl.java (.../TousseInstanceManagerImpl.java) (revision 37351) +++ ssts-tousse/src/main/java/com/forgon/disinfectsystem/tousse/toussedefinition/service/TousseInstanceManagerImpl.java (.../TousseInstanceManagerImpl.java) (revision 37391) @@ -4090,10 +4090,15 @@ @Override public void setLocation(TousseInstance tousseInstance,String orgUnitCode,String orgUnitName){ - if(tousseInstance != null){ - tousseInstance.setLocation(orgUnitCode); - tousseInstance.setLocationForDisplay(orgUnitName); - } + if(tousseInstance != null){ + if(StringUtils.isNotBlank(tousseInstance.getLocation_2())){ + tousseInstance.setLocation_2(orgUnitCode); + tousseInstance.setLocationForDisplay2(orgUnitName); + }else{ + tousseInstance.setLocation(orgUnitCode); + tousseInstance.setLocationForDisplay(orgUnitName); + } + } } @Override public void setToDefaultWareHouse(TousseInstance tousseInstance, @@ -11044,13 +11049,26 @@ * @param storageLocation * @return */ - private boolean valideStorageLocation(String currentOrgUnitCode, StorageLocation storageLocation) { + @Override + public boolean valideStorageLocation(String currentOrgUnitCode, StorageLocation storageLocation) { if(storageLocation == null || StringUtils.isBlank(currentOrgUnitCode)){ throw new SystemException("参数异常"); } - // 不是当前登陆用户所属科室的库位,不允许进行物品存取操作 - if(!StringUtils.equals(currentOrgUnitCode, storageLocation.getOrgUnitCode())) { - throw new SystemException(storageLocation.getName() + "不属于本科室,请扫描本科室的库位!"); + boolean enableOperationReservationShippedToTraysOfKardexContainer = + ConfigUtils.getSystemSetConfigByNameBool("enableOperationReservationShippedToTraysOfKardexContainer"); + if(enableOperationReservationShippedToTraysOfKardexContainer){ + Set goodsShareOrgUnitCodes = loadGoodsShareOrgUnitCode(currentOrgUnitCode, "warehousePosition"); + if(CollectionUtils.isEmpty(goodsShareOrgUnitCodes) + || !goodsShareOrgUnitCodes.contains(currentOrgUnitCode) + || !goodsShareOrgUnitCodes.contains(storageLocation.getOrgUnitCode())){ + //卡迪斯货柜支持扫描其他物品共享科室的库房进行存取物品BJDXZLYY-44 + throw new SystemException(storageLocation.getName() + "不属于本科室,请扫描本科室或者物品共享科室的库位!"); + } + }else{ + // 不是当前登陆用户所属科室的库位,不允许进行物品存取操作 + if(!StringUtils.equals(currentOrgUnitCode, storageLocation.getOrgUnitCode())) { + throw new SystemException(storageLocation.getName() + "不属于本科室,请扫描本科室的库位!"); + } } // 不是抽屉(叶子节点),不允许存入物品 boolean isLeaf = storageLocationManager.storageLocationIsLeaf(storageLocation.getId().toString()); @@ -11922,7 +11940,8 @@ * @param allInvoiceTousseInstance * @param storageLocationId */ - private void batchPutTousseInstanceIntoStorageLoaction(List tousseInstances, + @Override + public void batchPutTousseInstanceIntoStorageLoaction(List tousseInstances, StorageLocation storageLocation, String orgUnitCode, String operateDetail) { if(storageLocation == null){ throw new SystemException("库位id无效!"); @@ -12592,12 +12611,13 @@ } /** - * 判断是否可以放入库位 + * 判断器械包实例是否可以放入库位 * @param allInvoiceTousseInstance * @param storageLocation - * @param orgUnitCode + * @param orgUnit */ - private void canTousseInstancePutIntoStorageLocation(List allInvoiceTousseInstance, + @Override + public void canTousseInstancePutIntoStorageLocation(List allInvoiceTousseInstance, StorageLocation storageLocation, OrgUnit orgUnit) { // 不是当前登陆用户所属科室的库位,不允许进行物品存取操作 @@ -12612,6 +12632,11 @@ } //物品共用科室配置 Set orgUnitCodes = loadGoodsShareOrgUnitCode(orgUnit.getOrgUnitCoding(), "warehousePosition"); + //“卡迪斯货柜联动”功能改进支持可将状态为“已灭菌”的物品存入库房BJDXZLYY-44 + boolean enableOperationReservationShippedToTraysOfKardexContainer = + ConfigUtils.getSystemSetConfigByNameBool("enableOperationReservationShippedToTraysOfKardexContainer"); + boolean warehousePositionGoodsShare = ConfigUtils.extendedFunctionConfig("extendedFunctionalityOfGoodsDepartShareConfig", "warehousePosition"); + boolean shippedToTraysOfKardexContainer = (enableOperationReservationShippedToTraysOfKardexContainer && warehousePositionGoodsShare); for (TousseInstance ti : allInvoiceTousseInstance) { TousseDefinition td = ti.getTousseDefinition(); // 支持可追溯的消毒包(器械包和消毒物品),不支持不追溯的消毒包; @@ -12624,12 +12649,22 @@ if(ti.isComboTousse()){ throw new SystemException(ti.getTousseName() + "是聚合包,库位管理不支持该类物品!"); } - // 包的状态必须为已发货或者已签收 - if (!(StringUtils.equals(ti.getStatus(), TousseInstance.STATUS_SIGNED) || StringUtils.equals(ti.getStatus(), TousseInstance.STATUS_SHIPPED))) { - throw new SystemException(ti.getTousseName() + "不是“已发货”或“已签收”状态!"); + + //包的状态必须为已发货或者已签收 + List tousseStatus = new ArrayList(); + tousseStatus.add(TousseInstance.STATUS_SIGNED); + tousseStatus.add(TousseInstance.STATUS_SHIPPED); + if(shippedToTraysOfKardexContainer){ + //卡迪斯货柜可将状态为“已灭菌”、“已消毒”的物品存入库房BJDXZLYY-44 + tousseStatus.add(TousseInstance.STATUS_STERILED); + tousseStatus.add(TousseInstance.STATUS_DISINFECTED); } - // 只能存入与登录用户相同科室的包 - if(!orgUnitCodes.contains(ti.getFinalLocation())){ + if (!tousseStatus.contains(ti.getStatus())) { + throw new SystemException(String.format("%s不是“%s”状态!", ti.getTousseName(), StringTools.join(tousseStatus, "”或“"))); + } + //器械包实例发货完成之后,返回发货目的科室编码;器械包实例未发货,则返回生产改包实例的供应室编码 + String finalLocation = loadTousseInstanceFinalLocationOrgUnitCode(ti, shippedToTraysOfKardexContainer); + if(!orgUnitCodes.contains(finalLocation)){ if(orgUnitCodes.size() == 1){ throw new SystemException("只能存入" + orgUnit.getName() + "科室的包!"); }else{ @@ -12654,6 +12689,25 @@ } /** + * 器械包实例发货完成之后,返回发货目的科室编码; + * 器械包实例未发货,则返回生产改包实例的供应室编码 + * @param ti + * @return + */ + private String loadTousseInstanceFinalLocationOrgUnitCode(TousseInstance ti, boolean enableSteriledTousseInStarage) { + if(ti == null){ + throw new RuntimeException("参数异常"); + } + //发货的目的科室编码 + String finalLocation = ti.getFinalLocation(); + if(enableSteriledTousseInStarage && (ti.isSteriled() || ti.isDisinfected())){ + //生产改包实例的供应室编码 + finalLocation = ti.getOrgUnitCoding(); + } + return finalLocation; + } + + /** * 物品共用科室的编码及当前科室编码的集合GDSRMYY-580 * @param currentOrgUnitCode 科室编码 * @param moduleName warehousePosition 库位管理功能;invoiceSign 物品签收功能 @@ -12671,19 +12725,9 @@ if(StringUtils.isBlank(moduleName)){ return goodsShareDepartSet; } + //extendedFunctionalityOfGoodsDepartShareConfig配置了对应功能模块的名称 + boolean moduleGoodsShare = ConfigUtils.extendedFunctionConfig("extendedFunctionalityOfGoodsDepartShareConfig", moduleName); - boolean moduleGoodsShare = false; - String extendedFunctionalityOfGoodsDepartShareConfigStr = CssdUtils.getSystemSetConfigByName("extendedFunctionalityOfGoodsDepartShareConfig"); - if(StringUtils.isNotBlank(extendedFunctionalityOfGoodsDepartShareConfigStr)){ - JSONArray extendedFunctionalityOfGoodsDepartShareConfigArray = JSONArray.fromObject(extendedFunctionalityOfGoodsDepartShareConfigStr); - for (int i = 0; i < extendedFunctionalityOfGoodsDepartShareConfigArray.size(); i++) { - String item = extendedFunctionalityOfGoodsDepartShareConfigArray.getString(i); - if(moduleName.equals(item)){ - moduleGoodsShare = true; - break; - } - } - } //没开启配置项,只能签收当前科室下的包实例 if(!moduleGoodsShare){ return goodsShareDepartSet; Index: ssts-storagelocation/.classpath =================================================================== diff -u --- ssts-storagelocation/.classpath (revision 0) +++ ssts-storagelocation/.classpath (revision 37391) @@ -0,0 +1,10 @@ + + + + + + + + + + Index: settings.gradle =================================================================== diff -u -r36049 -r37391 --- settings.gradle (.../settings.gradle) (revision 36049) +++ settings.gradle (.../settings.gradle) (revision 37391) @@ -6,4 +6,4 @@ "ssts-returngoods", "ssts-satisfactionsurvey", "ssts-receiverecord", "ssts-datasync-default-impl","ssts-datasync-settlement-gyey-impl","ssts-client-misc","ssts-cszxyy-misc","ssts-zd5y-misc","ssts-gdsy-misc", "ssts-toussereturndisinfect","ssts-datasync-szszyy-impl","ssts-datasync-jysrmyy-impl", -"ssts-schedule","ssts-recallrecord" \ No newline at end of file +"ssts-schedule","ssts-recallrecord","ssts-storagelocation" \ No newline at end of file Index: ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/warehouse/action/StorageLocationAction.java =================================================================== diff -u -r36801 -r37391 --- ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/warehouse/action/StorageLocationAction.java (.../StorageLocationAction.java) (revision 36801) +++ ssts-basedata/src/main/java/com/forgon/disinfectsystem/basedatamanager/warehouse/action/StorageLocationAction.java (.../StorageLocationAction.java) (revision 37391) @@ -422,6 +422,32 @@ StrutsResponseUtils.output(result); } + /** + * 加载科室或者仓库或者库位下的第一个可放入物品的库位(叶子节点) + */ + public void loadFirstStorageLocation(){ + JSONObject result = JSONUtil.buildJsonObject(true); + try { + String objId = StrutsParamUtils.getPraramValue("objId", ""); + String type = StrutsParamUtils.getPraramValue("type", ""); + StorageLocation storageLocation = storageLocationManager.loadFirstStorageLocation(objId, type); + if(storageLocation != null){ + JSONObject json = new JSONObject(); + json.put("id", storageLocation.getId()); + json.put("name", storageLocation.getName()); + json.put("barcode", storageLocation.getBarcode()); + json.put("storageLocationCode", storageLocation.getStorageLocationCode()); + json.put("orgUnitCode", storageLocation.getOrgUnitCode()); + json.put("orgUnitName", storageLocation.getOrgUnitName()); + result = JSONUtil.buildJsonObject(true, json); + } + } catch (Exception e) { + e.printStackTrace(); + result = JSONUtil.buildJsonObject(false, e.getMessage()); + } + StrutsResponseUtils.output(result); + } + @Override public void prepare() throws Exception { String id = StrutsParamUtils.getPraramValue("id", null); Index: ssts-returngoods/src/main/java/com/forgon/disinfectsystem/returngoodsrecord/service/ReturnGoodsRecordManagerImpl.java =================================================================== diff -u -r37382 -r37391 --- ssts-returngoods/src/main/java/com/forgon/disinfectsystem/returngoodsrecord/service/ReturnGoodsRecordManagerImpl.java (.../ReturnGoodsRecordManagerImpl.java) (revision 37382) +++ ssts-returngoods/src/main/java/com/forgon/disinfectsystem/returngoodsrecord/service/ReturnGoodsRecordManagerImpl.java (.../ReturnGoodsRecordManagerImpl.java) (revision 37391) @@ -13,6 +13,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.Map.Entry; import java.util.stream.Collectors; import net.sf.json.JSONArray; @@ -26,6 +27,7 @@ import com.forgon.Constants; import com.forgon.directory.acegi.tools.AcegiHelper; import com.forgon.directory.model.OrgUnit; +import com.forgon.directory.service.OrgUnitManager; import com.forgon.disinfectsystem.basedatamanager.goodsstock.service.GoodsStockManager; import com.forgon.disinfectsystem.basedatamanager.supplyroomconfig.service.SupplyRoomConfigManager; import com.forgon.disinfectsystem.basedatamanager.supplyroomconfig.service.SupplyRoomConfigUtils; @@ -48,6 +50,7 @@ import com.forgon.disinfectsystem.entity.basedatamanager.supplyroomconfig.SupplyRoomConfig; import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseDefinition; import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseInstance; +import com.forgon.disinfectsystem.entity.basedatamanager.warehouse.StorageLocation; import com.forgon.disinfectsystem.entity.basedatamanager.warehouse.StorageRecord; import com.forgon.disinfectsystem.entity.basedatamanager.warehouse.WareHouse; import com.forgon.disinfectsystem.entity.goodsstock.GoodsStock; @@ -138,7 +141,13 @@ private InvoicePlanManager invoicePlanManager; private StorageRecordManager storageRecordManager; + + private OrgUnitManager orgUnitManager; + public void setOrgUnitManager(OrgUnitManager orgUnitManager) { + this.orgUnitManager = orgUnitManager; + } + public void setStorageRecordManager(StorageRecordManager storageRecordManager) { this.storageRecordManager = storageRecordManager; } @@ -1015,8 +1024,10 @@ returnGoodsRecord.setSettleAccountsDepartCoding(settleAccountsDepartCoding); } - //设置退货记录的处理科室编码为当前用户所属科室编码 - returnGoodsRecord.setHandleDepartCode(AcegiHelper.getLoginUser().getCurrentOrgUnitCode()); + if(StringUtils.isBlank(returnGoodsRecord.getHandleDepartCode())){ + //设置退货记录的处理科室编码为当前用户所属科室编码 + returnGoodsRecord.setHandleDepartCode(AcegiHelper.getLoginUser().getCurrentOrgUnitCode()); + } // 先保存一次,若重装,装配任务需记下退货记录Id saveOrUpdate(returnGoodsRecord); //判断聚合包包内器械包是否同时退货,聚合包只能扫包外标签退货,因此应该保证聚合包包内器械包同时退货 @@ -1626,8 +1637,17 @@ recyclingApplication.setReaders(";ORGUNIT_" + recyclingApplication.getDepartCoding() + ";"); recyclingApplication.setSubmitTime(returnGoodsRecord.getReturnTime()); - recyclingApplication.setHandleDepartCoding(AcegiHelper.getCurrentOrgUnitCode()); - recyclingApplication.setHandleDepart(AcegiHelper.getCurrentOrgUnitName()); + if(StringUtils.isNotBlank(returnGoodsRecord.getHandleDepartCode())){ + OrgUnit orgUnit = orgUnitManager.getByCode(returnGoodsRecord.getHandleDepartCode()); + if(orgUnit == null){ + throw new RuntimeException(String.format("不存在科室编码为%s的科室", returnGoodsRecord.getHandleDepartCode())); + } + recyclingApplication.setHandleDepartCoding(orgUnit.getOrgUnitCoding()); + recyclingApplication.setHandleDepart(orgUnit.getName()); + }else{ + recyclingApplication.setHandleDepartCoding(AcegiHelper.getCurrentOrgUnitCode()); + recyclingApplication.setHandleDepart(AcegiHelper.getCurrentOrgUnitName()); + } recyclingApplication.setDisposablePriceFluctuation(disposableGoodsFluctuation); recyclingApplicationManager.saveOrUpdate(recyclingApplication); returnGoodsRecord.setRecyclingApplication(recyclingApplication); @@ -2505,4 +2525,373 @@ showName = "[" + showName + "]"; return showName; } + + /** + * 临床科室把已发货的器械包返放入库位后,触发自动退货到供应室的操作 + * @param tousseInstances + * @param storageLocation + */ + @Override + public void autoReturnTousseInstanceAfterPutInStorage(String currentOrgUnitCode, List tousseInstances, + StorageLocation storageLocation) { + boolean enableOperationReservationShippedToTraysOfKardexContainer = + ConfigUtils.getSystemSetConfigByNameBool("enableOperationReservationShippedToTraysOfKardexContainer"); + if(!enableOperationReservationShippedToTraysOfKardexContainer){ + return; + } + //extendedFunctionalityOfGoodsDepartShareConfig配置了字段“warehousePosition” + if(!ConfigUtils.extendedFunctionConfig("extendedFunctionalityOfGoodsDepartShareConfig", "warehousePosition")){ + return; + } + + if(CollectionUtils.isEmpty(tousseInstances) || storageLocation == null || StringUtils.isBlank(currentOrgUnitCode)){ + return; + } + Set invoiceIdSet = new HashSet(); + Set orgUnitCodeSet = new HashSet(); + //处理科室编码->申请科室编码->器械包实例的map,不同处理科室生产的包,要分开退货;不同申请科室的包,也要分开退货 + Map>> supplyRoomLocationDepartTousseInstanceMap = new HashMap>>(); + for (TousseInstance tousseInstance : tousseInstances) { + + //非已发货的器械包实例,不需要退货 + if(!tousseInstance.isShipped()){ + continue; + } + //生产部门 + String orgUnitCoding = tousseInstance.getOrgUnitCoding(); + if(StringUtils.isBlank(orgUnitCoding)){ + continue; + } + + //生产部门(供应室)把包实例放入库位时,不需要退货 + if(StringUtils.equals(orgUnitCoding, currentOrgUnitCode)){ + continue; + } + + //当前登录科室把已发货的器械包放入当前登录科室的库位 + if(StringUtils.equals(storageLocation.getOrgUnitCode(), currentOrgUnitCode)){ + + Map> departTousseInstanceMap = supplyRoomLocationDepartTousseInstanceMap.get(orgUnitCoding); + if(departTousseInstanceMap == null){ + departTousseInstanceMap = new HashMap>(); + } + + String location = tousseInstance.getFinalLocation(); + List list = departTousseInstanceMap.get(location); + if(list == null){ + list = new ArrayList(); + } + list.add(tousseInstance); + departTousseInstanceMap.put(location, list); + + supplyRoomLocationDepartTousseInstanceMap.put(orgUnitCoding, departTousseInstanceMap); + + orgUnitCodeSet.add(orgUnitCoding); + orgUnitCodeSet.add(location); + + invoiceIdSet.add(tousseInstance.getInvoice2_id() != null ? tousseInstance.getInvoice2_id() : tousseInstance.getInvoice_id()); + } + } + + if(MapUtils.isEmpty(supplyRoomLocationDepartTousseInstanceMap)){ + return; + } + + //结算科室自动取值退货物品包实例对应的发货单对应的申请单中的结算科室; + //如果退货时扫描的包实例的发货单没有对应的申请单,则退货时的结算科室取值发货单上的结算科室;(存在自定义发货的物品没有对应的申请单) + Map> invoiceIdSettleAccountsDepartMap = loadInvoiceIdSettleAccountsDepartMap(invoiceIdSet); + //科室编码和名称的map + Map orgUnitCodeNameMap = orgUnitManager.getOrgUnitCodeAndNameMapByOrgUnitCodes(orgUnitCodeSet); + + //退货时间 + Date returnTime = new Date(); + //操作人 + String operator = AcegiHelper.getLoginUserFullName(); + //退货人 + String returnOfPeople = operator; + //退货单类型为器械包 + String type = TousseDefinition.PACKAGE_TYPE_INSIDE; + String remark = "通过卡迪斯货柜存入触发自动退货"; + for (Entry>> entry : supplyRoomLocationDepartTousseInstanceMap.entrySet()) { + //供应室编码 + String supplyRoomOrgUnitCoding = entry.getKey(); + Map> departTousseInstanceMap = entry.getValue(); + for (Entry> departEntry : departTousseInstanceMap.entrySet()) { + //临床科室编码 + String departCode = departEntry.getKey(); + List list = departEntry.getValue(); + if(CollectionUtils.isEmpty(list)){ + continue; + } + + //消毒物品退货时,同一个祖先包定义的不同材料明细的包定义需要分开 + Map> materialMD5TousseInstanceMap = buildDisinfectGoodsMd5TousseInstanceMap(list); + + for (Entry> materialMD5Entry : materialMD5TousseInstanceMap.entrySet()) { + List tousseInstanceList = materialMD5Entry.getValue(); + ReturnGoodsRecord returnGoodsRecord = new ReturnGoodsRecord(); + returnGoodsRecord.setReturnTime(returnTime); + returnGoodsRecord.setHandleDepartCode(supplyRoomOrgUnitCoding); + returnGoodsRecord.setDepart(orgUnitCodeNameMap.get(departCode)); + returnGoodsRecord.setDepartCoding(departCode); + returnGoodsRecord.setType(type); + returnGoodsRecord.setOperator(operator); + returnGoodsRecord.setReturnOfPeople(returnOfPeople); + String settleAccountsDepart = loadSettleAccountsDepart(tousseInstanceList, invoiceIdSettleAccountsDepartMap); + String settleAccountsDepartCoding = loadSettleAccountsDepartCoding(tousseInstanceList, invoiceIdSettleAccountsDepartMap); + if(StringUtils.isBlank(settleAccountsDepartCoding) || StringUtils.isBlank(settleAccountsDepart)){ + returnGoodsRecord.setSettleAccountsDepart(orgUnitCodeNameMap.get(departCode)); + returnGoodsRecord.setSettleAccountsDepartCoding(departCode); + }else{ + returnGoodsRecord.setSettleAccountsDepart(settleAccountsDepart); + returnGoodsRecord.setSettleAccountsDepartCoding(settleAccountsDepartCoding); + } + returnGoodsRecord.setRemark(remark); + + List newReturnTousseItems = buildReturnGoodsItem(tousseInstanceList, returnGoodsRecord); + if(CollectionUtils.isEmpty(newReturnTousseItems)){ + continue; + } + returnGoodsRecord.setReturnGoodsItems(newReturnTousseItems); + checkAndSaveForReturnTousse(returnGoodsRecord); + } + } + } + } + + /** + * 结算科室自动取值退货物品包实例对应的发货单对应的申请单中的结算科室; + * 如果退货时扫描的包实例的发货单没有对应的申请单,则退货时的结算科室取值发货单上的结算科室;(存在自定义发货的物品没有对应的申请单) + * @param invoiceIdSet + * @return + */ + private Map> loadInvoiceIdSettleAccountsDepartMap(Set invoiceIdSet) { + Map> invoiceIdSettleAccountsDepartMap = new HashMap>(); + if(CollectionUtils.isEmpty(invoiceIdSet)){ + return invoiceIdSettleAccountsDepartMap; + } + String sql = String.format("select i.id invoiceId, i.settleAccountsDepartCoding iSettleAccountsDepartCoding, i.settleAccountsDepart iSettleAccountsDepart" + + ", ip.settleAccountsDepartCoding ipSettleAccountsDepartCoding, ip.settleAccountsDepart ipSettleAccountsDepart " + + "from %s i " + + "left join %s ip on ip.id = i.invoicePlan_ID where %s ", + Invoice.class.getSimpleName(), + InvoicePlan.class.getSimpleName(), + SqlUtils.getNonStringFieldInLargeCollectionsPredicate("i.id", invoiceIdSet)); + ResultSet rs = null; + try { + rs = objectDao.executeSql(sql); + while(rs.next()){ + Long invoiceId = rs.getLong("invoiceId"); + String iSettleAccountsDepartCoding = rs.getString("iSettleAccountsDepartCoding"); + String iSettleAccountsDepart = rs.getString("iSettleAccountsDepart"); + String ipSettleAccountsDepartCoding = rs.getString("ipSettleAccountsDepartCoding"); + String ipSettleAccountsDepart = rs.getString("ipSettleAccountsDepart"); + Map settleAccountsDepartMap = new HashMap(); + if(StringUtils.isNotBlank(ipSettleAccountsDepartCoding)){ + settleAccountsDepartMap.put(ipSettleAccountsDepartCoding, ipSettleAccountsDepart); + invoiceIdSettleAccountsDepartMap.put(invoiceId, settleAccountsDepartMap); + }else{ + settleAccountsDepartMap.put(iSettleAccountsDepartCoding, iSettleAccountsDepart); + invoiceIdSettleAccountsDepartMap.put(invoiceId, settleAccountsDepartMap); + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + DatabaseUtil.closeResultSetAndStatement(rs); + } + + return invoiceIdSettleAccountsDepartMap; + } + + /** + * 根据包实例,构建退货单明细 + * @param tousseInstanceList + * @param returnGoodsRecord + * @return + */ + private List buildReturnGoodsItem(List tousseInstanceList, ReturnGoodsRecord returnGoodsRecord) { + List newReturnTousseItems = new ArrayList(); + if(CollectionUtils.isEmpty(tousseInstanceList)){ + return newReturnTousseItems; + } + for (TousseInstance ti : tousseInstanceList) { + TousseDefinition tousseDefinition = getAncestorTousseDefinitionOfReturnTousseInstance(ti); + if(tousseDefinition == null){ + continue; + } + ReturnGoodsItem returnTousseItem = getExistReturnGoodsItem(tousseDefinition, newReturnTousseItems); + if(returnTousseItem == null){ + returnTousseItem = new ReturnGoodsItem(); + returnTousseItem.setReturnGoodsRecord(returnGoodsRecord); + returnTousseItem.setAmount(0); + returnTousseItem.setTousseName(tousseDefinition.getName()); + returnTousseItem.setTousseDefinition(tousseDefinition); + returnTousseItem.setIsDelivery(Constants.STR_NO); + returnTousseItem.setIsPacking(Constants.STR_NO); + newReturnTousseItems.add(returnTousseItem); + } + returnTousseItem.getTousseInstanceList().add(ti); + returnTousseItem.setAmount(returnTousseItem.getAmount() + 1); + } + + //计算退货价格 + calculateReturnTousseItemPrice(returnGoodsRecord, newReturnTousseItems); + + return newReturnTousseItems; + } + + /** + * 计算退货价格 + * @param returnGoodsRecord + * @param newReturnTousseItems + */ + private void calculateReturnTousseItemPrice(ReturnGoodsRecord returnGoodsRecord, List newReturnTousseItems) { + if(CollectionUtils.isEmpty(newReturnTousseItems) || returnGoodsRecord == null){ + return; + } + BigDecimal settlementPriceOfRecord = new BigDecimal(0.00); + for (ReturnGoodsItem returnTousseItem : newReturnTousseItems) { + TousseDefinition tousseDefinition = returnTousseItem.getTousseDefinition(); + Double definitionPrice = tousseDefinition.getPrice(); + if(tousseDefinition.isDisinfection()){ + definitionPrice = TousseDefinitionUtils.getTousseDefinitionPrice(tousseDefinition); + } + returnTousseItem.setPrice(definitionPrice); + // 统计方式 + returnTousseItem.setMaterialAmount(tousseDefinition.getMaterialAmount()); + returnTousseItem.setMaterialAmountAtThatTime(tousseDefinition.getMaterialAmount()); + Double definitionFluctuationPrice = supplyRoomConfigManager.getTousseFluctuationPrice(definitionPrice); + returnTousseItem.setFluctuationPrice(definitionFluctuationPrice); + BigDecimal settlementFluctuationPrice = new BigDecimal(0.00); + BigDecimal settlementPrice = new BigDecimal(0.00); + + List tousseInstances = returnTousseItem.getTousseInstanceList(); + List disinfectGoodsMd5List = new ArrayList(); + //消毒物品不同的md5的数量 + tousseInstances.stream().forEach(ti -> { + TousseDefinition tdOfTi = ti.getTousseDefinition(); + if(tdOfTi.isDisinfection()){ + String md5 = tdOfTi.getMaterialsMD5(); + if(!disinfectGoodsMd5List.contains(md5)){ + disinfectGoodsMd5List.add(md5); + } + } + }); + if(disinfectGoodsMd5List.size() > 1){ + throw new SystemException(String.format("【%s】有多种不同的材料清单的包实例,每次只能录入一种材料清单的包进行退货", returnTousseItem.getTousseName())); + } + boolean reSetPrice = false; + // 有包实例时重新计算价格 + for (TousseInstance tousseInstance : tousseInstances) { + Double toussePrice = tousseInstance.getPrice(); + Double tousseFluctuationPrice = tousseInstance.getFluctuationPrice(); + + settlementPrice = settlementPrice.add(MathTools.mul(toussePrice, 1)); + settlementFluctuationPrice = settlementFluctuationPrice.add(MathTools.mul(tousseFluctuationPrice, 1)); + + if(!toussePrice.equals(definitionPrice) || !tousseFluctuationPrice.equals(definitionFluctuationPrice)){ + reSetPrice = true; + } + } + + returnTousseItem.setSettlementPrice(settlementFluctuationPrice); + settlementPriceOfRecord = settlementPriceOfRecord.add(settlementFluctuationPrice); + // 重新设置价格 + if(reSetPrice){ + double currentAmount = returnTousseItem.getAmount(); + returnTousseItem.setFluctuationPrice(settlementFluctuationPrice.doubleValue()/currentAmount ); + returnTousseItem.setPrice(settlementPrice.doubleValue()/currentAmount); + } + } + returnGoodsRecord.setSettlementPrice(settlementPriceOfRecord); + } + + /** + * 获取包实例的祖先包 + * @param ti + * @return + */ + private TousseDefinition getAncestorTousseDefinitionOfReturnTousseInstance( + TousseInstance ti) { + TousseDefinition td = ti.getTousseDefinition(); + if(td.isForeignOrSplitTousse()){ + return td; + } + List canReturnTousseTypes = new ArrayList(); + canReturnTousseTypes.add(TousseDefinition.PACKAGE_TYPE_INSIDE); + canReturnTousseTypes.add(TousseDefinition.PACKAGE_TYPE_DRESSING); + canReturnTousseTypes.add(TousseDefinition.PACKAGE_TYPE_DISINFECTION); + canReturnTousseTypes.add(TousseDefinition.PACKAGE_TYPE_FOREIGNPROXY); + canReturnTousseTypes.add(TousseDefinition.PACKAGE_TYPE_COMBO); + if(!canReturnTousseTypes.contains(td.getTousseType())){ + throw new SystemException(String.format("器械包退货暂不支持%s", td.getTousseType())); + } + Long ancestorID = td.getAncestorID(); + return tousseDefinitionManager.get(ancestorID); + } + + private ReturnGoodsItem getExistReturnGoodsItem(TousseDefinition td, List newReturnTousseItems) { + if(td == null || CollectionUtils.isEmpty(newReturnTousseItems)){ + return null; + } + for (ReturnGoodsItem returnGoodsItem : newReturnTousseItems) { + TousseDefinition returnTd = returnGoodsItem.getTousseDefinition(); + if(returnTd != null && td.getId().longValue() == returnTd.getId().longValue()){ + return returnGoodsItem; + } + } + return null; + } + + /** + * 消毒物品退货时,同一个祖先包定义的不同材料明细的包定义需要分开 + * @param tousseInstanceList + * @return + */ + private Map> buildDisinfectGoodsMd5TousseInstanceMap(List tousseInstanceList) { + Map> disinfectGoodsMd5TousseInstanceMap = new HashMap>(); + for (TousseInstance ti : tousseInstanceList) { + TousseDefinition td = ti.getTousseDefinition(); + String ancestorIDMd5 = ""; + if(td.isDisinfection()){ + ancestorIDMd5 = td.getAncestorID() + "_" + td.getMaterialsMD5(); + } + List tis = disinfectGoodsMd5TousseInstanceMap.get(ancestorIDMd5); + if(tis == null){ + tis = new ArrayList(); + } + tis.add(ti); + disinfectGoodsMd5TousseInstanceMap.put(ancestorIDMd5, tis); + } + return disinfectGoodsMd5TousseInstanceMap; + } + + private String loadSettleAccountsDepartCoding(List list, Map> invoiceIdSettleAccountsDepartMap) { + String settleAccountsDepartCoding = null; + for (TousseInstance ti : list) { + Long invoiceId = (ti.getInvoice2_id() != null ? ti.getInvoice2_id() : ti.getInvoice_id()); + Map settleAccountsDepartMap = invoiceIdSettleAccountsDepartMap.get(invoiceId); + if(settleAccountsDepartMap != null){ + for (String settleAccountsDepartKey: settleAccountsDepartMap.keySet()) { + settleAccountsDepartCoding = settleAccountsDepartKey; + } + } + } + return settleAccountsDepartCoding; + } + + private String loadSettleAccountsDepart(List list, Map> invoiceIdSettleAccountsDepartMap) { + String settleAccountsDepart = null; + for (TousseInstance ti : list) { + Long invoiceId = (ti.getInvoice2_id() != null ? ti.getInvoice2_id() : ti.getInvoice_id()); + Map settleAccountsDepartMap = invoiceIdSettleAccountsDepartMap.get(invoiceId); + if(settleAccountsDepartMap != null){ + for (String settleAccountsDepartValue: settleAccountsDepartMap.values()) { + settleAccountsDepart = settleAccountsDepartValue; + } + } + } + return settleAccountsDepart; + } } Index: build.gradle =================================================================== diff -u -r36088 -r37391 --- build.gradle (.../build.gradle) (revision 36088) +++ build.gradle (.../build.gradle) (revision 37391) @@ -736,6 +736,21 @@ } } +project("ssts-storagelocation") { + dependencies { + compile (project(":forgon-tools")) + compile (project(":forgon-core")) + compile (project(":ssts-basedata")) + compile (project(":ssts-diposablegoods")) + compile (project(":ssts-expensivegoods")) + compile (project(":ssts-datasync")) + compile (project(":ssts-stockmanage")) + compile (project(":ssts-tousse")) + compile (project(":ssts-invoice")) + compile (project(":ssts-returngoods")) + } +} + project("ssts-wash") { dependencies { compile (project(":forgon-tools")) @@ -1216,6 +1231,7 @@ compile (project(":ssts-qualitymon")) compile (project(":ssts-recallrecord")) + compile (project(":ssts-storagelocation")) } } @@ -1268,6 +1284,7 @@ compile (project(":ssts-datasync")) compile (project(":ssts-datasync-default-impl")) compile (project(":ssts-recallrecord")) + compile (project(":ssts-storagelocation")) compile group: 'org.seleniumhq.selenium', name: 'selenium-server', version: '3.141.59' Index: ssts-invoice/src/main/java/com/forgon/disinfectsystem/invoicemanager/service/InvoiceManagerImpl.java =================================================================== diff -u -r37177 -r37391 --- ssts-invoice/src/main/java/com/forgon/disinfectsystem/invoicemanager/service/InvoiceManagerImpl.java (.../InvoiceManagerImpl.java) (revision 37177) +++ ssts-invoice/src/main/java/com/forgon/disinfectsystem/invoicemanager/service/InvoiceManagerImpl.java (.../InvoiceManagerImpl.java) (revision 37391) @@ -90,6 +90,7 @@ import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseDefinition; import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseInstance; import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseInstanceAdditionalInfo; +import com.forgon.disinfectsystem.entity.basedatamanager.warehouse.StorageLocation; import com.forgon.disinfectsystem.entity.basedatamanager.warehouse.WareHouse; import com.forgon.disinfectsystem.entity.expensivegoods.ExpensiveGoodsModel; import com.forgon.disinfectsystem.entity.expensivegoods.ExpensiveGoodsModelStock; @@ -15189,5 +15190,114 @@ return JsonArray; } + + /** + * 当前登录科室把已灭菌、已消毒的器械包从当前登录科室的库位中取出时,需要由供应室自定义发货到当前登录科室 + * @param tousseInstances + * @param storageLocation + */ + @Override + public void autoInvoiceTousseInstanceAfterTakeOutStorage(String currentOrgUnitCode, List tousseInstances, + StorageLocation storageLocation) { + boolean enableOperationReservationShippedToTraysOfKardexContainer = + ConfigUtils.getSystemSetConfigByNameBool("enableOperationReservationShippedToTraysOfKardexContainer"); + if(!enableOperationReservationShippedToTraysOfKardexContainer){ + return; + } + //extendedFunctionalityOfGoodsDepartShareConfig配置了字段“warehousePosition” + if(!ConfigUtils.extendedFunctionConfig("extendedFunctionalityOfGoodsDepartShareConfig", "warehousePosition")){ + return; + } + + if(CollectionUtils.isEmpty(tousseInstances) || storageLocation == null || StringUtils.isBlank(currentOrgUnitCode)){ + return; + } + + Map> wareHouseTousseInstanceMap = new HashMap>(); + Map wareHouseMap = new HashMap(); + for (TousseInstance tousseInstance : tousseInstances) { + + if(!tousseInstance.isSteriled() && !tousseInstance.isDisinfected()){ + continue; + } + //生产部门 + String orgUnitCoding = tousseInstance.getOrgUnitCoding(); + if(StringUtils.isBlank(orgUnitCoding)){ + continue; + } + + //生产部门(供应室)从库位取出包实例时,不需要自定义发货 + if(StringUtils.equals(orgUnitCoding, currentOrgUnitCode)){ + continue; + } + //当前登录科室把已灭菌、已消毒的器械包从当前登录科室的库位中取出 + if(StringUtils.equals(storageLocation.getOrgUnitCode(), currentOrgUnitCode)){ + Long wareHouseId = tousseInstance.getWareHouseId(); + List list = wareHouseTousseInstanceMap.get(wareHouseId); + if(list == null){ + list = new ArrayList(); + } + list.add(tousseInstance); + wareHouseTousseInstanceMap.put(wareHouseId, list); + wareHouseMap.put(wareHouseId, tousseInstance.getWareHouseName()); + } + } + + if(MapUtils.isEmpty(wareHouseTousseInstanceMap)){ + return; + } + + String invoiceRemark = "通过卡迪斯货柜取出触发自动发货"; + for (Entry> entry : wareHouseTousseInstanceMap.entrySet()) { + Long wareHouseId = entry.getKey(); + List list = wareHouseTousseInstanceMap.get(wareHouseId); + JSONObject params = new JSONObject(); + + params.put("assistantSender", AcegiHelper.getLoginUserFullName()); + params.put("depart", storageLocation.getOrgUnitName()); + params.put("departCode", storageLocation.getOrgUnitCode()); + params.put("invoiceType", Invoice.TYPE_CUSTOM); + params.put("mode", "depart"); + params.put("sender", AcegiHelper.getLoginUserFullName()); + //供应室 + params.put("sourceWarehouseId", wareHouseId); + params.put("sourceWarehouseName", wareHouseMap.get(wareHouseId)); + params.put("invoiceRemark", invoiceRemark); + + JSONArray invoiceItems = new JSONArray(); + for (TousseInstance ti : list) { + JSONObject json = new JSONObject(); + json.put("barcode", ti.getBarcode()); + json.put("batchNumber", null); + json.put("count", 1); + json.put("diposable", Constants.STR_NO); + Double fluctuationPrice = ti.getFluctuationPrice(); + if(fluctuationPrice == null){ + fluctuationPrice = 0.0d; + } + json.put("fluctuationPrice", fluctuationPrice); + json.put("isRoutine", Constants.STR_YES); + json.put("isTracable", ti.getTousseDefinition().traceable()); + json.put("name", ti.getTousseName()); + Double price = ti.getPrice(); + if(price == null){ + price = 0.0d; + } + json.put("price", price); + json.put("sendAmount", 1); + json.put("showTousseName", ti.getTousseName()); + json.put("storage", 1); + json.put("tousseDefinitionId", ti.getTousseDefinition().getId()); + json.put("tousseFixedBarcode", null); + json.put("tousseType", ti.getTousseDefinition().getTousseType()); + invoiceItems.add(json); + } + + params.put("invoiceItems", invoiceItems); + + this.submitInvoice(params); + } + } + } \ No newline at end of file Index: ssts-storagelocation/src/test/resources/org/gradle/test-resource.xml =================================================================== diff -u --- ssts-storagelocation/src/test/resources/org/gradle/test-resource.xml (revision 0) +++ ssts-storagelocation/src/test/resources/org/gradle/test-resource.xml (revision 37391) @@ -0,0 +1 @@ + Index: forgon-tools/src/main/java/com/forgon/tools/util/ConfigUtils.java =================================================================== diff -u -r28928 -r37391 --- forgon-tools/src/main/java/com/forgon/tools/util/ConfigUtils.java (.../ConfigUtils.java) (revision 28928) +++ forgon-tools/src/main/java/com/forgon/tools/util/ConfigUtils.java (.../ConfigUtils.java) (revision 37391) @@ -20,6 +20,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.apache.commons.collections4.CollectionUtils; @@ -240,6 +241,32 @@ writeWebConfigInfo(configFilePath , key , value); return null; } + + /** + * 判断类似extendedFunctionalityOfGoodsDepartShareConfig:["warehousePosition"]此类配置项, + * 是否配置了某个子配置项 + * @param config + * @param moduleName + * @return + */ + public static boolean extendedFunctionConfig(String config, String subConfig){ + if(StringUtils.isBlank(config) || StringUtils.isBlank(subConfig)){ + return false; + } + boolean enableSubConfig = false; + String extendedFunctionConfigStr = getSystemSetConfigByName(config); + if(StringUtils.isNotBlank(extendedFunctionConfigStr)){ + JSONArray extendedFunctionConfigArray = JSONArray.fromObject(extendedFunctionConfigStr); + for (int i = 0; i < extendedFunctionConfigArray.size(); i++) { + String item = extendedFunctionConfigArray.getString(i); + if(subConfig.equals(item)){ + enableSubConfig = true; + break; + } + } + } + return enableSubConfig; + } /** * 根据key与value对config.js的进行设值(config.js由参数传入) Index: ssts-webservice/src/main/java/com/forgon/disinfectsystem/webservice/service/ServiceManagerImpl.java =================================================================== diff -u -r37355 -r37391 --- ssts-webservice/src/main/java/com/forgon/disinfectsystem/webservice/service/ServiceManagerImpl.java (.../ServiceManagerImpl.java) (revision 37355) +++ ssts-webservice/src/main/java/com/forgon/disinfectsystem/webservice/service/ServiceManagerImpl.java (.../ServiceManagerImpl.java) (revision 37391) @@ -74,6 +74,7 @@ import com.forgon.disinfectsystem.basedatamanager.position.service.PositionManager; import com.forgon.disinfectsystem.basedatamanager.specialInfection.service.SpecialInfectionManager; import com.forgon.disinfectsystem.basedatamanager.sterilisation.service.SterilisationManager; +import com.forgon.disinfectsystem.basedatamanager.storagelocation.goodsaccess.service.StorageLocationGoodsAccessManager; import com.forgon.disinfectsystem.basedatamanager.supplier.service.SupplierManager; import com.forgon.disinfectsystem.basedatamanager.supplyroomconfig.service.SupplyRoomConfigManager; import com.forgon.disinfectsystem.basedatamanager.taskGroup.service.TaskGroupManager; @@ -456,6 +457,9 @@ this.borrowRecordManager = borrowRecordManager; } private InitDbConnection dbConnection; + + @Autowired + private StorageLocationGoodsAccessManager storageLocationGoodsAccessManager; public void setDbConnection(InitDbConnection dbConnection) { this.dbConnection = dbConnection; @@ -7625,7 +7629,7 @@ //调用物品存取的方法 String result = JSONUtil.buildJsonObject(true).toString(); try { - result = tousseInstanceManager.scanBarcodeAndAddTousseToStorage(barcode, storageLocationBarcode, status); + result = storageLocationGoodsAccessManager.scanBarcodeAndAddTousseToStorage(barcode, storageLocationBarcode, status); } catch (Exception e) { e.printStackTrace(); result = JSONUtil.buildJsonObject(false, e.getMessage()).toString(); Index: ssts-tousse/src/main/java/com/forgon/disinfectsystem/tousse/toussedefinition/service/TousseInstanceManager.java =================================================================== diff -u -r36901 -r37391 --- ssts-tousse/src/main/java/com/forgon/disinfectsystem/tousse/toussedefinition/service/TousseInstanceManager.java (.../TousseInstanceManager.java) (revision 36901) +++ ssts-tousse/src/main/java/com/forgon/disinfectsystem/tousse/toussedefinition/service/TousseInstanceManager.java (.../TousseInstanceManager.java) (revision 37391) @@ -12,9 +12,11 @@ import org.apache.commons.collections4.Predicate; +import com.forgon.directory.model.OrgUnit; import com.forgon.disinfectsystem.entity.basedatamanager.taskGroup.TaskGroup; import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseDefinition; import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseInstance; +import com.forgon.disinfectsystem.entity.basedatamanager.warehouse.StorageLocation; import com.forgon.disinfectsystem.entity.basedatamanager.warehouse.WareHouse; import com.forgon.disinfectsystem.entity.invoicemanager.Invoice; import com.forgon.disinfectsystem.entity.invoicemanager.InvoicePlan; @@ -1315,5 +1317,30 @@ * @param tousseInstanceVoList */ public void receiveJLKShippingInfo(List tousseInstanceVoList); + + /** + * 器械包实例批量放入库位 + * @param allInvoiceTousseInstance + * @param storageLocationId + */ + public void batchPutTousseInstanceIntoStorageLoaction(List tousseInstances, + StorageLocation storageLocation, String orgUnitCode, String operateDetail); + + /** + * 检查当前库位是否可以使用 + * @param currentOrgUnitCode + * @param storageLocation + * @return + */ + public boolean valideStorageLocation(String currentOrgUnitCode, StorageLocation storageLocation); + + /** + * 判断包实例是否可以放入库位 + * @param allTousseInstances 器械包实例 + * @param storageLocation 库位 + * @param orgUnit 当前登录科室 + */ + public void canTousseInstancePutIntoStorageLocation(List allTousseInstances, StorageLocation storageLocation, OrgUnit orgUnit); + } Index: ssts-storagelocation/.project =================================================================== diff -u --- ssts-storagelocation/.project (revision 0) +++ ssts-storagelocation/.project (revision 37391) @@ -0,0 +1,30 @@ + + + ssts-storagelocation + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + org.zeroturnaround.eclipse.rebelXmlBuilder + + + + + + org.springsource.ide.eclipse.gradle.core.nature + org.eclipse.jdt.core.javanature + org.zeroturnaround.eclipse.jrebelNature + org.eclipse.buildship.core.gradleprojectnature + + Index: ssts-storagelocation/src/main/java/com/forgon/disinfectsystem/basedatamanager/storagelocation/goodsaccess/service/StorageLocationGoodsAccessManagerImpl.java =================================================================== diff -u --- ssts-storagelocation/src/main/java/com/forgon/disinfectsystem/basedatamanager/storagelocation/goodsaccess/service/StorageLocationGoodsAccessManagerImpl.java (revision 0) +++ ssts-storagelocation/src/main/java/com/forgon/disinfectsystem/basedatamanager/storagelocation/goodsaccess/service/StorageLocationGoodsAccessManagerImpl.java (revision 37391) @@ -0,0 +1,352 @@ +package com.forgon.disinfectsystem.basedatamanager.storagelocation.goodsaccess.service; + +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.sf.json.JSONObject; +import net.sf.json.JsonConfig; + +import org.apache.commons.collections.MapUtils; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; + +import com.forgon.directory.acegi.tools.AcegiHelper; +import com.forgon.directory.model.BarcodeDevice; +import com.forgon.directory.model.OrgUnit; +import com.forgon.directory.service.OrgUnitManager; +import com.forgon.disinfectsystem.barcode.service.BarcodeManager; +import com.forgon.disinfectsystem.basedatamanager.warehouse.service.StorageLocationManager; +import com.forgon.disinfectsystem.basedatamanager.warehouse.service.StorageRecordManager; +import com.forgon.disinfectsystem.entity.assestmanagement.DisposableGoodsBatchStock; +import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseInstance; +import com.forgon.disinfectsystem.entity.basedatamanager.warehouse.StorageLocation; +import com.forgon.disinfectsystem.entity.basedatamanager.warehouse.StorageRecord; +import com.forgon.disinfectsystem.entity.basedatamanager.warehouse.Storage_TousseInstance; +import com.forgon.disinfectsystem.invoicemanager.service.InvoiceManager; +import com.forgon.disinfectsystem.returngoodsrecord.service.ReturnGoodsRecordManager; +import com.forgon.disinfectsystem.tousse.toussedefinition.service.TousseInstanceManager; +import com.forgon.exception.SystemException; +import com.forgon.tools.db.DatabaseUtil; +import com.forgon.tools.hibernate.ObjectDao; +import com.forgon.tools.json.JSONUtil; +import com.forgon.tools.json.JsonPropertyFilter; +import com.forgon.tools.string.StringTools; +import com.forgon.tools.util.SqlUtils; + +public class StorageLocationGoodsAccessManagerImpl implements StorageLocationGoodsAccessManager { + + private BarcodeManager barcodeManager; + + private StorageLocationManager storageLocationManager; + + private StorageRecordManager storageRecordManager; + + private ObjectDao objectDao; + + private TousseInstanceManager tousseInstanceManager; + + private InvoiceManager invoiceManager; + + private ReturnGoodsRecordManager returnGoodsRecordManager; + + private OrgUnitManager orgUnitManager; + + public void setOrgUnitManager(OrgUnitManager orgUnitManager) { + this.orgUnitManager = orgUnitManager; + } + + public void setReturnGoodsRecordManager(ReturnGoodsRecordManager returnGoodsRecordManager) { + this.returnGoodsRecordManager = returnGoodsRecordManager; + } + + public void setBarcodeManager(BarcodeManager barcodeManager) { + this.barcodeManager = barcodeManager; + } + + public void setStorageLocationManager(StorageLocationManager storageLocationManager) { + this.storageLocationManager = storageLocationManager; + } + + public void setStorageRecordManager(StorageRecordManager storageRecordManager) { + this.storageRecordManager = storageRecordManager; + } + + public void setObjectDao(ObjectDao objectDao) { + this.objectDao = objectDao; + } + + public void setTousseInstanceManager(TousseInstanceManager tousseInstanceManager) { + this.tousseInstanceManager = tousseInstanceManager; + } + + public void setInvoiceManager(InvoiceManager invoiceManager) { + this.invoiceManager = invoiceManager; + } + + @Override + public String scanBarcodeAndAddTousseToStorage(String barcode, String storageBarcode, String status) { + JSONObject json = JSONUtil.buildJsonObject(false); + json.put("success", false); + if (StringUtils.isNotBlank(barcode)) { + // 库位/物品 + BarcodeDevice barcodeDevice = barcodeManager.getBarcodeByBarcode(barcode); + // 找不到条码对应的对象信息 + if (barcodeDevice == null) { + throw new SystemException(barcode + "为无效条码!"); + } + + String currentOrgUnitCode = AcegiHelper.getCurrentOrgUnitCode(); + if (barcodeDevice instanceof StorageLocation) { + // 扫描库位条码,返回库位信息 + StorageLocation storageLocation = (StorageLocation) barcodeDevice; + // 检查库位是否可以使用 + tousseInstanceManager.valideStorageLocation(currentOrgUnitCode, storageLocation); + // 上级库位 + String parentStorageLocationPath = storageLocationManager.getParentStorageLocationNameById(storageLocation.getId()); + // 扫描的库位信息 + JsonConfig config = new JsonConfig(); + config.setJsonPropertyFilter(new JsonPropertyFilter(new String[] {"tousseDefinitionList"})); + JSONObject data = JSONObject.fromObject(storageLocation, config); + data.put("parentStorageLocationPath", parentStorageLocationPath); + json.put("data", data); + json.put("returnType", "storageLocation"); + json.put("success", true); + return json.toString(); + } else if (barcodeDevice instanceof TousseInstance) { + // 扫描了器械包条码 + if (StringUtils.isEmpty(storageBarcode)) { + // 先扫描物品条码,提示错误信息 + throw new SystemException("请先扫描库位条码!"); + } else { + // 先扫描库位条码,再扫描物品条码,保存新的库存信息 + // 器械包实例 + TousseInstance ti = (TousseInstance) barcodeDevice; + // 库位 + StorageLocation storageLocation = (StorageLocation) barcodeManager.getBarcodeByBarcode(storageBarcode); + // 保存库存记录 + if (StorageRecord.IN.equals(status)) { + List tousseInstances = new ArrayList(); + tousseInstances.add(ti); + tousseInstanceManager.batchPutTousseInstanceIntoStorageLoaction(tousseInstances, storageLocation, currentOrgUnitCode, StorageRecord.OPERATE_DETAIL_IN_MANUAL); + //入库操作,系统自动补发一条退货记录操作 + returnGoodsRecordManager.autoReturnTousseInstanceAfterPutInStorage(currentOrgUnitCode, tousseInstances, storageLocation); + } else if (StorageRecord.OUT.equals(status)) { + // 查询是否存在存放该物品的库存记录 + int inStorageAmount = storageLocationManager.getInStorageAmountByTousseIdAndStorageLocationId(ti.getId(), storageLocation.getId()); + if(inStorageAmount <= 0){ + json.put("message", ti.getTousseDefinitionName() + "不在该库位或已取出!"); + json.put("returnType", "errorStatus"); + return json.toString(); + } + //存入或取出物品 + storageRecordManager.saveStorageRecord(ti, storageLocation, status, StorageRecord.OPERATE_DETAIL_OUT_MANUAL, null); + //出库操作 系统自动补发一条自定义发货记录操作; + List tousseInstances = new ArrayList(); + tousseInstances.add(ti); + invoiceManager.autoInvoiceTousseInstanceAfterTakeOutStorage(currentOrgUnitCode, tousseInstances, storageLocation); + } + JSONObject jsonObj = new JSONObject(); + jsonObj.put("tousseName", ti.getTousseName()); // 器械包名称 + jsonObj.put("validUntil", ti.getValidUntilStr()!=null ? ti.getValidUntilStr() : ""); // 失效时间 + jsonObj.put("barcode", ti.getBarcode()); // 条码 + jsonObj.put("storageName", storageLocation.getName()); // 库位名称 + json.put("data",jsonObj); + json.put("returnType", "storageRecord"); + json.put("success", true); + return json.toString(); + } + } else { + if (StringUtils.isEmpty(storageBarcode)) { + // 先扫描物品条码,提示错误信息 + json.put("message", "请先扫描库位条码!"); + return json.toString(); + } + // 根据批次号查找一次性物品,库位管理不支持一次性物品 + DisposableGoodsBatchStock disposableGoodsBatchStock = + (DisposableGoodsBatchStock) objectDao.getByProperty(DisposableGoodsBatchStock.class.getSimpleName(), "barcode", barcode); + if (disposableGoodsBatchStock != null) { + throw new SystemException(disposableGoodsBatchStock.getDiposableGoods().getName() + "属于一次性物品,库位管理不支持一次性物品!"); + } + // 扫描到非库位、非器械包条码 + json.put("message", barcode + "为无效条码!"); + return json.toString(); + } + } + return json.toString(); + } + + @Override + public JSONObject scanBarcode(String barcode, String storageBarcode, String status) { + + if(StringUtils.isBlank(barcode)){ + throw new SystemException("条码不能为空!"); + } + + JSONObject json = new JSONObject(); + // 库位/物品 + BarcodeDevice barcodeDevice = barcodeManager.getBarcodeByBarcode(barcode); + // 找不到条码对应的对象信息 + if (barcodeDevice == null) { + throw new SystemException(barcode + "为无效条码!"); + } + + String currentOrgUnitCode = AcegiHelper.getCurrentOrgUnitCode(); + // 扫描库位条码,返回库位信息 + if (barcodeDevice instanceof StorageLocation) { + StorageLocation storageLocation = (StorageLocation) barcodeDevice; + // 检查库位是否可以使用 + tousseInstanceManager.valideStorageLocation(currentOrgUnitCode, storageLocation); + // 上级库位 + String parentStorageLocationPath = storageLocationManager.getParentStorageLocationNameById(storageLocation.getId()); + // 扫描的库位信息 + JsonConfig config = new JsonConfig(); + config.setJsonPropertyFilter(new JsonPropertyFilter(new String[] {"tousseDefinitionList"})); + JSONObject data = JSONObject.fromObject(storageLocation, config); + data.put("parentStorageLocationPath", parentStorageLocationPath); + json.put("storageLocation", data); + json.put("returnType", "storageLocation"); + return json; + } + + // 扫描了器械包条码 + if (barcodeDevice instanceof TousseInstance) { + if (StringUtils.isEmpty(storageBarcode)) { + throw new SystemException("请先扫描库位条码!"); + } + if(StringUtils.isBlank(status) + || (!StringUtils.equals(StorageRecord.IN, status) + && !StringUtils.equals(StorageRecord.OUT, status))){ + throw new SystemException("参数异常!"); + } + + // 器械包实例 + TousseInstance ti = (TousseInstance) barcodeDevice; + // 库位 + StorageLocation storageLocation = (StorageLocation) barcodeManager.getBarcodeByBarcode(storageBarcode); + if (StorageRecord.IN.equals(status)) { + //判断器械包实例是否可以放入库位 + List tousseInstances = new ArrayList(); + tousseInstances.add(ti); + OrgUnit orgUnit = orgUnitManager.getByCode(currentOrgUnitCode); + tousseInstanceManager.canTousseInstancePutIntoStorageLocation(tousseInstances, storageLocation, orgUnit ); + } else if (StorageRecord.OUT.equals(status)) { + // 查询是否存在存放该物品的库存记录 + int inStorageAmount = storageLocationManager.getInStorageAmountByTousseIdAndStorageLocationId(ti.getId(), storageLocation.getId()); + if(inStorageAmount <= 0){ + throw new SystemException(ti.getTousseDefinitionName() + "【" + ti.getBarcode() + "】" + "不在该库位或已取出!"); + } + }else{ + throw new SystemException("参数异常!"); + } + JSONObject jsonObj = new JSONObject(); + jsonObj.put("id", ti.getId()); + jsonObj.put("tousseName", ti.getTousseName()); // 器械包名称 + jsonObj.put("validUntil", ti.getValidUntilStr()!=null ? ti.getValidUntilStr() : ""); // 失效时间 + jsonObj.put("barcode", ti.getBarcode()); // 条码 + jsonObj.put("storageName", storageLocation.getName()); // 库位名称 + json.put("tousseInstance",jsonObj); + json.put("returnType", "storageRecord"); + return json; + } + // 根据批次号查找一次性物品,库位管理不支持一次性物品 + DisposableGoodsBatchStock disposableGoodsBatchStock = + (DisposableGoodsBatchStock) objectDao.getByProperty(DisposableGoodsBatchStock.class.getSimpleName(), "barcode", barcode); + if (disposableGoodsBatchStock != null) { + throw new SystemException(disposableGoodsBatchStock.getDiposableGoods().getName() + "属于一次性物品,库位管理不支持一次性物品!"); + } + // 扫描到非库位、非器械包条码 + throw new SystemException(barcode + "为无效条码!"); + } + + @Override + public void storageLocationItemStorage(String tousseInstanceIds, Long storageLocationId) { + if(StringUtils.isBlank(tousseInstanceIds) || !DatabaseUtil.isPoIdValid(storageLocationId)){ + throw new SystemException("参数异常!"); + } + // 库位 + StorageLocation storageLocation = storageLocationManager.getStorageLocationById(storageLocationId+""); + if(storageLocation == null){ + throw new SystemException("参数异常!"); + } + // 需要入库的器械包实例 + List tousseInstances = tousseInstanceManager.getCollection(tousseInstanceIds, ";"); + if(CollectionUtils.isEmpty(tousseInstances)){ + throw new SystemException("参数异常!"); + } + String currentOrgUnitCode = AcegiHelper.getCurrentOrgUnitCode(); + tousseInstanceManager.batchPutTousseInstanceIntoStorageLoaction(tousseInstances, storageLocation, currentOrgUnitCode, StorageRecord.OPERATE_DETAIL_IN_MANUAL); + //入库操作,系统自动补发一条退货记录操作 + returnGoodsRecordManager.autoReturnTousseInstanceAfterPutInStorage(currentOrgUnitCode, tousseInstances, storageLocation); + } + + @Override + public void storageLocationItemRetrieval(String tousseInstanceIds, Long storageLocationId) { + if(StringUtils.isBlank(tousseInstanceIds) || !DatabaseUtil.isPoIdValid(storageLocationId)){ + throw new SystemException("参数异常!"); + } + // 库位 + StorageLocation storageLocation = storageLocationManager.getStorageLocationById(storageLocationId+""); + if(storageLocation == null){ + throw new SystemException("参数异常!"); + } + // 需要出库的器械包实例 + List tousseInstances = tousseInstanceManager.getCollection(tousseInstanceIds, ";"); + if(CollectionUtils.isEmpty(tousseInstances)){ + throw new SystemException("参数异常!"); + } + String currentOrgUnitCode = AcegiHelper.getCurrentOrgUnitCode(); + + // 查询是否存在存放该物品的库存记录 + Map tousseInstanceIdInStorageLocationIdMap = loadStorageTousseInstanceMap(tousseInstanceIds, storageLocation); + if(MapUtils.isEmpty(tousseInstanceIdInStorageLocationIdMap)){ + throw new SystemException("物品不在该库位或已取出!"); + } + for (TousseInstance tousseInstance : tousseInstances) { + Long tousseInstanceId = tousseInstance.getId(); + if(!tousseInstanceIdInStorageLocationIdMap.containsKey(tousseInstanceId)){ + throw new SystemException(tousseInstance.getTousseName() + "(" + tousseInstance.getBarcode() + ")" + "不在该库位或已取出!"); + } + } + //存入或取出物品 + storageRecordManager.batchSaveTousseInstanceOutStorageRecord(tousseInstances, StorageRecord.OPERATE_DETAIL_OUT_MANUAL, null); + //出库操作 系统自动补发一条自定义发货记录操作; + invoiceManager.autoInvoiceTousseInstanceAfterTakeOutStorage(currentOrgUnitCode, tousseInstances, storageLocation); + } + + /** + * 包实例id及所在库位ID的map + * @param tousseInstanceIds + * @param storageLocation + * @return + */ + private Map loadStorageTousseInstanceMap(String tousseInstanceIds, StorageLocation storageLocation) { + Map tousseInstanceIdInStorageLocationIdMap = new HashMap(); + if(StringUtils.isBlank(tousseInstanceIds) || storageLocation == null){ + return tousseInstanceIdInStorageLocationIdMap; + } + + String sql = String.format("select po.tousseInstanceId, po.storageLocationId from %s po where po.storageLocationId = %s and %s", + Storage_TousseInstance.class.getSimpleName(), + storageLocation.getId(), + SqlUtils.getNonStringFieldInLargeCollectionsPredicate("po.tousseInstanceId", StringTools.toCollectionIgnoreNullAndBlank(tousseInstanceIds, ";"))); + ResultSet rs = null; + try { + rs = objectDao.executeSql(sql); + while(rs.next()){ + Long tousseInstanceId = rs.getLong("tousseInstanceId"); + Long storageLocationId = rs.getLong("storageLocationId"); + tousseInstanceIdInStorageLocationIdMap.put(tousseInstanceId, storageLocationId); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + DatabaseUtil.closeResultSetAndStatement(rs); + } + + return tousseInstanceIdInStorageLocationIdMap; + } + +} Index: ssts-returngoods/src/main/java/com/forgon/disinfectsystem/returngoodsrecord/service/ReturnGoodsRecordManager.java =================================================================== diff -u -r31114 -r37391 --- ssts-returngoods/src/main/java/com/forgon/disinfectsystem/returngoodsrecord/service/ReturnGoodsRecordManager.java (.../ReturnGoodsRecordManager.java) (revision 31114) +++ ssts-returngoods/src/main/java/com/forgon/disinfectsystem/returngoodsrecord/service/ReturnGoodsRecordManager.java (.../ReturnGoodsRecordManager.java) (revision 37391) @@ -9,6 +9,8 @@ import net.sf.json.JSONArray; import net.sf.json.JSONObject; +import com.forgon.disinfectsystem.entity.basedatamanager.toussedefinition.TousseInstance; +import com.forgon.disinfectsystem.entity.basedatamanager.warehouse.StorageLocation; import com.forgon.disinfectsystem.entity.returngoodsrecord.ReturnGoodsItem; import com.forgon.disinfectsystem.entity.returngoodsrecord.ReturnGoodsRecord; import com.google.gson.JsonObject; @@ -70,4 +72,12 @@ * @return */ public JSONObject loadTousseInstanceInfo(String barcode, boolean isTousse); + + /** + * 临床科室把已发货的器械包返放入库位后,触发自动退货到供应室的操作 + * @param tousseInstances + * @param storageLocation + */ + public void autoReturnTousseInstanceAfterPutInStorage(String currentOrgUnitCode, List tousseInstances, + StorageLocation storageLocation); }