Explorar o código

[task-5919] 华创启德试剂耗材出库登记接口调整,后端不再保存出库主子表,只根据流程修改库存表的数量,预扣量和出库未使用量(其他环境原逻辑保留)

huangws hai 3 semanas
pai
achega
59c676763d

+ 13 - 2
ibps-provider-root/modules/provider-business/src/main/java/com/lc/ibps/components/reagent/api/ILingYongService.java

@@ -78,6 +78,17 @@ public interface ILingYongService {
 	 */
 	@RequestMapping(value = "/save", method = { RequestMethod.POST })
 	public APIResult<Void> save(
- 			@RequestBody(required = true) @Valid LingYongPo lingYongPo,
-			@RequestParam(required = false) String operate);
+ 			@RequestBody(required = true) @Valid LingYongPo lingYongPo);
+
+	/**
+	 *
+	 * 保存【试剂耗材领用主表】记录(带流程)
+	 *
+	 * @param
+	 * @return
+	 */
+	@RequestMapping(value = "/saveByFlow", method = { RequestMethod.POST })
+	public APIResult<Void> saveByFlow(
+			@RequestParam(required = true) String mainId,
+			@RequestParam(required = true) String operate);
 }

+ 33 - 95
ibps-provider-root/modules/provider-business/src/main/java/com/lc/ibps/components/reagent/provider/LingYongProvider.java

@@ -90,112 +90,43 @@ public class LingYongProvider extends GenericProvider implements ILingYongServic
 		return result;
 	}
 	
