From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master
---
jnpf-lims/jnpf-lims-controller/src/main/java/jnpf/limsController/LimsLiuyangController.java | 1173 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1,173 insertions(+), 0 deletions(-)
diff --git a/jnpf-lims/jnpf-lims-controller/src/main/java/jnpf/limsController/LimsLiuyangController.java b/jnpf-lims/jnpf-lims-controller/src/main/java/jnpf/limsController/LimsLiuyangController.java
new file mode 100644
index 0000000..54fc6ca
--- /dev/null
+++ b/jnpf-lims/jnpf-lims-controller/src/main/java/jnpf/limsController/LimsLiuyangController.java
@@ -0,0 +1,1173 @@
+package jnpf.limsController;
+
+import jnpf.audit.sdk.annotation.AuditLog;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jnpf.limsEntity.LimsLiuyangBiangengShenqingEntity;
+import jnpf.limsEntity.LimsLiuyangJihuaBiangengShenqingEntity;
+import jnpf.limsEntity.LimsLiuyangJihuaBiangengShenqingZixiangEntity;
+import jnpf.limsEntity.LimsLiuyangJihuaCalculateParam;
+import jnpf.limsEntity.LimsLiuyangJihuaCalculateResult;
+import jnpf.limsEntity.LimsLiuyangJihuaBiangengCalculateParam;
+import jnpf.limsEntity.LimsLiuyangJihuaEntity;
+import jnpf.limsEntity.LimsLiuyangJihuaZixiangEntity;
+import jnpf.limsEntity.LimsLiuyangJiluEntity;
+import jnpf.limsEntity.LiuyangStatus;
+import jnpf.limsEntity.LiuyangWendingxingZhouqiZixiangEntity;
+import jnpf.limsEntity.LimsQingyandanEntity;
+import jnpf.limsService.LiuyangWendingxingZhouqiZixiangService;
+import jnpf.limsService.LimsLiuyangJihuaService;
+import jnpf.limsService.LimsLiuyangJihuaZixiangService;
+import jnpf.limsService.LimsLiuyangBiangengShenqingService;
+import jnpf.limsService.LimsLiuyangJihuaBiangengShenqingService;
+import jnpf.limsService.LimsLiuyangJihuaBiangengShenqingZixiangService;
+import jnpf.limsService.LimsLiuyangJiluService;
+import jnpf.limsService.LimsQingyandanService;
+import jnpf.util.R;
+import jnpf.util.RandomUtil;
+import jnpf.util.UserProvider;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.sql.DataSource;
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Tag(name = "lims鐣欐牱鎺ュ彛", description = "鐣欐牱璁板綍娴佺▼鎿嶄綔")
+@RestController
+@RequestMapping("/lims/biz")
+public class LimsLiuyangController {
+
+ private static final String BIANGENG_ZIXIANG_TABLE = "lims_liuyang_jihua_biangeng_shenqing_zixiang";
+ private static final String LIUYANG_CHUKU_SHENQING_TABLE = "lims_liuyang_chuku_shenqing";
+ private static final String LIUYANG_CHUKU_SHENQING_ZIXIANG_TABLE = "lims_liuyang_chuku_shenqing_zixiang";
+ private static final String LIUYANG_CHUKU_TABLE = "lims_liuyang_chuku";
+ private static final String LIUYANG_XIAOHUI_SHENQING_TABLE = "lims_liuyang_xiaohui_shenqing";
+ private static final String LIUYANG_XIAOHUI_SHENQING_ZIXIANG_TABLE = "lims_liuyang_xiaohui_shenqing_zixiang";
+ private static final String BIZ_STATUS_DESTROYED = "destroyed";
+ private static final String BIZ_STATUS_DISABLED = "disabled";
+
+ private static final List<String> DEFAULT_BIANGENG_ZIXIANG_FIELDS = Arrays.asList(
+ "zhouqi",
+ "zhouqi_danwei",
+ "jihua_riqi",
+ "shifou_yiguancha",
+ "guancha_riqi",
+ "guancha_ren",
+ "guancha_shuliang",
+ "guancha_qingkuang",
+ "guancha_jieguo",
+ "beizhu"
+ );
+
+ @Autowired
+ private LimsLiuyangJiluService limsLiuyangJiluService;
+
+ @Autowired
+ private LimsQingyandanService limsQingyandanService;
+
+ @Autowired
+ private LiuyangWendingxingZhouqiZixiangService liuyangWendingxingZhouqiZixiangService;
+
+ @Autowired
+ private LimsLiuyangJihuaService limsLiuyangJihuaService;
+
+ @Autowired
+ private LimsLiuyangJihuaZixiangService limsLiuyangJihuaZixiangService;
+
+ @Autowired
+ private LimsLiuyangBiangengShenqingService limsLiuyangBiangengShenqingService;
+
+ @Autowired
+ private LimsLiuyangJihuaBiangengShenqingService limsLiuyangJihuaBiangengShenqingService;
+
+ @Autowired
+ private LimsLiuyangJihuaBiangengShenqingZixiangService limsLiuyangJihuaBiangengShenqingZixiangService;
+
+ @Autowired
+ private DataSource dataSource;
+
+ @Autowired
+ private JdbcTemplate jdbcTemplate;
+
+ /**
+ * 鐣欐牱鎿嶄綔锛�
+ * submit -> 寰呭鏍革紝骞舵妸璇烽獙鍗� liuyang_jilu_id 鍏宠仈鍒板綋鍓嶇暀鏍疯褰曪紱
+ * reject -> 宸查��鍥烇紝骞舵竻绌鸿楠屽崟 liuyang_jilu_id锛�
+ * accept -> 宸叉帴鏀讹紝骞跺悓姝ュ叆搴撴暟閲�/鍗曚綅涓虹暀鏍风幇瀛橀噺锛�
+ * delete -> 鎸� JNPF 琛ㄥ崟瑙勮寖杞垹闄ょ暀鏍疯褰曘��
+ */
+ @Transactional(rollbackFor = Exception.class)
+ @Operation(summary = "鐣欐牱鎿嶄綔锛堟彁浜�/鎷掔粷/鍚屾剰锛�")
+ @PostMapping("/liuyang/action")
+ @AuditLog(action = "LIUYANG_ACTION", label = "鐣欐牱鎿嶄綔", bizType = "LIUYANG",
+ bizCodeExpr = "#result.success ? (#params['id'] ?: 'LIUYANG_ACTION') : ''", targetTable = "lims_liuyang_jilu",
+ targetIdExpr = "#params['id']", extraExpr = "{'action': #params['action']}",
+ diff = true, entityClass = LimsLiuyangJiluEntity.class)
+ public R<String> liuyangAction(@RequestBody Map<String, String> params) {
+ String action = params.get("action");
+ String id = params.get("id");
+ String flowId = firstNotBlank(params.get("flow_id"), params.get("flowId"));
+ String taskId = firstNotBlank(params.get("task_id"), params.get("taskId"));
+ String bizSign = params.get("biz_sign");
+
+ if (action == null || action.isEmpty()) {
+ return R.error("缂哄皯 action");
+ }
+ if ((id == null || id.isEmpty()) && (flowId == null || flowId.isEmpty())) {
+ return R.error("缂哄皯 flow_id");
+ }
+
+ LimsLiuyangJiluEntity liuyangJilu = findLiuyangJilu(id, flowId, taskId);
+ if (liuyangJilu == null) {
+ return R.error("鐣欐牱璁板綍鏁版嵁涓嶅瓨鍦�");
+ }
+
+ switch (action) {
+ case "submit":
+ updateLiuyangStatus(liuyangJilu, LiuyangStatus.PENDING_AUDIT, bizSign);
+ updateQingyandanLiuyangJiluId(liuyangJilu, liuyangJilu.getId());
+ return R.success("鎻愪氦鎴愬姛");
+ case "reject":
+ updateLiuyangStatus(liuyangJilu, LiuyangStatus.REJECTED, bizSign);
+ updateQingyandanLiuyangJiluId(liuyangJilu, null);
+ return R.success("鎷掔粷鎴愬姛");
+ case "accept":
+ receiveLiuyangJilu(liuyangJilu, bizSign);
+ return R.success("鍚屾剰鎴愬姛");
+ case "delete":
+ softDeleteLiuyangJilu(liuyangJilu, bizSign);
+ updateQingyandanLiuyangJiluId(liuyangJilu, null);
+ return R.success("鍒犻櫎鎴愬姛");
+ default:
+ return R.error("涓嶆敮鎸佺殑鎿嶄綔: " + action);
+ }
+ }
+
+ /**
+ * 鐣欐牱閿�姣佹祦绋嬫搷浣滐細
+ * submit -> 閿�姣佸崟鍙峰洖鍐欏埌鐣欐牱璁板綍锛�
+ * reject -> 娓呯┖鐣欐牱璁板綍閿�姣佸崟鍙凤紱
+ * accept -> shifou_pizhun=yes 鏃剁疆涓哄凡閿�姣佸苟绂佺敤鍏宠仈瑙傚療璁″垝鍙婂瓙椤癸紝shifou_pizhun=no 鏃舵竻绌洪攢姣佸崟鍙枫��
+ */
+ @Transactional(rollbackFor = Exception.class)
+ @Operation(summary = "鐣欐牱閿�姣佹搷浣滐紙鎻愪氦/鎷掔粷/鍚屾剰锛�")
+ @PostMapping("/liuyang/xiaohui/action")
+ @AuditLog(action = "DESTROY_ACTION", label = "鐣欐牱閿�姣佹搷浣�", bizType = "LIUYANG",
+ bizCodeExpr = "#result.success ? (#params['id'] ?: 'LIUYANG_DESTROY') : ''", targetTable = "lims_liuyang_jilu",
+ targetIdExpr = "#params['id']", extraExpr = "{'action': #params['action']}",
+ diff = true, entityClass = LimsLiuyangJiluEntity.class)
+ public R<String> liuyangXiaohuiAction(@RequestBody Map<String, String> params) {
+ if (params == null) {
+ return R.error("璇锋眰鍙傛暟涓嶈兘涓虹┖");
+ }
+ String flowId = firstNotBlank(params.get("flow_id"), params.get("flowId"));
+ String taskId = firstNotBlank(params.get("task_id"), params.get("taskId"));
+ String action = params.get("action");
+ String shifouPizhun = firstNotBlank(params.get("shifou_pizhun"), params.get("shifouPizhun"));
+
+ if (isBlank(flowId)) {
+ return R.error("娴佺▼id(flow_id)涓嶈兘涓虹┖");
+ }
+ if (isBlank(taskId)) {
+ return R.error("娴佺▼浠诲姟id(task_id)涓嶈兘涓虹┖");
+ }
+ if (isBlank(action)) {
+ return R.error("缂哄皯 action");
+ }
+
+ Map<String, Object> shenqing = findLiuyangXiaohuiShenqing(flowId, taskId);
+ if (shenqing == null || shenqing.isEmpty()) {
+ return R.error("鐣欐牱閿�姣佺敵璇锋暟鎹笉瀛樺湪");
+ }
+ String shenqingId = getString(shenqing, "f_id");
+ String xiaohuiDanhao = getString(shenqing, "xiaohui_danhao");
+ List<String> liuyangJiluIds = listLiuyangXiaohuiJiluIds(shenqingId);
+ if (liuyangJiluIds.isEmpty()) {
+ return R.error("鐣欐牱閿�姣佺敵璇峰瓙椤逛笉鑳戒负绌�");
+ }
+
+ switch (action) {
+ case "submit":
+ if (isBlank(xiaohuiDanhao)) {
+ return R.error("閿�姣佸崟鍙蜂笉鑳戒负绌�");
+ }
+ updateLiuyangXiaohuiDanhao(liuyangJiluIds, xiaohuiDanhao);
+ return R.success("鎻愪氦鎴愬姛");
+ case "reject":
+ updateLiuyangXiaohuiDanhao(liuyangJiluIds, null);
+ return R.success("鎷掔粷鎴愬姛");
+ case "accept":
+ if ("yes".equals(shifouPizhun)) {
+ acceptLiuyangXiaohui(liuyangJiluIds);
+ return R.success("鍚屾剰鎴愬姛");
+ }
+ if ("no".equals(shifouPizhun)) {
+ updateLiuyangXiaohuiDanhao(liuyangJiluIds, null);
+ return R.success("鎷掔粷鎴愬姛");
+ }
+ return R.error("鏄惁鎵瑰噯(shifou_pizhun)涓嶈兘涓虹┖锛屼笖蹇呴』涓� yes 鎴� no");
+ default:
+ return R.error("涓嶆敮鎸佺殑鎿嶄綔: " + action);
+ }
+ }
+
+ /**
+ * 璁$畻鐣欐牱璁″垝瀛愰」鍛ㄦ湡鍒楄〃銆�
+ */
+ @Operation(summary = "璁$畻鐣欐牱璁″垝鍛ㄦ湡")
+ @PostMapping("/liuyang/jihua/calculate")
+ public R<List<LimsLiuyangJihuaCalculateResult>> calculateLiuyangJihua(@RequestBody LimsLiuyangJihuaCalculateParam param) {
+ if (param == null || isBlank(param.getLiuyangJiluId())) {
+ return R.error("鐣欐牱璁板綍涓婚敭涓嶈兘涓虹┖");
+ }
+ if (isBlank(param.getLiuyangZhouqiId())) {
+ return R.error("鐣欐牱鍛ㄦ湡涓婚敭涓嶈兘涓虹┖");
+ }
+
+ LimsLiuyangJiluEntity liuyangJilu = limsLiuyangJiluService.getById(param.getLiuyangJiluId());
+ if (liuyangJilu == null || Integer.valueOf(1).equals(liuyangJilu.getDeleteMark())) {
+ return R.error("鐣欐牱璁板綍鏁版嵁涓嶅瓨鍦�");
+ }
+ if (liuyangJilu.getShouyangRiqi() == null) {
+ return R.error("鐣欐牱璁板綍鏀舵牱鏃ユ湡涓嶈兘涓虹┖");
+ }
+
+ List<LiuyangWendingxingZhouqiZixiangEntity> zhouqiList = listWendingxingZhouqiZixiang(param.getLiuyangZhouqiId());
+ if (zhouqiList.isEmpty()) {
+ return R.error("绋冲畾鎬у懆鏈熷瓙椤逛笉鑳戒负绌�");
+ }
+
+ try {
+ List<LimsLiuyangJihuaCalculateResult> jihuaList = zhouqiList.stream()
+ .map(row -> buildJihuaZixiang(row, liuyangJilu.getShouyangRiqi()))
+ .collect(Collectors.toList());
+ return R.success("璁$畻鎴愬姛", jihuaList);
+ } catch (IllegalArgumentException e) {
+ return R.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 璁″垝鍙樻洿鏃讹紝鎸夋柊鐨勭暀鏍锋棩鏈熼噸鏂拌绠楁湭瑙傚療璁″垝锛屽苟淇濈暀宸茶瀵熺殑鍘熻鍒掋��
+ */
+ @Operation(summary = "璁$畻鐣欐牱璁″垝鍙樻洿瀛愰」")
+ @PostMapping("/liuyang/jihua/biangeng/calculate")
+ public R<List<Map<String, Object>>> calculateLiuyangJihuaBiangeng(@RequestBody LimsLiuyangJihuaBiangengCalculateParam param) {
+ if (param == null || isBlank(param.getLiuyangJihuaId())) {
+ return R.error("鐣欐牱瑙傚療璁″垝涓婚敭涓嶈兘涓虹┖");
+ }
+ if (isBlank(param.getLiuyangZhouqiId())) {
+ return R.error("鐣欐牱鍛ㄦ湡涓婚敭涓嶈兘涓虹┖");
+ }
+ if (param.getLiuyangRiqi() == null) {
+ return R.error("鐣欐牱鏃ユ湡涓嶈兘涓虹┖");
+ }
+
+ List<LiuyangWendingxingZhouqiZixiangEntity> zhouqiList = listWendingxingZhouqiZixiang(param.getLiuyangZhouqiId());
+ if (zhouqiList.isEmpty()) {
+ return R.error("绋冲畾鎬у懆鏈熷瓙椤逛笉鑳戒负绌�");
+ }
+
+ try {
+ List<String> responseFields = getBiangengZixiangBusinessFields();
+ List<Map<String, Object>> result = new ArrayList<>();
+
+ List<LimsLiuyangJihuaZixiangEntity> observedList = listObservedJihuaZixiang(param.getLiuyangJihuaId());
+ Set<String> observedZhouqiKeys = observedList.stream()
+ .map(row -> buildZhouqiKey(row.getZhouqi(), row.getZhouqiDanwei()))
+ .collect(Collectors.toSet());
+ observedList.stream()
+ .map(row -> buildBiangengRow(row, responseFields))
+ .forEach(result::add);
+
+ zhouqiList.stream()
+ .filter(row -> !observedZhouqiKeys.contains(buildZhouqiKey(row.getZhouqi(), row.getZhouqiDanwei())))
+ .map(row -> buildBiangengRow(row, param.getLiuyangRiqi(), responseFields))
+ .forEach(result::add);
+
+ return R.success("璁$畻鎴愬姛", result);
+ } catch (IllegalArgumentException e) {
+ return R.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 鎻愪氦鐣欐牱瑙傚療璁″垝锛氬惎鐢ㄨ鍒掞紝骞跺叧鑱斿洖鐣欐牱璁板綍銆�
+ */
+ @Transactional(rollbackFor = Exception.class)
+ @Operation(summary = "鎻愪氦鐣欐牱瑙傚療璁″垝")
+ @PostMapping("/liuyang/jihua/submit")
+ @AuditLog(action = "PLAN_SUBMIT", label = "鎻愪氦鐣欐牱瑙傚療璁″垝", bizType = "LIUYANG",
+ bizCodeExpr = "#result.success ? 'LIUYANG_PLAN' : ''", targetTable = "lims_liuyang_jihua",
+ targetIdExpr = "#formData['id'] ?: #formData['f_id']", diff = true,
+ entityClass = LimsLiuyangJihuaEntity.class)
+ public R<String> submitLiuyangJihua(@RequestBody Map<String, Object> formData) {
+ String jihuaId = getFormId(formData);
+ if (isBlank(jihuaId)) {
+ return R.error("鐣欐牱瑙傚療璁″垝涓婚敭涓嶈兘涓虹┖");
+ }
+
+ LimsLiuyangJihuaEntity jihua = limsLiuyangJihuaService.getById(jihuaId);
+ if (jihua == null || Integer.valueOf(1).equals(jihua.getDeleteMark())) {
+ return R.error("鐣欐牱瑙傚療璁″垝鏁版嵁涓嶅瓨鍦�");
+ }
+ if (isBlank(jihua.getLiuyangJiluId())) {
+ return R.error("鐣欐牱瑙傚療璁″垝鏈叧鑱旂暀鏍疯褰�");
+ }
+
+ LimsLiuyangJihuaEntity jihuaUpdate = new LimsLiuyangJihuaEntity();
+ jihuaUpdate.setId(jihua.getId());
+ jihuaUpdate.setBizStatus("enabled");
+ limsLiuyangJihuaService.updateById(jihuaUpdate);
+ jihua.setBizStatus("enabled");
+
+ syncJihuaInfoToZixiang(jihua);
+
+ LimsLiuyangJiluEntity jiluUpdate = new LimsLiuyangJiluEntity();
+ jiluUpdate.setId(jihua.getLiuyangJiluId());
+ jiluUpdate.setLiuyangJihuaId(jihua.getId());
+ limsLiuyangJiluService.updateById(jiluUpdate);
+
+ return R.success("鎻愪氦鎴愬姛");
+ }
+
+ /**
+ * 鐣欐牱瑙傚療璁″垝鍙樻洿锛氬皢鍙樻洿鐢宠鍚屾鍒板疄闄呯暀鏍疯瀵熻鍒掋��
+ */
+ @Transactional(rollbackFor = Exception.class)
+ @Operation(summary = "鐣欐牱瑙傚療璁″垝鍙樻洿")
+ @PostMapping("/liuyang/jihua/biangeng/action")
+ @AuditLog(action = "PLAN_CHANGE", label = "鐣欐牱瑙傚療璁″垝鍙樻洿", bizType = "LIUYANG",
+ bizCodeExpr = "#result.success ? (#params['id'] ?: 'LIUYANG_PLAN_CHANGE') : ''", targetTable = "lims_liuyang_jihua",
+ targetIdExpr = "T(jnpf.limsService.support.LimsAuditTargetIds).liuyangJihuaByChangeFlow(" +
+ "#params['flow_id'] ?: #params['flowId'], #params['task_id'] ?: #params['taskId'])",
+ extraExpr = "{'action': #params['action']}", diff = true,
+ entityClass = LimsLiuyangJihuaEntity.class)
+ public R<String> liuyangJihuaBiangengAction(@RequestBody Map<String, String> params) {
+ if (params == null) {
+ return R.error("璇锋眰鍙傛暟涓嶈兘涓虹┖");
+ }
+ String flowId = firstNotBlank(params.get("flow_id"), params.get("flowId"));
+ String taskId = firstNotBlank(params.get("task_id"), params.get("taskId"));
+
+ if (isBlank(flowId)) {
+ return R.error("娴佺▼id(flow_id)涓嶈兘涓虹┖");
+ }
+ if (isBlank(taskId)) {
+ return R.error("娴佺▼浠诲姟id(task_id)涓嶈兘涓虹┖");
+ }
+
+ LimsLiuyangJihuaBiangengShenqingEntity shenqing = findJihuaBiangengShenqing(flowId, taskId);
+ if (shenqing == null) {
+ return R.error("鐣欐牱瑙傚療璁″垝鍙樻洿鐢宠鏁版嵁涓嶅瓨鍦�");
+ }
+ if (isBlank(shenqing.getLiuyangJihuaId())) {
+ return R.error("鍙樻洿鐢宠鏈叧鑱旂暀鏍疯瀵熻鍒�");
+ }
+
+ LimsLiuyangJihuaEntity jihua = limsLiuyangJihuaService.getById(shenqing.getLiuyangJihuaId());
+ if (jihua == null || Integer.valueOf(1).equals(jihua.getDeleteMark())) {
+ return R.error("鐣欐牱瑙傚療璁″垝鏁版嵁涓嶅瓨鍦�");
+ }
+
+ updateJihuaByBiangeng(shenqing);
+ softDeleteUnobservedJihuaZixiang(shenqing.getLiuyangJihuaId());
+ syncBiangengZixiangToJihuaZixiang(jihua, shenqing);
+
+ return R.success("鍙樻洿鎴愬姛");
+ }
+
+ /**
+ * 鐣欐牱鏁伴噺鍙樻洿锛氬皢鍙樻洿鐢宠鐨勫叆搴撴暟閲�/鍗曚綅鍚屾鍒扮暀鏍疯褰曘��
+ * 浠呭綋鐣欐牱璁板綍鏈嚭搴擄紙鍏ュ簱鏁伴噺 == 鐣欐牱鐜板瓨閲忥級鏃跺厑璁稿彉鏇淬��
+ */
+ @Transactional(rollbackFor = Exception.class)
+ @Operation(summary = "鐣欐牱鏁伴噺鍙樻洿")
+ @PostMapping("/liuyang/biangeng/action")
+ @AuditLog(action = "QUANTITY_CHANGE", label = "鐣欐牱鏁伴噺鍙樻洿", bizType = "LIUYANG",
+ bizCodeExpr = "#result.success ? #params['liuyang_jilu_id'] : ''",
+ targetTable = "lims_liuyang_jilu", targetIdExpr = "#params['liuyang_jilu_id']",
+ diff = true, entityClass = LimsLiuyangJiluEntity.class)
+ public R<String> liuyangBiangengAction(@RequestBody Map<String, String> params) {
+ String liuyangJiluId = params.get("liuyang_jilu_id");
+ String biangengShenqingId = params.get("biangeng_shenqing_id");
+
+ if (isBlank(liuyangJiluId)) {
+ return R.error("鐣欐牱璁板綍涓婚敭涓嶈兘涓虹┖");
+ }
+ if (isBlank(biangengShenqingId)) {
+ return R.error("鍙樻洿鐢宠涓婚敭涓嶈兘涓虹┖");
+ }
+
+ LimsLiuyangJiluEntity jilu = findById(liuyangJiluId);
+ if (jilu == null) {
+ return R.error("鐣欐牱璁板綍鏁版嵁涓嶅瓨鍦�");
+ }
+
+ LimsLiuyangBiangengShenqingEntity shenqing = findBiangengShenqing(biangengShenqingId);
+ if (shenqing == null) {
+ return R.error("鍙樻洿鐢宠鏁版嵁涓嶅瓨鍦�");
+ }
+
+ if (!equalsNullable(jilu.getRukuShuliang(), jilu.getLiuyangXiancunliang())) {
+ return R.error("璇ョ暀鏍锋牱鍝佸凡鍑哄簱锛屾棤娉曞彉鏇存暟閲�");
+ }
+
+ LimsLiuyangJiluEntity jiluUpdate = new LimsLiuyangJiluEntity();
+ jiluUpdate.setId(jilu.getId());
+ jiluUpdate.setRukuShuliang(shenqing.getRukuShuliang());
+ jiluUpdate.setLiuyangXiancunliang(shenqing.getRukuShuliang());
+ jiluUpdate.setDanwei(shenqing.getDanwei());
+ jiluUpdate.setLiuyangXiancunliangDanwei(shenqing.getDanwei());
+ limsLiuyangJiluService.updateById(jiluUpdate);
+
+ syncBiangengToJihua(liuyangJiluId, shenqing);
+
+ return R.success("鍙樻洿鎴愬姛");
+ }
+
+ /**
+ * 鐣欐牱鍑哄簱楠岃瘉锛氬鎵瑰墠鏍¢獙鐢宠鍑哄簱鏁伴噺涓嶈兘澶т簬鐣欐牱鐜板瓨閲忋��
+ */
+ @Operation(summary = "鐣欐牱鍑哄簱楠岃瘉")
+ @PostMapping("/liuyang/chuku/validate")
+ public R<String> validateLiuyangChuku(@RequestBody Map<String, String> params) {
+ if (params == null) {
+ return R.error("璇锋眰鍙傛暟涓嶈兘涓虹┖");
+ }
+ String flowId = params.get("flow_id");
+ String taskId = params.get("task_id");
+ if (isBlank(flowId)) {
+ return R.error("娴佺▼id(flow_id)涓嶈兘涓虹┖");
+ }
+ if (isBlank(taskId)) {
+ return R.error("娴佺▼浠诲姟id(task_id)涓嶈兘涓虹┖");
+ }
+
+ try {
+ String shenqingId = findLiuyangChukuShenqingId(flowId, taskId);
+ if (isBlank(shenqingId)) {
+ return R.error("鐣欐牱鍑哄簱鐢宠鏁版嵁涓嶅瓨鍦�");
+ }
+
+ List<Map<String, String>> zixiangList = listLiuyangChukuShenqingZixiang(shenqingId);
+ for (Map<String, String> zixiang : zixiangList) {
+ String liuyangJiluId = zixiang.get("liuyang_jilu_id");
+ LimsLiuyangJiluEntity jilu = isBlank(liuyangJiluId) ? null : findById(liuyangJiluId);
+ if (jilu == null) {
+ return R.error(buildChukuStockErrorMessage(zixiang));
+ }
+
+ BigDecimal chukuShuliang = parseDecimal(zixiang.get("chuku_shuliang"));
+ BigDecimal xiancunliang = parseDecimal(jilu.getLiuyangXiancunliang());
+ if (chukuShuliang == null || xiancunliang == null || chukuShuliang.compareTo(xiancunliang) > 0) {
+ return R.error(buildChukuStockErrorMessage(zixiang, jilu));
+ }
+ }
+ return R.success("楠岃瘉閫氳繃");
+ } catch (SQLException e) {
+ log.error("鐣欐牱鍑哄簱楠岃瘉澶辫触锛歠lowId={}, taskId={}", flowId, taskId, e);
+ return R.error("鐣欐牱鍑哄簱楠岃瘉澶辫触");
+ }
+ }
+
+ /**
+ * 鐣欐牱鍑哄簱锛氭寜鐢宠瀛愰」鎵e噺鐣欐牱鐜板瓨閲忥紝鍚屾瑙傚療璁″垝鐜板瓨閲忥紝骞跺啓鍑哄簱璁板綍銆�
+ */
+ @Transactional(rollbackFor = Exception.class)
+ @Operation(summary = "鐣欐牱鍑哄簱")
+ @PostMapping("/liuyang/chuku/action")
+ @AuditLog(action = "OUTBOUND", label = "鐣欐牱鍑哄簱", bizType = "LIUYANG",
+ bizCodeExpr = "#result.success ? #params['liuyang_jilu_id'] : ''",
+ targetTable = "lims_liuyang_jilu", targetIdExpr = "#params['liuyang_jilu_id']",
+ diff = true, entityClass = LimsLiuyangJiluEntity.class)
+ public R<String> liuyangChukuAction(@RequestBody Map<String, String> params) {
+ if (params == null) {
+ return R.error("璇锋眰鍙傛暟涓嶈兘涓虹┖");
+ }
+ String flowId = params.get("flow_id");
+ String taskId = params.get("task_id");
+ if (isBlank(flowId)) {
+ return R.error("娴佺▼id(flow_id)涓嶈兘涓虹┖");
+ }
+ if (isBlank(taskId)) {
+ return R.error("娴佺▼浠诲姟id(task_id)涓嶈兘涓虹┖");
+ }
+
+ Map<String, Object> shenqing = findLiuyangChukuShenqing(flowId, taskId);
+ if (shenqing == null || shenqing.isEmpty()) {
+ return R.error("鐣欐牱鍑哄簱鐢宠鏁版嵁涓嶅瓨鍦�");
+ }
+ String shenqingId = getString(shenqing, "f_id");
+ List<Map<String, Object>> zixiangList = listLiuyangChukuShenqingZixiangRows(shenqingId);
+ if (zixiangList.isEmpty()) {
+ return R.error("鐣欐牱鍑哄簱鐢宠瀛愰」涓嶈兘涓虹┖");
+ }
+
+ for (Map<String, Object> zixiang : zixiangList) {
+ String liuyangJiluId = getString(zixiang, "liuyang_jilu_id");
+ LimsLiuyangJiluEntity jilu = isBlank(liuyangJiluId) ? null : findById(liuyangJiluId);
+ if (jilu == null) {
+ return R.error(buildChukuStockErrorMessage(zixiang));
+ }
+
+ BigDecimal chukuShuliang = parseDecimal(getString(zixiang, "chuku_shuliang"));
+ BigDecimal oldXiancunliang = parseDecimal(jilu.getLiuyangXiancunliang());
+ if (chukuShuliang == null || oldXiancunliang == null || chukuShuliang.compareTo(oldXiancunliang) > 0) {
+ return R.error(buildChukuStockErrorMessage(zixiang, jilu));
+ }
+
+ BigDecimal newXiancunliang = oldXiancunliang.subtract(chukuShuliang);
+ String newXiancunliangText = toPlainString(newXiancunliang);
+
+ LimsLiuyangJiluEntity jiluUpdate = new LimsLiuyangJiluEntity();
+ jiluUpdate.setId(jilu.getId());
+ jiluUpdate.setLiuyangXiancunliang(newXiancunliangText);
+ limsLiuyangJiluService.updateById(jiluUpdate);
+
+ syncChukuLiuyangXiancunliangToJihua(jilu.getId(), newXiancunliangText);
+ insertLiuyangChukuRecord(shenqing, zixiang, jilu, oldXiancunliang);
+ }
+
+ return R.success("鍑哄簱鎴愬姛");
+ }
+
+ private Map<String, Object> findLiuyangChukuShenqing(String flowId, String taskId) {
+ String sql = "select * from " + LIUYANG_CHUKU_SHENQING_TABLE
+ + " where f_flow_id = ? and f_flow_task_id = ?"
+ + " and (f_delete_mark is null or f_delete_mark <> 1)"
+ + " limit 1";
+ List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, flowId, taskId);
+ return list.isEmpty() ? null : list.get(0);
+ }
+
+ private List<Map<String, Object>> listLiuyangChukuShenqingZixiangRows(String shenqingId) {
+ String sql = "select * from " + LIUYANG_CHUKU_SHENQING_ZIXIANG_TABLE
+ + " where f_foreign_id = ?"
+ + " and (f_delete_mark is null or f_delete_mark <> 1)";
+ return jdbcTemplate.queryForList(sql, shenqingId);
+ }
+
+ private void syncChukuLiuyangXiancunliangToJihua(String liuyangJiluId, String liuyangXiancunliang) {
+ LambdaUpdateWrapper<LimsLiuyangJihuaEntity> wrapper = new LambdaUpdateWrapper<>();
+ wrapper.eq(LimsLiuyangJihuaEntity::getLiuyangJiluId, liuyangJiluId)
+ .and(w -> w.isNull(LimsLiuyangJihuaEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangJihuaEntity::getDeleteMark, 1))
+ .set(LimsLiuyangJihuaEntity::getLiuyangXiancunliang, liuyangXiancunliang);
+ limsLiuyangJihuaService.update(wrapper);
+ }
+
+ private void insertLiuyangChukuRecord(Map<String, Object> shenqing,
+ Map<String, Object> zixiang,
+ LimsLiuyangJiluEntity jilu,
+ BigDecimal oldXiancunliang) {
+ String sql = "insert into " + LIUYANG_CHUKU_TABLE
+ + " (f_id, f_foreign_id, f_tenant_id, chuku_shenqing_id,"
+ + " yangpin_mingcheng, yangpin_bianma, guige, pihao,"
+ + " liuyang_xiancunliang, chuku_shuliang, danwei, yongtu,"
+ + " shenqing_ren, shenqing_riqi, fafang_ren, shenhe_ren, shenhe_riqi, fafang_riqi)"
+ + " values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ String shenqingId = getString(shenqing, "f_id");
+ jdbcTemplate.update(sql,
+ RandomUtil.uuId(),
+ jilu.getId(),
+ firstNotBlank(getString(zixiang, "f_tenant_id"), getString(shenqing, "f_tenant_id")),
+ shenqingId,
+ firstNotBlank(getString(zixiang, "yangpin_mingcheng"), jilu.getYangpinMingcheng()),
+ firstNotBlank(getString(zixiang, "yangpin_bianma"), jilu.getYangpinBianma()),
+ firstNotBlank(getString(zixiang, "guige"), jilu.getGuige()),
+ firstNotBlank(getString(zixiang, "pihao"), jilu.getPihao()),
+ toPlainString(oldXiancunliang),
+ parseDecimal(getString(zixiang, "chuku_shuliang")),
+ firstNotBlank(getString(zixiang, "danwei"), jilu.getDanwei()),
+ firstNotBlank(getString(zixiang, "yongtu"), getString(shenqing, "yongtu")),
+ getObject(shenqing, "shenqing_ren"),
+ getObject(shenqing, "shenqing_riqi"),
+ getObject(shenqing, "fafang_ren"),
+ getObject(shenqing, "shenhe_ren"),
+ getObject(shenqing, "shenhe_riqi"),
+ getObject(shenqing, "fafang_riqi"));
+ }
+
+ private Map<String, Object> findLiuyangXiaohuiShenqing(String flowId, String taskId) {
+ String sql = "select * from " + LIUYANG_XIAOHUI_SHENQING_TABLE
+ + " where f_flow_id = ? and f_flow_task_id = ?"
+ + " and (f_delete_mark is null or f_delete_mark <> 1)"
+ + " limit 1";
+ List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, flowId, taskId);
+ return list.isEmpty() ? null : list.get(0);
+ }
+
+ private List<String> listLiuyangXiaohuiJiluIds(String shenqingId) {
+ String sql = "select distinct liuyang_jilu_id from " + LIUYANG_XIAOHUI_SHENQING_ZIXIANG_TABLE
+ + " where f_foreign_id = ?"
+ + " and liuyang_jilu_id is not null and liuyang_jilu_id <> ''"
+ + " and (f_delete_mark is null or f_delete_mark <> 1)";
+ return jdbcTemplate.queryForList(sql, shenqingId).stream()
+ .map(row -> getString(row, "liuyang_jilu_id"))
+ .filter(value -> !isBlank(value))
+ .distinct()
+ .collect(Collectors.toList());
+ }
+
+ private void updateLiuyangXiaohuiDanhao(List<String> liuyangJiluIds, String xiaohuiDanhao) {
+ LambdaUpdateWrapper<LimsLiuyangJiluEntity> wrapper = new LambdaUpdateWrapper<>();
+ wrapper.in(LimsLiuyangJiluEntity::getId, liuyangJiluIds)
+ .and(w -> w.isNull(LimsLiuyangJiluEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangJiluEntity::getDeleteMark, 1))
+ .set(LimsLiuyangJiluEntity::getXiaohuiDanhao, xiaohuiDanhao);
+ limsLiuyangJiluService.update(wrapper);
+ }
+
+ private void acceptLiuyangXiaohui(List<String> liuyangJiluIds) {
+ LambdaUpdateWrapper<LimsLiuyangJiluEntity> jiluUpdate = new LambdaUpdateWrapper<>();
+ jiluUpdate.in(LimsLiuyangJiluEntity::getId, liuyangJiluIds)
+ .and(w -> w.isNull(LimsLiuyangJiluEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangJiluEntity::getDeleteMark, 1))
+ .set(LimsLiuyangJiluEntity::getBizStatus, BIZ_STATUS_DESTROYED);
+ limsLiuyangJiluService.update(jiluUpdate);
+
+ List<String> jihuaIds = listLiuyangJihuaIdsByJiluIds(liuyangJiluIds);
+
+ LambdaUpdateWrapper<LimsLiuyangJihuaEntity> jihuaUpdate = new LambdaUpdateWrapper<>();
+ jihuaUpdate.in(LimsLiuyangJihuaEntity::getLiuyangJiluId, liuyangJiluIds)
+ .and(w -> w.isNull(LimsLiuyangJihuaEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangJihuaEntity::getDeleteMark, 1))
+ .set(LimsLiuyangJihuaEntity::getBizStatus, BIZ_STATUS_DISABLED);
+ limsLiuyangJihuaService.update(jihuaUpdate);
+
+ if (!jihuaIds.isEmpty()) {
+ LambdaUpdateWrapper<LimsLiuyangJihuaZixiangEntity> zixiangUpdate = new LambdaUpdateWrapper<>();
+ zixiangUpdate.in(LimsLiuyangJihuaZixiangEntity::getForeignId, jihuaIds)
+ .and(w -> w.isNull(LimsLiuyangJihuaZixiangEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangJihuaZixiangEntity::getDeleteMark, 1))
+ .set(LimsLiuyangJihuaZixiangEntity::getBizStatus, BIZ_STATUS_DISABLED);
+ limsLiuyangJihuaZixiangService.update(zixiangUpdate);
+ }
+ }
+
+ private List<String> listLiuyangJihuaIdsByJiluIds(List<String> liuyangJiluIds) {
+ LambdaQueryWrapper<LimsLiuyangJihuaEntity> query = new LambdaQueryWrapper<>();
+ query.in(LimsLiuyangJihuaEntity::getLiuyangJiluId, liuyangJiluIds)
+ .and(w -> w.isNull(LimsLiuyangJihuaEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangJihuaEntity::getDeleteMark, 1));
+ return limsLiuyangJihuaService.list(query).stream()
+ .map(LimsLiuyangJihuaEntity::getId)
+ .filter(value -> !isBlank(value))
+ .distinct()
+ .collect(Collectors.toList());
+ }
+
+ private String findLiuyangChukuShenqingId(String flowId, String taskId) throws SQLException {
+ String sql = "select f_id from " + LIUYANG_CHUKU_SHENQING_TABLE
+ + " where f_flow_id = ? and f_flow_task_id = ?"
+ + " and (f_delete_mark is null or f_delete_mark <> 1)"
+ + " limit 1";
+ try (Connection connection = dataSource.getConnection();
+ PreparedStatement statement = connection.prepareStatement(sql)) {
+ statement.setString(1, flowId);
+ statement.setString(2, taskId);
+ try (ResultSet resultSet = statement.executeQuery()) {
+ return resultSet.next() ? resultSet.getString("f_id") : null;
+ }
+ }
+ }
+
+ private List<Map<String, String>> listLiuyangChukuShenqingZixiang(String shenqingId) throws SQLException {
+ String sql = "select liuyang_jilu_id, chuku_shuliang, yangpin_mingcheng, pihao from "
+ + LIUYANG_CHUKU_SHENQING_ZIXIANG_TABLE
+ + " where f_foreign_id = ?"
+ + " and (f_delete_mark is null or f_delete_mark <> 1)";
+ List<Map<String, String>> list = new ArrayList<>();
+ try (Connection connection = dataSource.getConnection();
+ PreparedStatement statement = connection.prepareStatement(sql)) {
+ statement.setString(1, shenqingId);
+ try (ResultSet resultSet = statement.executeQuery()) {
+ while (resultSet.next()) {
+ Map<String, String> row = new LinkedHashMap<>();
+ row.put("liuyang_jilu_id", resultSet.getString("liuyang_jilu_id"));
+ row.put("chuku_shuliang", resultSet.getString("chuku_shuliang"));
+ row.put("yangpin_mingcheng", resultSet.getString("yangpin_mingcheng"));
+ row.put("pihao", resultSet.getString("pihao"));
+ list.add(row);
+ }
+ }
+ }
+ return list;
+ }
+
+ private String buildChukuStockErrorMessage(Map<String, ?> zixiang) {
+ return buildChukuStockErrorMessage(zixiang, null);
+ }
+
+ private String buildChukuStockErrorMessage(Map<String, ?> zixiang, LimsLiuyangJiluEntity jilu) {
+ String yangpinMingcheng = firstNotBlank(getString(zixiang, "yangpin_mingcheng"), jilu == null ? null : jilu.getYangpinMingcheng());
+ String pihao = firstNotBlank(getString(zixiang, "pihao"), jilu == null ? null : jilu.getPihao());
+ return trimToEmpty(yangpinMingcheng) + "鎵规" + trimToEmpty(pihao) + "搴撳瓨涓嶈冻锛屼笉婊¤冻鍑哄簱鏉′欢";
+ }
+
+ private BigDecimal parseDecimal(String value) {
+ if (isBlank(value)) {
+ return null;
+ }
+ try {
+ return new BigDecimal(value.trim());
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ }
+
+ private String firstNotBlank(String first, String second) {
+ return isBlank(first) ? second : first;
+ }
+
+ private String trimToEmpty(String value) {
+ return value == null ? "" : value.trim();
+ }
+
+ private String getString(Map<String, ?> row, String key) {
+ if (row == null || key == null) {
+ return null;
+ }
+ Object value = row.get(key);
+ return value == null ? null : String.valueOf(value);
+ }
+
+ private Object getObject(Map<String, ?> row, String key) {
+ if (row == null || key == null) {
+ return null;
+ }
+ return row.get(key);
+ }
+
+ private String toPlainString(BigDecimal value) {
+ return value == null ? null : value.stripTrailingZeros().toPlainString();
+ }
+
+ private void syncBiangengToJihua(String liuyangJiluId, LimsLiuyangBiangengShenqingEntity shenqing) {
+ LambdaUpdateWrapper<LimsLiuyangJihuaEntity> wrapper = new LambdaUpdateWrapper<>();
+ wrapper.eq(LimsLiuyangJihuaEntity::getLiuyangJiluId, liuyangJiluId)
+ .and(w -> w.isNull(LimsLiuyangJihuaEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangJihuaEntity::getDeleteMark, 1))
+ .set(LimsLiuyangJihuaEntity::getRukuShuliang, shenqing.getRukuShuliang())
+ .set(LimsLiuyangJihuaEntity::getLiuyangXiancunliang, shenqing.getRukuShuliang())
+ .set(LimsLiuyangJihuaEntity::getDanwei, shenqing.getDanwei())
+ .set(LimsLiuyangJihuaEntity::getLiuyangXiancunliangDanwei, shenqing.getDanwei());
+ limsLiuyangJihuaService.update(wrapper);
+ }
+
+ private LimsLiuyangBiangengShenqingEntity findBiangengShenqing(String id) {
+ LambdaQueryWrapper<LimsLiuyangBiangengShenqingEntity> query = new LambdaQueryWrapper<>();
+ query.eq(LimsLiuyangBiangengShenqingEntity::getId, id)
+ .and(w -> w.isNull(LimsLiuyangBiangengShenqingEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangBiangengShenqingEntity::getDeleteMark, 1));
+ query.last("limit 1");
+ return limsLiuyangBiangengShenqingService.getOne(query, false);
+ }
+
+ private LimsLiuyangJihuaBiangengShenqingEntity findJihuaBiangengShenqing(String flowId, String taskId) {
+ LambdaQueryWrapper<LimsLiuyangJihuaBiangengShenqingEntity> query = new LambdaQueryWrapper<>();
+ query.eq(LimsLiuyangJihuaBiangengShenqingEntity::getFlowId, flowId)
+ .eq(LimsLiuyangJihuaBiangengShenqingEntity::getFlowTaskId, taskId)
+ .and(w -> w.isNull(LimsLiuyangJihuaBiangengShenqingEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangJihuaBiangengShenqingEntity::getDeleteMark, 1));
+ query.last("limit 1");
+ return limsLiuyangJihuaBiangengShenqingService.getOne(query, false);
+ }
+
+ private void updateJihuaByBiangeng(LimsLiuyangJihuaBiangengShenqingEntity shenqing) {
+ LimsLiuyangJihuaEntity update = new LimsLiuyangJihuaEntity();
+ update.setId(shenqing.getLiuyangJihuaId());
+ update.setLiuyangRiqi(shenqing.getLiuyangRiqi());
+ update.setLiuyangZhouqiId(shenqing.getLiuyangZhouqiId());
+ limsLiuyangJihuaService.updateById(update);
+ }
+
+ private void softDeleteUnobservedJihuaZixiang(String jihuaId) {
+ LambdaUpdateWrapper<LimsLiuyangJihuaZixiangEntity> wrapper = new LambdaUpdateWrapper<>();
+ wrapper.eq(LimsLiuyangJihuaZixiangEntity::getForeignId, jihuaId)
+ .and(w -> w.isNull(LimsLiuyangJihuaZixiangEntity::getShifouYiguancha)
+ .or()
+ .ne(LimsLiuyangJihuaZixiangEntity::getShifouYiguancha, "yes"))
+ .and(w -> w.isNull(LimsLiuyangJihuaZixiangEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangJihuaZixiangEntity::getDeleteMark, 1))
+ .set(LimsLiuyangJihuaZixiangEntity::getDeleteMark, 1)
+ .set(LimsLiuyangJihuaZixiangEntity::getDeleteTime, new Date())
+ .set(LimsLiuyangJihuaZixiangEntity::getDeleteUserId, UserProvider.getUser().getUserId());
+ limsLiuyangJihuaZixiangService.update(wrapper);
+ }
+
+ private void syncBiangengZixiangToJihuaZixiang(LimsLiuyangJihuaEntity jihua, LimsLiuyangJihuaBiangengShenqingEntity shenqing) {
+ List<LimsLiuyangJihuaBiangengShenqingZixiangEntity> shenqingZixiangList = listUnobservedJihuaBiangengZixiang(shenqing.getId());
+ if (shenqingZixiangList.isEmpty()) {
+ return;
+ }
+
+ List<LimsLiuyangJihuaZixiangEntity> jihuaZixiangList = shenqingZixiangList.stream()
+ .map(row -> buildJihuaZixiangFromBiangeng(jihua, shenqing, row))
+ .collect(Collectors.toList());
+ limsLiuyangJihuaZixiangService.saveBatch(jihuaZixiangList);
+ }
+
+ private List<LimsLiuyangJihuaBiangengShenqingZixiangEntity> listUnobservedJihuaBiangengZixiang(String shenqingId) {
+ LambdaQueryWrapper<LimsLiuyangJihuaBiangengShenqingZixiangEntity> query = new LambdaQueryWrapper<>();
+ query.eq(LimsLiuyangJihuaBiangengShenqingZixiangEntity::getForeignId, shenqingId)
+ .and(w -> w.isNull(LimsLiuyangJihuaBiangengShenqingZixiangEntity::getShifouYiguancha)
+ .or()
+ .ne(LimsLiuyangJihuaBiangengShenqingZixiangEntity::getShifouYiguancha, "yes"))
+ .and(w -> w.isNull(LimsLiuyangJihuaBiangengShenqingZixiangEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangJihuaBiangengShenqingZixiangEntity::getDeleteMark, 1))
+ .orderByAsc(LimsLiuyangJihuaBiangengShenqingZixiangEntity::getJihuaRiqi);
+ return limsLiuyangJihuaBiangengShenqingZixiangService.list(query);
+ }
+
+ private LimsLiuyangJihuaZixiangEntity buildJihuaZixiangFromBiangeng(
+ LimsLiuyangJihuaEntity jihua,
+ LimsLiuyangJihuaBiangengShenqingEntity shenqing,
+ LimsLiuyangJihuaBiangengShenqingZixiangEntity shenqingZixiang) {
+ LimsLiuyangJihuaZixiangEntity zixiang = new LimsLiuyangJihuaZixiangEntity();
+ zixiang.setId(RandomUtil.uuId());
+ zixiang.setForeignId(jihua.getId());
+ zixiang.setZhouqi(shenqingZixiang.getZhouqi());
+ zixiang.setZhouqiDanwei(shenqingZixiang.getZhouqiDanwei());
+ zixiang.setJihuaRiqi(shenqingZixiang.getJihuaRiqi());
+ zixiang.setGuanchaRiqi(shenqingZixiang.getGuanchaRiqi());
+ zixiang.setGuanchaRen(shenqingZixiang.getGuanchaRen());
+ zixiang.setGuanchaShuliang(shenqingZixiang.getGuanchaShuliang());
+ zixiang.setGuanchaQingkuang(shenqingZixiang.getGuanchaQingkuang());
+ zixiang.setGuanchaJieguo(shenqingZixiang.getGuanchaJieguo());
+ zixiang.setShifouYiguancha(shenqingZixiang.getShifouYiguancha());
+ zixiang.setBeizhu(shenqingZixiang.getBeizhu());
+ zixiang.setBizType(jihua.getBizType());
+ zixiang.setYangpinMingcheng(jihua.getYangpinMingcheng());
+ zixiang.setYangpinBianma(jihua.getYangpinBianma());
+ zixiang.setGuige(jihua.getGuige());
+ zixiang.setPihao(jihua.getPihao());
+ zixiang.setShengchanRiqi(jihua.getShengchanRiqi());
+ zixiang.setYouxiaoqi(jihua.getYouxiaoqi());
+ zixiang.setLiuyangRiqi(shenqing.getLiuyangRiqi());
+ zixiang.setGuanchaShuliangDanwei(jihua.getDanwei());
+ zixiang.setBizStatus(jihua.getBizStatus());
+ return zixiang;
+ }
+
+ private boolean equalsNullable(String a, String b) {
+ if (a == null && b == null) {
+ return true;
+ }
+ if (a == null || b == null) {
+ return false;
+ }
+ return a.trim().equals(b.trim());
+ }
+
+ private String getFormId(Map<String, Object> formData) {
+ if (formData == null) {
+ return null;
+ }
+ Object id = formData.get("f_id");
+ if (id == null) {
+ id = formData.get("id");
+ }
+ return id == null ? null : String.valueOf(id);
+ }
+
+ private void syncJihuaInfoToZixiang(LimsLiuyangJihuaEntity jihua) {
+ LambdaUpdateWrapper<LimsLiuyangJihuaZixiangEntity> wrapper = new LambdaUpdateWrapper<>();
+ wrapper.eq(LimsLiuyangJihuaZixiangEntity::getForeignId, jihua.getId())
+ .and(w -> w.isNull(LimsLiuyangJihuaZixiangEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangJihuaZixiangEntity::getDeleteMark, 1))
+ // 鎻愪氦璁″垝鏃讹紝灏嗕富琛ㄦ牱鍝佷俊鎭啑浣欏埌鍛ㄦ湡瀛愰」锛屼究浜庡悗缁瀵熷垪琛ㄧ嫭绔嬪睍绀恒��
+ .set(LimsLiuyangJihuaZixiangEntity::getBizType, jihua.getBizType())
+ .set(LimsLiuyangJihuaZixiangEntity::getYangpinMingcheng, jihua.getYangpinMingcheng())
+ .set(LimsLiuyangJihuaZixiangEntity::getYangpinBianma, jihua.getYangpinBianma())
+ .set(LimsLiuyangJihuaZixiangEntity::getGuige, jihua.getGuige())
+ .set(LimsLiuyangJihuaZixiangEntity::getPihao, jihua.getPihao())
+ .set(LimsLiuyangJihuaZixiangEntity::getShengchanRiqi, jihua.getShengchanRiqi())
+ .set(LimsLiuyangJihuaZixiangEntity::getYouxiaoqi, jihua.getYouxiaoqi())
+ .set(LimsLiuyangJihuaZixiangEntity::getLiuyangRiqi, jihua.getLiuyangRiqi())
+ .set(LimsLiuyangJihuaZixiangEntity::getGuanchaShuliangDanwei, jihua.getDanwei())
+ .set(LimsLiuyangJihuaZixiangEntity::getBizStatus, jihua.getBizStatus());
+ limsLiuyangJihuaZixiangService.update(wrapper);
+ }
+
+ private LimsLiuyangJiluEntity findLiuyangJilu(String id, String flowId, String taskId) {
+ if (id != null && !id.isEmpty()) {
+ return findById(id);
+ }
+ return findByFlow(flowId, taskId);
+ }
+
+ private LimsLiuyangJiluEntity findById(String id) {
+ LambdaQueryWrapper<LimsLiuyangJiluEntity> query = new LambdaQueryWrapper<>();
+ query.eq(LimsLiuyangJiluEntity::getId, id)
+ .and(w -> w.isNull(LimsLiuyangJiluEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangJiluEntity::getDeleteMark, 1));
+ query.last("limit 1");
+ return limsLiuyangJiluService.getOne(query, false);
+ }
+
+ private LimsLiuyangJiluEntity findByFlow(String flowId, String taskId) {
+ LambdaQueryWrapper<LimsLiuyangJiluEntity> query = new LambdaQueryWrapper<>();
+ query.eq(LimsLiuyangJiluEntity::getFlowId, flowId)
+ .and(w -> w.isNull(LimsLiuyangJiluEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangJiluEntity::getDeleteMark, 1));
+ if (taskId != null && !taskId.isEmpty()) {
+ query.eq(LimsLiuyangJiluEntity::getFlowTaskId, taskId);
+ }
+ query.last("limit 1");
+ return limsLiuyangJiluService.getOne(query, false);
+ }
+
+ private List<LiuyangWendingxingZhouqiZixiangEntity> listWendingxingZhouqiZixiang(String zhouqiId) {
+ LambdaQueryWrapper<LiuyangWendingxingZhouqiZixiangEntity> query = new LambdaQueryWrapper<>();
+ query.eq(LiuyangWendingxingZhouqiZixiangEntity::getForeignId, zhouqiId)
+ .and(w -> w.isNull(LiuyangWendingxingZhouqiZixiangEntity::getDeleteMark)
+ .or()
+ .ne(LiuyangWendingxingZhouqiZixiangEntity::getDeleteMark, 1))
+ .orderByAsc(LiuyangWendingxingZhouqiZixiangEntity::getZhouqi);
+ return liuyangWendingxingZhouqiZixiangService.list(query);
+ }
+
+ private List<LimsLiuyangJihuaZixiangEntity> listObservedJihuaZixiang(String jihuaId) {
+ LambdaQueryWrapper<LimsLiuyangJihuaZixiangEntity> query = new LambdaQueryWrapper<>();
+ query.eq(LimsLiuyangJihuaZixiangEntity::getForeignId, jihuaId)
+ .eq(LimsLiuyangJihuaZixiangEntity::getShifouYiguancha, "yes")
+ .and(w -> w.isNull(LimsLiuyangJihuaZixiangEntity::getDeleteMark)
+ .or()
+ .ne(LimsLiuyangJihuaZixiangEntity::getDeleteMark, 1))
+ .orderByAsc(LimsLiuyangJihuaZixiangEntity::getJihuaRiqi);
+ return limsLiuyangJihuaZixiangService.list(query);
+ }
+
+ private LimsLiuyangJihuaCalculateResult buildJihuaZixiang(LiuyangWendingxingZhouqiZixiangEntity zhouqi, Date shouyangRiqi) {
+ if (zhouqi.getZhouqi() == null) {
+ throw new IllegalArgumentException("鍛ㄦ湡涓嶈兘涓虹┖");
+ }
+ if (isBlank(zhouqi.getZhouqiDanwei())) {
+ throw new IllegalArgumentException("鍛ㄦ湡鍗曚綅涓嶈兘涓虹┖");
+ }
+
+ LimsLiuyangJihuaCalculateResult item = new LimsLiuyangJihuaCalculateResult();
+ item.setZhouqi(zhouqi.getZhouqi());
+ item.setZhouqiDanwei(zhouqi.getZhouqiDanwei());
+ item.setJihuaRiqi(calculateJihuaRiqi(shouyangRiqi, zhouqi.getZhouqi(), zhouqi.getZhouqiDanwei()));
+ item.setGuanchaRiqi(null);
+ item.setShifouYiguancha("no");
+ return item;
+ }
+
+ private Map<String, Object> buildBiangengRow(LimsLiuyangJihuaZixiangEntity jihuaZixiang, List<String> responseFields) {
+ Map<String, Object> row = newEmptyBiangengRow(responseFields);
+ putIfPresent(row, "zhouqi", jihuaZixiang.getZhouqi());
+ putIfPresent(row, "zhouqi_danwei", jihuaZixiang.getZhouqiDanwei());
+ putIfPresent(row, "jihua_riqi", jihuaZixiang.getJihuaRiqi());
+ putIfPresent(row, "shifou_yiguancha", jihuaZixiang.getShifouYiguancha());
+ putIfPresent(row, "guancha_riqi", jihuaZixiang.getGuanchaRiqi());
+ putIfPresent(row, "guancha_ren", jihuaZixiang.getGuanchaRen());
+ putIfPresent(row, "guancha_shuliang", jihuaZixiang.getGuanchaShuliang());
+ putIfPresent(row, "guancha_qingkuang", jihuaZixiang.getGuanchaQingkuang());
+ putIfPresent(row, "guancha_jieguo", jihuaZixiang.getGuanchaJieguo());
+ putIfPresent(row, "beizhu", jihuaZixiang.getBeizhu());
+ return row;
+ }
+
+ private Map<String, Object> buildBiangengRow(LiuyangWendingxingZhouqiZixiangEntity zhouqi, Date liuyangRiqi, List<String> responseFields) {
+ if (zhouqi.getZhouqi() == null) {
+ throw new IllegalArgumentException("鍛ㄦ湡涓嶈兘涓虹┖");
+ }
+ if (isBlank(zhouqi.getZhouqiDanwei())) {
+ throw new IllegalArgumentException("鍛ㄦ湡鍗曚綅涓嶈兘涓虹┖");
+ }
+
+ Map<String, Object> row = newEmptyBiangengRow(responseFields);
+ putIfPresent(row, "zhouqi", zhouqi.getZhouqi());
+ putIfPresent(row, "zhouqi_danwei", zhouqi.getZhouqiDanwei());
+ putIfPresent(row, "jihua_riqi", calculateJihuaRiqi(liuyangRiqi, zhouqi.getZhouqi(), zhouqi.getZhouqiDanwei()));
+ putIfPresent(row, "shifou_yiguancha", "no");
+ return row;
+ }
+
+ private Map<String, Object> newEmptyBiangengRow(List<String> responseFields) {
+ Map<String, Object> row = new LinkedHashMap<>();
+ for (String field : responseFields) {
+ row.put(field, null);
+ }
+ return row;
+ }
+
+ private void putIfPresent(Map<String, Object> row, String field, Object value) {
+ if (row.containsKey(field)) {
+ row.put(field, value);
+ }
+ }
+
+ private String buildZhouqiKey(BigDecimal zhouqi, String zhouqiDanwei) {
+ if (zhouqi == null || isBlank(zhouqiDanwei)) {
+ return "";
+ }
+ return zhouqi.stripTrailingZeros().toPlainString() + "|" + zhouqiDanwei.trim();
+ }
+
+ private List<String> getBiangengZixiangBusinessFields() {
+ Set<String> fields = new LinkedHashSet<>();
+ try (Connection connection = dataSource.getConnection()) {
+ DatabaseMetaData metaData = connection.getMetaData();
+ readBusinessColumns(fields, metaData, connection.getCatalog(), connection.getSchema(), BIANGENG_ZIXIANG_TABLE);
+ if (fields.isEmpty()) {
+ readBusinessColumns(fields, metaData, connection.getCatalog(), connection.getSchema(), BIANGENG_ZIXIANG_TABLE.toUpperCase());
+ }
+ } catch (Exception e) {
+ log.warn("璇诲彇{}瀛楁澶辫触锛屼娇鐢ㄩ粯璁ゅ瓧娈�", BIANGENG_ZIXIANG_TABLE, e);
+ }
+ if (fields.isEmpty()) {
+ fields.addAll(DEFAULT_BIANGENG_ZIXIANG_FIELDS);
+ }
+ return new ArrayList<>(fields);
+ }
+
+ private void readBusinessColumns(Set<String> fields, DatabaseMetaData metaData, String catalog, String schema, String tableName) throws SQLException {
+ try (ResultSet columns = metaData.getColumns(catalog, schema, tableName, null)) {
+ while (columns.next()) {
+ String columnName = columns.getString("COLUMN_NAME");
+ if (!isBlank(columnName) && !columnName.toLowerCase().startsWith("f_")) {
+ fields.add(columnName);
+ }
+ }
+ }
+ }
+
+ private Date calculateJihuaRiqi(Date shouyangRiqi, BigDecimal zhouqi, String zhouqiDanwei) {
+ int amount = toIntegerZhouqi(zhouqi);
+ LocalDateTime baseTime = LocalDateTime.ofInstant(shouyangRiqi.toInstant(), ZoneId.systemDefault());
+ LocalDateTime jihuaTime;
+ switch (zhouqiDanwei.trim()) {
+ case "day":
+ case "澶�":
+ jihuaTime = baseTime.plusDays(amount);
+ break;
+ case "week":
+ case "鍛�":
+ jihuaTime = baseTime.plusWeeks(amount);
+ break;
+ case "month":
+ case "鏈�":
+ jihuaTime = baseTime.plusMonths(amount);
+ break;
+ case "quarter":
+ case "瀛�":
+ jihuaTime = baseTime.plusMonths(amount * 3L);
+ break;
+ case "year":
+ case "骞�":
+ jihuaTime = baseTime.plusYears(amount);
+ break;
+ default:
+ throw new IllegalArgumentException("涓嶆敮鎸佺殑鍛ㄦ湡鍗曚綅锛�" + zhouqiDanwei);
+ }
+ return Date.from(jihuaTime.atZone(ZoneId.systemDefault()).toInstant());
+ }
+
+ private int toIntegerZhouqi(BigDecimal zhouqi) {
+ try {
+ return zhouqi.stripTrailingZeros().intValueExact();
+ } catch (ArithmeticException e) {
+ throw new IllegalArgumentException("鍛ㄦ湡蹇呴』涓烘暣鏁帮細" + zhouqi);
+ }
+ }
+
+ private void updateLiuyangStatus(LimsLiuyangJiluEntity liuyangJilu, LiuyangStatus status, String bizSign) {
+ LimsLiuyangJiluEntity update = new LimsLiuyangJiluEntity();
+ update.setId(liuyangJilu.getId());
+ update.setBizStatus(status.getCode());
+ if (bizSign != null && !bizSign.isEmpty()) {
+ update.setBizSign(bizSign);
+ }
+ limsLiuyangJiluService.updateById(update);
+ }
+
+ private void receiveLiuyangJilu(LimsLiuyangJiluEntity liuyangJilu, String bizSign) {
+ LimsLiuyangJiluEntity update = new LimsLiuyangJiluEntity();
+ update.setId(liuyangJilu.getId());
+ update.setBizStatus(LiuyangStatus.RECEIVED.getCode());
+ update.setLiuyangXiancunliang(liuyangJilu.getRukuShuliang());
+ update.setLiuyangXiancunliangDanwei(liuyangJilu.getDanwei());
+ if (bizSign != null && !bizSign.isEmpty()) {
+ update.setBizSign(bizSign);
+ }
+ limsLiuyangJiluService.updateById(update);
+ }
+
+ private void softDeleteLiuyangJilu(LimsLiuyangJiluEntity liuyangJilu, String bizSign) {
+ LimsLiuyangJiluEntity update = new LimsLiuyangJiluEntity();
+ update.setId(liuyangJilu.getId());
+ update.setDeleteMark(1);
+ update.setDeleteTime(new Date());
+ update.setDeleteUserId(UserProvider.getUser().getUserId());
+ if (bizSign != null && !bizSign.isEmpty()) {
+ update.setBizSign(bizSign);
+ }
+ limsLiuyangJiluService.updateById(update);
+ }
+
+ private void updateQingyandanLiuyangJiluId(LimsLiuyangJiluEntity liuyangJilu, String liuyangJiluId) {
+ String qingyandanId = liuyangJilu.getQingyandanId();
+ if (qingyandanId == null || qingyandanId.isEmpty()) {
+ return;
+ }
+
+ LimsQingyandanEntity qingyandan = limsQingyandanService.getById(qingyandanId);
+ if (qingyandan == null) {
+ return;
+ }
+
+ LambdaUpdateWrapper<LimsQingyandanEntity> updateWrapper = new LambdaUpdateWrapper<>();
+ updateWrapper.eq(LimsQingyandanEntity::getId, qingyandan.getId())
+ .set(LimsQingyandanEntity::getLiuyangJiluId, liuyangJiluId);
+ limsQingyandanService.update(updateWrapper);
+ }
+
+ private boolean isBlank(String value) {
+ return value == null || value.trim().isEmpty();
+ }
+}
--
Gitblit v1.8.0