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
|
+ "]的值格式不正确:" + 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;
|
}
|
}
|
}
|