-	@ApiOperation(value = "保存", notes = "保存试剂耗材领用主表信息", 
+	@ApiOperation(value = "有流程的保存", notes = "脚本保存好主子表数据,接口只负责改预扣量",
 			extensions = {
 					@Extension(properties = {
 							@ExtensionProperty(name = "submitCtrl", value = StringPool.Y)
 					})
 			})
 	@Override
-	public APIResult<Void> save(
-			@ApiParam(name = "lingYongPo", value = "试剂耗材领用主表对象", required = true)
-			@RequestBody(required = true) LingYongPo lingYongPo,
+	public APIResult<Void> saveByFlow(
+			@RequestParam(required = true) String mainId,
 			@RequestParam(required = false) String operate) {
 		APIResult<Void> result = new APIResult<Void>();
 		// 默认操作类型,如果为空则视为正常领用开始
-		if (operate == null) {
-			operate = "not";
-		}
 		try {
-			logger.info(" com.lc.ibps.components.provider.LingYongProvider.save()--->lingYongPo: {}, operate: {}", lingYongPo.toString(), operate);
-			String sids = "";
-			// 判断是否为正常领用流程
-			boolean isNormalFlow = !"back".equalsIgnoreCase(operate) && !"end".equalsIgnoreCase(operate);
-			if (!lingYongPo.getLingYongDetailPoList().isEmpty()) {
-				if (isNormalFlow) {
-					// --- 原有逻辑开始 (正常领用) ---
-					sids = lingYongPo.getWeiZhiLingYong();
-					/**  把流水id转换为库存id */
-					ReagentConsumabConvertAndPadId(lingYongPo);
-					List<Map<String, Object>> records = new ArrayList<>(lingYongPo.getLingYongDetailPoList().size());
-					for (LingYongDetailPo bean : lingYongPo.getLingYongDetailPoList()) {
-						Map<String, Object> map = new HashMap<>();
-						String id = UniqueIdUtil.getId();
-						map.put("id_", id);
-						bean.setTaiZhangId(id);
-						map.put("ming_cheng_", StrUtil.str(bean.getShiJiMingCheng()));
-						map.put("pi_hao_", StrUtil.str(bean.getPiHao()));
-						map.put("bian_ma_", StrUtil.str(bean.getBianMa()));
-						map.put("inventory_id", StrUtil.str(bean.getInventoryId()));
-						map.put("shu_liang_", StrUtil.str(bean.getShuLiang()));
-						map.put("you_xiao_qi_", StrUtil.str(bean.getYouXiaoQi()));
-						records.add(map);
-					}
-					// 扣减库存 ("not", "领用")
-					inventoryService.handleOperation(operate, "领用", records);
-					// --- 原有逻辑结束 ---
-				} else {
-					// --- 新增逻辑: back 或 end (回退/归还) ---
-					// 不再新创建主子表数据,主表无需额外操作
-					// 子表获取库存id和数量,更新库存表
-
-					for (LingYongDetailPo bean : lingYongPo.getLingYongDetailPoList()) {
-						String kcId = bean.getInventoryId();
-						if (kcId == null || kcId.trim().isEmpty()) {
-							logger.warn("忽略一条没有库存ID的明细记录: {}", bean);
-							continue;
-						}
-						// 获取数量
-						String quantityStr = StrUtil.str(bean.getShuLiang());
-						List<Map<String, Object>> records2 = new ArrayList<>(lingYongPo.getLingYongDetailPoList().size());
-						for (LingYongDetailPo bean2 : lingYongPo.getLingYongDetailPoList()) {
-							Map<String, Object> map = new HashMap<>();
-							map.put("id_", StrUtil.str(bean.getId()));
-							map.put("ming_cheng_", StrUtil.str(bean.getShiJiMingCheng()));
-							map.put("pi_hao_", StrUtil.str(bean.getPiHao()));
-							map.put("bian_ma_", StrUtil.str(bean.getBianMa()));
-							map.put("inventory_id", StrUtil.str(bean.getInventoryId()));
-							map.put("shu_liang_", StrUtil.str(bean.getShuLiang()));
-							map.put("you_xiao_qi_", StrUtil.str(bean.getYouXiaoQi()));
-							records2.add(map);
-						}
-						// 调用库存服务查询
-						// 假设 queryInventoryById 返回 List<Inventory> 或类似对象
-						inventoryService.handleOperation(operate, "领用",records2);
-					}
-				}
+			logger.info(" com.lc.ibps.components.provider.LingYongProvider.saveByFlow()--->mainId: {}, operate: {}", mainId.toString(), operate.toString());
+			String retVal = inventoryService.handleFlowOperation(mainId, operate);
+			// 防御性编程:防止返回 null
+			if (retVal == null || retVal.trim().isEmpty()) {
+				result.setMessage("更新失败!服务返回为空");
+				return result;
 			}
-
-			// 只有在正常流程下才保存主表和级联子表数据
-			if (isNormalFlow) {
-				LingYong domain = lingYongRepository.newInstance(lingYongPo);
-				domain.saveCascade();
-
-				// 【新增逻辑】获取保存后回填的主表ID
-				// 假设 LingYongPo 类中有 getId() 方法,且 saveCascade() 执行后该值已被填充
-				String mainTableId = "";
-				if (lingYongPo.getId() != null) {
-					mainTableId = lingYongPo.getId().toString();
+			// 【优化点】使用 indexOf 查找分隔符,避免 split 的正则问题
+			int separatorIndex = retVal.indexOf('^');
+			if (separatorIndex > 0) {
+				String codePart = retVal.substring(0, separatorIndex).trim(); // 提取 ^ 前的部分并去空格
+				String msgPart = retVal.substring(separatorIndex + 1);        // 提取 ^ 后的部分
+				if ("1".equals(codePart)) {
+					result.setMessage("更新成功!");
+					// 如果需要,可以在这里设置 result.setCode(StateEnum.SUCCESS.getCode());
 				} else {
-					// 如果 ID 是字符串类型直接获取,或者需要其他处理方式,请根据实际情况调整
-					// 某些框架可能需要 domain.getId(),这里假设 po 对象已被更新
-					logger.warn("保存后未获取到主表ID,请检查实体类映射配置");
-				}
-
-				/** 新增 恒生医院试剂耗材出库hrp接入逻辑 */
-				ReagentConsumabOutputForHSYY(sids);
-
-				// 【修改】在成功消息中追加主表ID
-				if (!mainTableId.isEmpty()) {
-					result.setMessage("保存试剂耗材领用主表成功,主表ID:" + mainTableId);
-				} else {
-					result.setMessage("保存试剂耗材领用主表成功 (未获取到ID)");
+					// 拼接自定义错误消息
+					result.setMessage("更新失败!" + msgPart);
 				}
 			} else {
-				// 回退模式下的成功消息
-				result.setMessage("试剂耗材领用回退/结束处理成功");
+				// 如果没有找到 ^,说明返回格式不对,直接将整个返回值当作错误信息
+				logger.error("服务返回格式错误,未找到分隔符 '^': {}", retVal);
+				result.setMessage("更新失败!系统返回格式异常:" + retVal);
 			}
-
 		} catch (Exception e) {
 			result.setMessage("保存试剂耗材领用失败!" + StateEnum.ERROR.getText());
 			setExceptionResult(result, StateEnum.ERROR.getCode(), StateEnum.ERROR.getText(), e);
@@ -203,13 +134,20 @@ public class LingYongProvider extends GenericProvider implements ILingYongServic
 		return result;
 	}
 
-	public APIResult<Void> saveold(
+	@ApiOperation(value = "保存", notes = "保存试剂耗材领用主表信息",
+			extensions = {
+					@Extension(properties = {
+							@ExtensionProperty(name = "submitCtrl", value = StringPool.Y)
+					})
+			})
+	@Override
+	public APIResult<Void> save(
 			@ApiParam(name = "lingYongPo", value = "试剂耗材领用主表对象", required = true)  
-			@RequestBody(required = true) LingYongPo lingYongPo,
-			@RequestParam(required = false) String operate) {
+			@RequestBody(required = true) LingYongPo lingYongPo
+	) {
 		APIResult<Void> result = new APIResult<Void>();
 		try {
-			logger.info(" com.lc.ibps.components.provider.LingYongProvider.save()--->lingYongPo: {},operate: {}", lingYongPo.toString(), operate.toString());
+			logger.info(" com.lc.ibps.components.provider.LingYongProvider.save()--->lingYongPo: {}", lingYongPo.toString());
 			String sids = "";
 			if(!lingYongPo.getLingYongDetailPoList().isEmpty()){
 				sids = lingYongPo.getWeiZhiLingYong();

+ 166 - 16
ibps-provider-root/modules/provider-business/src/main/java/com/lc/ibps/components/reagent/service/InventoryService.java

@@ -3,6 +3,7 @@ package com.lc.ibps.components.reagent.service;
 import com.lc.ibps.base.core.util.BeanUtils;
 import com.lc.ibps.base.core.util.Collections;
 import com.lc.ibps.cloud.provider.GenericProvider;
+import com.lc.ibps.components.querybuilder.utils.CollectionUtils;
 import com.lc.ibps.components.reagent.domain.ReagentConsumablesInventory;
 import com.lc.ibps.components.reagent.domain.ReagentConsumablesTransaction;
 import com.lc.ibps.components.reagent.dto.InventoryDTO;
@@ -140,32 +141,163 @@ public class InventoryService extends GenericProvider {
         return retVal;
     }
 
-    public void handleBackOrEndOperation(String status, List<Map<String, Object>> records) throws Exception {
+    public String handleFlowOperation(String MainId, String operate) throws Exception {
+        List<Map<String, Object>> detailList = storeService.queryLingYongRecord(MainId);
+        if (CollectionUtils.isEmpty(detailList)) {
+            return "-1^未找到子表数据";
+        }
 
-        for(Map<String, Object> record : records){
-            record.put("status", status);
-            String name1 = StrUtil.str(record.get("ming_cheng_"));
-            String name2 = StrUtil.str(record.get("shi_ji_ming_cheng"));
-            String reagentName = !name1.isEmpty() ? name1 : !name2.isEmpty() ? name2 : "";
-            record.put("ming_cheng_", reagentName);
-            String kcId = StrUtil.str(record.get("inventory_id"));
-            String batchNum = StrUtil.str(record.get("pi_hao_"));
-            String reagentCode = StrUtil.str(record.get("bian_ma_"));
+        // 用于第二阶段更新的暂存列表 (并行列表)
+        List<String> updateIds = new ArrayList<>();
+        List<Integer> updateWithholds = new ArrayList<>();
+        List<Integer> updateQuantities = new ArrayList<>();
+        List<Boolean> isEndOps = new ArrayList<>();
+        //用于存储每条记录对应的 remainAmount
+        List<String> updateRemainAmounts = new ArrayList<>();
+
+        boolean checkFlag = true;
+        String errorMsg = "";
+
+        // 第一阶段:纯校验 & 数据准备
+        for (Map<String, Object> detail : detailList) {
+            // 1. 解析数量 (整数)
+            String shuLiangStr = StrUtil.str(detail.get("shu_liang_")).trim();
+            if (shuLiangStr == null || shuLiangStr.length() == 0) {
+                checkFlag = false;
+                errorMsg = "数量不能为空";
+                break;
+            }
+
+            int shuLiang;
+            try {
+                shuLiang = Integer.parseInt(shuLiangStr);
+            } catch (NumberFormatException e) {
+                checkFlag = false;
+                errorMsg = "数量格式错误:" + shuLiangStr;
+                break;
+            }
+            if (shuLiang <= 0) {
+                checkFlag = false;
+                errorMsg = "数量必须大于0";
+                break;
+            }
+
+            // 2. 查询库存
+            String inventoryId = StrUtil.str(detail.get("inventory_id"));
+            String batchNum = StrUtil.str(detail.get("pi_hao_"));
+            String reagentCode = StrUtil.str(detail.get("bian_ma_"));
+            String name = StrUtil.str(detail.get("shi_ji_ming_cheng"));
 
             List<Map<String, Object>> inventoryList;
-            if (BeanUtils.isNotEmpty(kcId)) {
-                inventoryList = storeService.queryInventoryById(kcId);
-            }else {
+            if (inventoryId != null && inventoryId.trim().length() > 0) {
+                inventoryList = storeService.queryInventoryById(inventoryId);
+            } else {
                 inventoryList = storeService.queryInventoryByPhAndCode(batchNum, reagentCode);
             }
-            if (inventoryList.size() == 1) {
-                handleSingleInventory(inventoryList.get(0), record);
+            if (CollectionUtils.isEmpty(inventoryList) || inventoryList.size() != 1) {
+                checkFlag = false;
+                errorMsg = "未找到唯一库存记录";
+                break;
+            }
+
+            Map<String, Object> invMap = inventoryList.get(0);
+            int quantity = parseInteger(invMap.get("quantity"));
+            int withhold = parseInteger(invMap.get("withhold"));
+            String rawRemain = StrUtil.str(invMap.get("wei_shi_yong_lian"));
+            String remainAmount;
+
+            // 手动判断空值:检查是否为 null 或者 去除空格后长度为0
+            if (rawRemain == null || rawRemain.trim().isEmpty()) {
+                // 情况1:为空时,直接赋值为当前库存数量 quantity
+                remainAmount = shuLiangStr;
             } else {
-                handleMultipleInventories(inventoryList, record);
+                // 情况2:不为空时,解析为整数,加上当前库存数量 quantity
+                try {
+                    // 去除首尾空格并转为整数
+                    int currentVal = Integer.parseInt(rawRemain.trim());
+                    int newVal = currentVal + Integer.parseInt(shuLiangStr);
+                    remainAmount = String.valueOf(newVal);
+                } catch (NumberFormatException e) {
+                    remainAmount = shuLiangStr;
+                }
+            }
+
+            String realId = StrUtil.str(invMap.get("id"));
+            if (realId == null || realId.trim().length() == 0) {
+                realId = inventoryId;
+            }
+            if (realId == null || realId.trim().length() == 0) {
+                checkFlag = false;
+                errorMsg = "无法获取有效的库存ID";
+                break;
+            }
+
+            int newWithhold = 0;
+            int newQuantity = quantity;
+            boolean isEnd = false;
+
+            // 3. 逻辑判断
+            if ("start".equals(operate)) {
+                if ((quantity - withhold) < shuLiang) {
+                    checkFlag = false;
+                    errorMsg = name + " 可用库存不足 (可用:" + (quantity - withhold) + ", 需:" + shuLiang + ")";
+                    break;
+                }
+                newWithhold = withhold + shuLiang;
+            } else if ("back".equals(operate)) {
+                if (withhold < shuLiang) {
+                    checkFlag = false;
+                    errorMsg = name + " 预扣数量不足 (预扣:" + withhold + ", 需:" + shuLiang + ")";
+                    break;
+                }
+                newWithhold = withhold - shuLiang;
+            } else if ("end".equals(operate)) {
+                if (quantity < shuLiang || withhold < shuLiang) {
+                    checkFlag = false;
+                    errorMsg = name + " 库存或预扣不足 (库存:" + quantity + ", 预扣:" + withhold + ", 需:" + shuLiang + ")";
+                    break;
+                }
+                newQuantity = quantity - shuLiang;
+                newWithhold = withhold - shuLiang;
+                isEnd = true;
+            } else {
+                checkFlag = false;
+                errorMsg = "未知操作类型:" + operate;
+                break;
             }
 
+            // 校验通过,存入列表
+            updateIds.add(realId);
+            updateWithholds.add(newWithhold);
+            updateQuantities.add(newQuantity);
+            isEndOps.add(isEnd);
+            //将当前记录的 remainAmount 存入列表,与上面其他列表保持索引一致
+            updateRemainAmounts.add(remainAmount);
+        }
+
+        // 校验失败直接返回,不执行更新
+        if (!checkFlag) {
+            return "-1^" + errorMsg;
         }
 
+        // =======================
+        // 第二阶段:纯更新
+        // =======================
+        for (int i = 0; i < updateIds.size(); i++) {
+            String id = updateIds.get(i);
+            int w = updateWithholds.get(i);
+            int q = updateQuantities.get(i);
+            // 获取对应的 remainAmount
+            String rAmount = updateRemainAmounts.get(i);
+
+            if (isEndOps.get(i)) {
+                //在 operate 为 "end" 时,传入 remainAmount
+                linYongService.updateWithholdAndInventory(id, q, w, rAmount);
+            } else {
+                linYongService.updateWithhold(id, w);
+            }
+        }
+        return "1^成功";
     }
 
     private void handleSingleInventory(Map<String, Object> inventory, Map<String, Object> record) throws Exception {
@@ -370,4 +502,22 @@ public class InventoryService extends GenericProvider {
         }
         return retVal;
     }
+
+    // 辅助方法:安全转 Integer
+    private int parseInteger(Object obj) {
+        if (obj == null) {
+            return 0;
+        }
+        String s = String.valueOf(obj).trim(); // 使用原生 String.valueOf
+        // 原生判断空
+        if (s == null || s.length() == 0) {
+            return 0;
+        }
+        try {
+            return Integer.parseInt(s);
+        } catch (NumberFormatException e) {
+            return 0;
+        }
+    }
+
 }

+ 5 - 0
ibps-provider-root/modules/provider-business/src/main/java/com/lc/ibps/components/reagent/service/LinYongService.java

@@ -41,6 +41,11 @@ public class LinYongService implements OperationService{
         commonDao.execute(String.format(sql,Math.max(quantity,0),Math.max(withhold,0),id));
     }
 
+    public void updateWithholdAndInventory(String id, long quantity,long withhold, String remainAmount) {
+        String sql = "update t_reagent_inventory set update_time_=now(), quantity=%s, withhold=%s, wei_shi_yong_lian=%s where id_='%s'";
+        commonDao.execute(String.format(sql,Math.max(quantity,0),Math.max(withhold,0),remainAmount, id));
+    }
+
     public void updateInventory(String id,long quantity){
         String sql = "update t_reagent_inventory set update_time_=now(),quantity=%s where id_='%s'";
         commonDao.execute(String.format(sql,Math.max(quantity,0),id));