package jnpf.limsService.impl;
|
|
import jnpf.audit.sdk.annotation.AuditLog;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import jnpf.base.service.SuperServiceImpl;
|
import jnpf.exception.DataException;
|
import jnpf.limsEntity.BizEnabledEnum;
|
import jnpf.limsEntity.ZhiliangBiaozhunGuanliEntity;
|
import jnpf.limsEntity.ZhiliangBiaozhunGuanliZixiangEntity;
|
import jnpf.limsMapper.ZhiliangBiaozhunGuanliMapper;
|
import jnpf.limsService.ZhiliangBiaozhunGuanliService;
|
import jnpf.limsService.ZhiliangBiaozhunGuanliZixiangService;
|
import jnpf.util.RandomUtil;
|
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.util.ArrayList;
|
import java.util.Date;
|
import java.util.List;
|
import java.util.Map;
|
|
@Service
|
public class ZhiliangBiaozhunGuanliServiceImpl
|
extends SuperServiceImpl<ZhiliangBiaozhunGuanliMapper, ZhiliangBiaozhunGuanliEntity>
|
implements ZhiliangBiaozhunGuanliService {
|
|
@Autowired
|
private ZhiliangBiaozhunGuanliZixiangService zhiliangBiaozhunGuanliZixiangService;
|
|
/** copyProperties 时统一忽略的系统/主键字段 */
|
private static final String[] MAIN_IGNORE = {
|
"id", "tenantId",
|
"creatorUserId", "creatorTime", "lastModifyUserId", "lastModifyTime",
|
"deleteMark", "deleteTime", "deleteUserId"
|
};
|
|
private static final String[] ZIXIANG_IGNORE = {
|
"id", "foreignId", "tenantId",
|
"deleteMark", "deleteTime", "deleteUserId"
|
};
|
|
@Override
|
public ZhiliangBiaozhunGuanliEntity findByYangpinId(String yangpinId) {
|
QueryWrapper<ZhiliangBiaozhunGuanliEntity> wrapper = new QueryWrapper<>();
|
wrapper.eq("yangpin_id", yangpinId);
|
wrapper.orderByDesc("f_id");
|
wrapper.last("LIMIT 1");
|
return this.getOne(wrapper);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
@AuditLog(action = "VERSION_UPGRADE", label = "质量标准版本升级", bizType = "ZHILIANG_BIAOZHUN",
|
bizCodeExpr = "#result ?: ''", targetTable = "zhiliang_biaozhun_guanli",
|
targetIdExpr = "#result", diff = true,
|
entityClass = ZhiliangBiaozhunGuanliEntity.class)
|
public String versionUpgrade(Map<String, Object> formData) {
|
if (formData == null || formData.isEmpty()) {
|
throw new DataException("入参不能为空");
|
}
|
|
// 路由复用:id 为空 = 新建场景(实际写入由 jnpf 在线表单完成),直接放行
|
// id 有值 = 版本升级场景,需要为旧数据生成历史快照
|
//
|
// 版本升级流程:jnpf 表单的 beforeSubmit 钩子先调用本接口,
|
// 我们把当前 DB 中的源记录整份复制成一条 biz_enabled=disabled 的历史快照行;
|
// 接口返回成功后 jnpf 才执行它原生的 UPDATE,把源行(同一 f_id)更新成表单里
|
// 用户填写的"新版本数据"。
|
// 因此:本方法 INSERT 的那条新行 = 历史快照(旧数据);
|
// 源行(被 jnpf 后续 UPDATE)= 升级后的当前活跃版本。
|
String sourceId = asString(formData.get("id"));
|
if (sourceId == null || sourceId.isEmpty()) {
|
return null;
|
}
|
|
// 1. 用 id 查源主表(当前在 DB 里的旧数据)
|
ZhiliangBiaozhunGuanliEntity source = this.getById(sourceId);
|
if (source == null) {
|
throw new DataException("未找到对应的质量标准记录(id=" + sourceId + ")");
|
}
|
|
// 1.1 校验前端传入的 biaozhun_banben 在 (yangpin_id, biaozhun_bianhao) 维度下是否唯一
|
validateBiaozhunBanbenUnique(formData, source);
|
|
// 2. 查源记录的子表项
|
List<ZhiliangBiaozhunGuanliZixiangEntity> sourceZixiangList =
|
zhiliangBiaozhunGuanliZixiangService.listByForeignId(sourceId);
|
|
// 3. 把源主表整体复制成"历史快照"行:新 f_id、biz_enabled=disabled
|
String historicalSnapshotId = RandomUtil.uuId();
|
ZhiliangBiaozhunGuanliEntity historicalSnapshot = new ZhiliangBiaozhunGuanliEntity();
|
BeanUtils.copyProperties(source, historicalSnapshot, MAIN_IGNORE);
|
historicalSnapshot.setId(historicalSnapshotId);
|
historicalSnapshot.setBizEnabled(BizEnabledEnum.DISABLED.getCode());
|
// 兜底:如果 MetaObjectHandler 没生效,至少 creatorTime 有值
|
historicalSnapshot.setCreatorTime(new Date());
|
|
this.save(historicalSnapshot);
|
|
// 4. 复制源子表项到历史快照下:每条新 f_id,f_foreign_id 指向快照主表 f_id
|
if (sourceZixiangList != null && !sourceZixiangList.isEmpty()) {
|
List<ZhiliangBiaozhunGuanliZixiangEntity> historicalZixiangList = new ArrayList<>(sourceZixiangList.size());
|
for (ZhiliangBiaozhunGuanliZixiangEntity src : sourceZixiangList) {
|
ZhiliangBiaozhunGuanliZixiangEntity copy = new ZhiliangBiaozhunGuanliZixiangEntity();
|
BeanUtils.copyProperties(src, copy, ZIXIANG_IGNORE);
|
copy.setId(RandomUtil.uuId());
|
copy.setForeignId(historicalSnapshotId);
|
historicalZixiangList.add(copy);
|
}
|
zhiliangBiaozhunGuanliZixiangService.saveBatch(historicalZixiangList);
|
}
|
|
return historicalSnapshotId;
|
}
|
|
private static String asString(Object v) {
|
return v == null ? null : v.toString();
|
}
|
|
/**
|
* 仅做前端拦截用:校验 formData 里的 biaozhun_banben 在同一
|
* (yangpin_id, biaozhun_bianhao) 维度下是否已存在 —— 不同标准编号下的版本号是隔离的,
|
* 不应跨标准互相判重。yangpin_id 与 biaozhun_bianhao 都取自 DB 源记录,
|
* 避免前端篡改。任一值缺失则跳过校验。
|
*/
|
private void validateBiaozhunBanbenUnique(Map<String, Object> formData,
|
ZhiliangBiaozhunGuanliEntity source) {
|
String biaozhunBanben = asString(formData.get("biaozhun_banben"));
|
if (biaozhunBanben == null || biaozhunBanben.isEmpty()) {
|
return;
|
}
|
String yangpinId = source.getYangpinId();
|
String biaozhunBianhao = source.getBiaozhunBianhao();
|
if (yangpinId == null || yangpinId.isEmpty()
|
|| biaozhunBianhao == null || biaozhunBianhao.isEmpty()) {
|
return;
|
}
|
QueryWrapper<ZhiliangBiaozhunGuanliEntity> w = new QueryWrapper<>();
|
w.eq("yangpin_id", yangpinId);
|
w.eq("biaozhun_bianhao", biaozhunBianhao);
|
w.eq("biaozhun_banben", biaozhunBanben);
|
w.and(q -> q.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
|
// 排除源记录自身:upgrade 场景下新记录是从源复制的,源不应与自己冲突
|
if (source.getId() != null && !source.getId().isEmpty()) {
|
w.ne("f_id", source.getId());
|
}
|
if (this.count(w) > 0) {
|
throw new DataException("该样品的标准编号【" + biaozhunBianhao
|
+ "】下已存在版本号【" + biaozhunBanben + "】,请使用其他版本号");
|
}
|
}
|
}
|