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-biz/src/main/java/jnpf/limsService/impl/LimsQingyandanYichangServiceImpl.java |  222 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 222 insertions(+), 0 deletions(-)

diff --git a/jnpf-lims/jnpf-lims-biz/src/main/java/jnpf/limsService/impl/LimsQingyandanYichangServiceImpl.java b/jnpf-lims/jnpf-lims-biz/src/main/java/jnpf/limsService/impl/LimsQingyandanYichangServiceImpl.java
new file mode 100644
index 0000000..a765bb7
--- /dev/null
+++ b/jnpf-lims/jnpf-lims-biz/src/main/java/jnpf/limsService/impl/LimsQingyandanYichangServiceImpl.java
@@ -0,0 +1,222 @@
+package jnpf.limsService.impl;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import jnpf.audit.sdk.annotation.AuditLog;
+import jnpf.exception.DataException;
+import jnpf.limsEntity.LimsQingyandanEntity;
+import jnpf.limsEntity.LimsQingyandanYichangShenqingEntity;
+import jnpf.limsEntity.LimsQingyandanYichangShenqingZiduanEntity;
+import jnpf.limsMapper.LimsQingyandanMapper;
+import jnpf.limsMapper.LimsQingyandanYichangShenqingMapper;
+import jnpf.limsMapper.LimsQingyandanYichangShenqingZiduanMapper;
+import jnpf.limsService.LimsQingyandanYichangService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+
+import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 璇烽獙鍗曞紓甯哥敵璇峰鐞嗘湇鍔″疄鐜般��
+ */
+@Service
+public class LimsQingyandanYichangServiceImpl implements LimsQingyandanYichangService {
+
+    private static final String[] DATE_PATTERNS = {
+            "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd"
+    };
+
+    private static final Set<String> IMMUTABLE_COLUMNS;
+    private static final Map<String, QingyandanField> QINGYANDAN_FIELDS;
+
+    static {
+        Set<String> immutableColumns = new HashSet<>();
+        Collections.addAll(immutableColumns,
+                "f_id", "f_tenant_id", "f_flow_id", "f_flow_task_id", "f_flow_state",
+                "f_version", "f_delete_mark", "f_delete_time", "f_delete_user_id",
+                "f_creator_user_id", "f_creator_time", "f_last_modify_user_id",
+                "f_last_modify_time");
+        IMMUTABLE_COLUMNS = Collections.unmodifiableSet(immutableColumns);
+        QINGYANDAN_FIELDS = buildQingyandanFields();
+    }
+
+    @Autowired
+    private LimsQingyandanYichangShenqingMapper shenqingMapper;
+
+    @Autowired
+    private LimsQingyandanYichangShenqingZiduanMapper ziduanMapper;
+
+    @Autowired
+    private LimsQingyandanMapper qingyandanMapper;
+
+    /**
+     * 鏌ヨ寮傚父鐢宠鍙婂叾鍙樻洿瀛楁锛屽苟鍦ㄥ悓涓�浜嬪姟涓洿鏂板叧鑱旇楠屽崟銆�
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    @AuditLog(action = "UPDATE", label = "澶勭悊璇烽獙鍗曞紓甯哥敵璇�", bizType = "QINGYANDAN",
+            bizCodeExpr = "#result > 0 ? #flowId : ''", targetTable = "lims_qingyandan",
+            targetIdExpr = "T(jnpf.limsService.support.LimsAuditTargetIds).qingyandanByExceptionFlow(#flowId, #flowTaskId)",
+            diff = true, entityClass = LimsQingyandanEntity.class)
+    public int chuli(String flowId, String flowTaskId) {
+        String resolvedFlowId = requireText(flowId, "娴佺▼ID(flow_id)涓嶈兘涓虹┖");
+        String resolvedFlowTaskId = requireText(flowTaskId, "娴佺▼浠诲姟ID(flow_task_id)涓嶈兘涓虹┖");
+
+        LimsQingyandanYichangShenqingEntity shenqing = getShenqing(
+                resolvedFlowId, resolvedFlowTaskId);
+        if (!StringUtils.hasText(shenqing.getQingyandanId())) {
+            throw new DataException("寮傚父鐢宠鏈叧鑱旇楠屽崟");
+        }
+
+        LambdaQueryWrapper<LimsQingyandanYichangShenqingZiduanEntity> ziduanQuery =
+                new LambdaQueryWrapper<>();
+        ziduanQuery.eq(LimsQingyandanYichangShenqingZiduanEntity::getForeignId, shenqing.getId());
+        List<LimsQingyandanYichangShenqingZiduanEntity> ziduanList =
+                ziduanMapper.selectList(ziduanQuery);
+        if (ziduanList.isEmpty()) {
+            throw new DataException("寮傚父鐢宠娌℃湁闇�瑕佸彉鏇寸殑瀛楁");
+        }
+
+        Map<String, Object> changes = resolveChanges(ziduanList);
+        UpdateWrapper<LimsQingyandanEntity> update = new UpdateWrapper<>();
+        update.eq("f_id", shenqing.getQingyandanId().trim());
+        changes.forEach(update::set);
+        int updated = qingyandanMapper.update(null, update);
+        if (updated != 1) {
+            throw new DataException(updated == 0 ? "鍏宠仈鐨勮楠屽崟涓嶅瓨鍦�" : "鍏宠仈鍒板鏉¤楠屽崟锛屽凡鍙栨秷鏇存柊");
+        }
+        return changes.size();
+    }
+
+    private LimsQingyandanYichangShenqingEntity getShenqing(String flowId, String flowTaskId) {
+        LambdaQueryWrapper<LimsQingyandanYichangShenqingEntity> query = new LambdaQueryWrapper<>();
+        query.eq(LimsQingyandanYichangShenqingEntity::getFlowId, flowId)
+                .eq(LimsQingyandanYichangShenqingEntity::getFlowTaskId, flowTaskId);
+        List<LimsQingyandanYichangShenqingEntity> rows = shenqingMapper.selectList(query);
+        if (rows.isEmpty()) {
+            throw new DataException("鏈壘鍒板搴旂殑璇烽獙鍗曞紓甯哥敵璇�");
+        }
+        if (rows.size() > 1) {
+            throw new DataException("鍚屼竴娴佺▼浠诲姟鍏宠仈浜嗗鏉¤楠屽崟寮傚父鐢宠");
+        }
+        return rows.get(0);
+    }
+
+    private Map<String, Object> resolveChanges(
+            List<LimsQingyandanYichangShenqingZiduanEntity> ziduanList) {
+        Map<String, Object> changes = new LinkedHashMap<>();
+        for (int i = 0; i < ziduanList.size(); i++) {
+            LimsQingyandanYichangShenqingZiduanEntity ziduan = ziduanList.get(i);
+            if (ziduan == null || !StringUtils.hasText(ziduan.getKebianZiduan())) {
+                throw new DataException("绗�" + (i + 1) + "鏉″彉鏇寸殑鍙彉瀛楁涓嶈兘涓虹┖");
+            }
+            String requestedField = normalize(ziduan.getKebianZiduan());
+            QingyandanField field = QINGYANDAN_FIELDS.get(requestedField);
+            if (field == null) {
+                throw new DataException("涓嶆敮鎸佸彉鏇磋楠屽崟瀛楁锛�" + ziduan.getKebianZiduan());
+            }
+            Object value = convertValue(ziduan.getBiangenghouShuju(), field, i);
+            changes.put(field.column, value);
+        }
+        return changes;
+    }
+
+    private Object convertValue(String value, QingyandanField field, int index) {
+        if (field.type == String.class) {
+            return value;
+        }
+        if (!StringUtils.hasText(value)) {
+            return null;
+        }
+        String trimmed = value.trim();
+        try {
+            if (field.type == Integer.class || field.type == int.class) {
+                return Integer.valueOf(trimmed);
+            }
+            if (field.type == Long.class || field.type == long.class) {
+                return Long.valueOf(trimmed);
+            }
+            if (field.type == BigDecimal.class) {
+                return new BigDecimal(trimmed);
+            }
+            if (field.type == Date.class) {
+                return parseDate(trimmed);
+            }
+        } catch (IllegalArgumentException | ParseException e) {
+            throw new DataException("绗�" + (index + 1) + "鏉″彉鏇村瓧娈礫" + field.column
+                    + "]鐨勫�兼牸寮忎笉姝g‘锛�" + value);
+        }
+        throw new DataException("涓嶆敮鎸佸瓧娈礫" + field.column + "]鐨勬暟鎹被鍨嬶細"
+                + field.type.getSimpleName());
+    }
+
+    private Date parseDate(String value) throws ParseException {
+        if (value.matches("^-?\\d+$")) {
+            return new Date(Long.parseLong(value));
+        }
+        for (String pattern : DATE_PATTERNS) {
+            SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.ROOT);
+            format.setLenient(false);
+            try {
+                return format.parse(value);
+            } catch (ParseException ignored) {
+                // Continue with the next supported format.
+            }
+        }
+        throw new ParseException(value, 0);
+    }
+
+    private static Map<String, QingyandanField> buildQingyandanFields() {
+        Map<String, QingyandanField> fields = new HashMap<>();
+        for (Field javaField : LimsQingyandanEntity.class.getDeclaredFields()) {
+            TableField tableField = javaField.getAnnotation(TableField.class);
+            if (tableField == null || !tableField.exist() || !StringUtils.hasText(tableField.value())) {
+                continue;
+            }
+            String column = normalize(tableField.value());
+            if (IMMUTABLE_COLUMNS.contains(column)) {
+                continue;
+            }
+            QingyandanField metadata = new QingyandanField(column, javaField.getType());
+            fields.put(column, metadata);
+            fields.put(normalize(javaField.getName()), metadata);
+        }
+        return Collections.unmodifiableMap(fields);
+    }
+
+    private static String requireText(String value, String message) {
+        if (!StringUtils.hasText(value)) {
+            throw new DataException(message);
+        }
+        return value.trim();
+    }
+
+    private static String normalize(String value) {
+        return value == null ? "" : value.trim().toLowerCase(Locale.ROOT);
+    }
+
+    private static final class QingyandanField {
+        private final String column;
+        private final Class<?> type;
+
+        private QingyandanField(String column, Class<?> type) {
+            this.column = column;
+            this.type = type;
+        }
+    }
+}

--
Gitblit v1.8.0