package jnpf.limsService.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import jnpf.base.ActionResult;
|
import jnpf.base.ActionResultCode;
|
import jnpf.flowable.TaskApi;
|
import jnpf.flowable.model.task.FlowModel;
|
import jnpf.limsEntity.JianyanJielun;
|
import jnpf.limsEntity.LimsAdDiaochabiaoEntity;
|
import jnpf.limsEntity.LimsJianyanResultItem;
|
import jnpf.limsEntity.LimsJianyanXiangEntity;
|
import jnpf.limsEntity.LimsOosOotDiaochabiaoEntity;
|
import jnpf.limsEntity.YichangDiaochaLeixing;
|
import jnpf.limsEntity.ZhiliangBiaozhunGuanliZixiangEntity;
|
import jnpf.limsService.LimsAdDiaochabiaoService;
|
import jnpf.limsService.LimsFlowTemplateResolver;
|
import jnpf.limsService.LimsOosOotDiaochabiaoService;
|
import jnpf.limsService.LimsYichangDiaochaService;
|
import jnpf.limsService.ZhiliangBiaozhunGuanliZixiangService;
|
import jnpf.util.UserProvider;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
import java.text.SimpleDateFormat;
|
import java.util.Collections;
|
import java.util.Date;
|
import java.util.LinkedHashMap;
|
import java.util.Map;
|
|
@Service
|
public class LimsYichangDiaochaServiceImpl implements LimsYichangDiaochaService {
|
|
@Autowired
|
private ZhiliangBiaozhunGuanliZixiangService zhiliangBiaozhunGuanliZixiangService;
|
|
@Autowired
|
private LimsAdDiaochabiaoService limsAdDiaochabiaoService;
|
|
@Autowired
|
private LimsOosOotDiaochabiaoService limsOosOotDiaochabiaoService;
|
|
@Autowired
|
private LimsFlowTemplateResolver limsFlowTemplateResolver;
|
|
@Autowired
|
private TaskApi taskApi;
|
|
@Override
|
public void createIfNeeded(LimsJianyanXiangEntity row, LimsJianyanResultItem item) {
|
if (row == null || item == null) {
|
return;
|
}
|
YichangDiaochaLeixing t = YichangDiaochaLeixing.fromCode(item.getYichangDiaochaLeixing());
|
if (t == null || !t.isInvestigation()) {
|
return;
|
}
|
|
// 确定性反查:lims_jianyan_xiang.f_foreign_id = zixiang.f_id(= 表单检验项目id);
|
// zixiang.f_foreign_id = guanli.f_id(= 表单质量标准)。f_foreign_id 创建后稳定、报告流程不覆盖。
|
String jianyanXiangmuId = row.getForeignId();
|
String zhiliangBiaozhunId = null;
|
if (jianyanXiangmuId != null && !jianyanXiangmuId.isEmpty()) {
|
ZhiliangBiaozhunGuanliZixiangEntity zixiang =
|
zhiliangBiaozhunGuanliZixiangService.getById(jianyanXiangmuId);
|
if (zixiang != null) {
|
zhiliangBiaozhunId = zixiang.getForeignId();
|
}
|
}
|
|
if (t == YichangDiaochaLeixing.AD) {
|
launchAd(row, item, jianyanXiangmuId, zhiliangBiaozhunId, t);
|
} else {
|
// OOS / OOT:同一张表 + 同一模板,diaocha_fenlei 用枚举 code(oos/oot)
|
launchOosOot(row, item, jianyanXiangmuId, zhiliangBiaozhunId, t);
|
}
|
}
|
|
private void launchAd(LimsJianyanXiangEntity row, LimsJianyanResultItem item, String jianyanXiangmuId,
|
String zhiliangBiaozhunId, YichangDiaochaLeixing t) {
|
// 判重:自然键 = qingyan_liushuihao + jianyan_xiangmu_id;已存在则跳过,防重复发起
|
QueryWrapper<LimsAdDiaochabiaoEntity> dup = new QueryWrapper<>();
|
dup.eq("qingyan_liushuihao", row.getJianyanLiushuihao());
|
dup.eq("jianyan_xiangmu_id", jianyanXiangmuId);
|
dup.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
|
if (limsAdDiaochabiaoService.count(dup) > 0) {
|
return;
|
}
|
|
Date now = new Date();
|
Map<String, Object> formData = baseFormData(row, jianyanXiangmuId, zhiliangBiaozhunId, now);
|
formData.put("ad_diaocha_bianhao", nextBianhao("AD", now, true));
|
// 异常描述:AD 表单发起阶段必填,用检验结果数据拼一句客观描述,调查员可再改
|
formData.put("yichang_miaoshu", describeAnomaly(row, item));
|
launch(t, formData, row.getJianyanLiushuihao());
|
}
|
|
private void launchOosOot(LimsJianyanXiangEntity row, LimsJianyanResultItem item, String jianyanXiangmuId,
|
String zhiliangBiaozhunId, YichangDiaochaLeixing t) {
|
String fenlei = t.getCode(); // oos / oot
|
// 判重:自然键 = qingyan_liushuihao + jianyan_xiangmu_id + diaocha_fenlei
|
QueryWrapper<LimsOosOotDiaochabiaoEntity> dup = new QueryWrapper<>();
|
dup.eq("qingyan_liushuihao", row.getJianyanLiushuihao());
|
dup.eq("jianyan_xiangmu_id", jianyanXiangmuId);
|
dup.eq("diaocha_fenlei", fenlei);
|
dup.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
|
if (limsOosOotDiaochabiaoService.count(dup) > 0) {
|
return;
|
}
|
|
Date now = new Date();
|
Map<String, Object> formData = baseFormData(row, jianyanXiangmuId, zhiliangBiaozhunId, now);
|
formData.put("diaocha_fenlei", fenlei);
|
formData.put("diaocha_bianhao", nextBianhao(fenlei.toUpperCase(), now, false));
|
// 检验描述:OOS/OOT 表单发起阶段必填,同 AD 异常描述
|
formData.put("jianyan_miaoshu", describeAnomaly(row, item));
|
launch(t, formData, row.getJianyanLiushuihao());
|
}
|
|
/** 公共表单字段(key = 物理列名,AD/OOS/OOT 同源)。日期用 yyyy-MM-dd 字符串(与库内现有数据一致)。 */
|
private Map<String, Object> baseFormData(LimsJianyanXiangEntity row, String jianyanXiangmuId,
|
String zhiliangBiaozhunId, Date now) {
|
String today = new SimpleDateFormat("yyyy-MM-dd").format(now);
|
String currentUserId = UserProvider.getUser().getUserId();
|
Map<String, Object> m = new LinkedHashMap<>();
|
m.put("yangpin_leixing", row.getBizType());
|
m.put("yangpin_mingcheng", row.getChanpinMingcheng());
|
m.put("yangpin_id", row.getChanpinId());
|
m.put("pihao", row.getPihao());
|
m.put("qingyan_liushuihao", row.getJianyanLiushuihao());
|
m.put("zhiliang_biaozhun", zhiliangBiaozhunId);
|
m.put("jianyan_xiangmu", row.getJianyanXiangmuMingcheng());
|
m.put("jianyan_xiangmu_id", jianyanXiangmuId);
|
m.put("faxian_riqi", today);
|
m.put("jianyan_ren", currentUserId);
|
m.put("jianyan_riqi", today);
|
m.put("qingyandan_id", row.getQingyandanId());
|
return m;
|
}
|
|
/**
|
* 异常描述 / 检验描述(表单发起阶段必填):用 检验项目 + 本次检验结果 + 标准规定 + 检验结论
|
* 拼一句客观描述,调查员可在表单里再修改。结果/结论取自本次录入 item,标准/项目取自检验项 row。
|
*/
|
private String describeAnomaly(LimsJianyanXiangEntity row, LimsJianyanResultItem item) {
|
String xiangmu = safe(row.getJianyanXiangmuMingcheng());
|
String jieguo = safe(item.getJianyanJieguo());
|
String biaozhun = safe(row.getBiaozhunGuiding());
|
String jielun = jielunLabel(item.getJianyanJielun());
|
return "检验项目【" + xiangmu + "】检验结果【" + jieguo + "】,标准规定【" + biaozhun + "】,检验结论【" + jielun + "】。";
|
}
|
|
private static String safe(String s) {
|
return s == null ? "" : s;
|
}
|
|
/** 检验结论 code → 中文 label;空 / 未知 code 不抛异常(返回原值或空) */
|
private static String jielunLabel(String code) {
|
if (code == null || code.isEmpty()) {
|
return "";
|
}
|
try {
|
return JianyanJielun.fromCode(code).getLabel();
|
} catch (Exception e) {
|
return code;
|
}
|
}
|
|
/** 解析 templateId → 以当前登录用户名义 launchFlow → 校验返回;失败抛异常(交 submit 收集为发起失败)。 */
|
private void launch(YichangDiaochaLeixing t, Map<String, Object> formData, String liushuihao) {
|
String enCode = t.getFlowTemplateEnCode();
|
String templateId = limsFlowTemplateResolver.resolveTemplateId(enCode);
|
if (templateId == null || templateId.isEmpty()) {
|
throw new RuntimeException("未找到流程模板(enCode=" + enCode + "),无法发起 " + t.getCode() + " 调查流程");
|
}
|
FlowModel model = new FlowModel();
|
model.setTemplateId(templateId);
|
model.setUserIds(Collections.singletonList(UserProvider.getUser().getUserId()));
|
model.setFormDataList(Collections.singletonList(formData));
|
// hasPermission 默认 false:两模板 visibleType=1 全局可发起,不做发起权限过滤
|
ActionResult result = taskApi.launchFlow(model);
|
// 成功判定用平台常量 ActionResultCode.SUCCESS(与 VisualdevModelDataController 发起后判定一致);
|
// 不能硬编码 "200"——launchFlow 成功返回的 code 是 SUCCESS 码、msg 为"提交成功,请耐心等待",并非 "200"。
|
if (result == null || !ActionResultCode.SUCCESS.getCode().equals(result.getCode())) {
|
throw new RuntimeException("发起 " + t.getCode() + " 调查流程失败(流水号=" + liushuihao + "):"
|
+ (result == null ? "无返回" : result.getMsg()));
|
}
|
}
|
|
/**
|
* 生成"前缀+yyyyMMdd+3位日内流水"编号;流水 = 当天该前缀已有行数 + 1。
|
* isAd=true 查 lims_ad_diaochabiao.ad_diaocha_bianhao,否则查 lims_oos_oot_diaochabiao.diaocha_bianhao。
|
* LIMS 单据量低,并发碰撞可忽略;真正的重复由判重自然键拦截。
|
*/
|
private String nextBianhao(String prefix, Date now, boolean isAd) {
|
String head = prefix + new SimpleDateFormat("yyyy").format(now);
|
long seq;
|
if (isAd) {
|
QueryWrapper<LimsAdDiaochabiaoEntity> w = new QueryWrapper<>();
|
w.likeRight("ad_diaocha_bianhao", head);
|
seq = limsAdDiaochabiaoService.count(w) + 1;
|
} else {
|
QueryWrapper<LimsOosOotDiaochabiaoEntity> w = new QueryWrapper<>();
|
w.likeRight("diaocha_bianhao", head);
|
seq = limsOosOotDiaochabiaoService.count(w) + 1;
|
}
|
return String.format("%s%04d", head, seq);
|
}
|
}
|