package jnpf.elnService.impl;
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import jnpf.base.UserInfo;
|
import jnpf.database.util.TenantDataSourceUtil;
|
import jnpf.elnEntity.runtime.ElnRecordEntity;
|
import jnpf.elnEntity.runtime.ElnRecordFieldValueEntity;
|
import jnpf.elnEntity.runtime.ElnRecordFormulaCalculationResult;
|
import jnpf.elnEntity.runtime.ElnRecordRepeatValueEntity;
|
import jnpf.elnEntity.runtime.ElnRecordForms;
|
import jnpf.elnEntity.runtime.ElnRecordRevisionEntity;
|
import jnpf.elnEntity.runtime.ElnRecordVos;
|
import jnpf.elnMapper.ElnRecordFieldValueMapper;
|
import jnpf.elnMapper.ElnRecordMapper;
|
import jnpf.elnMapper.ElnRecordRepeatValueMapper;
|
import jnpf.elnMapper.ElnRecordRevisionMapper;
|
import jnpf.elnService.ElnTestWorkItemSnapshotProvider;
|
import jnpf.elnService.ElnRecordFormulaCalculationService;
|
import jnpf.elnService.ElnRecordRecalculationService;
|
import jnpf.exception.DataException;
|
import jnpf.lims.api.model.TestWorkItemSnapshotBatch;
|
import jnpf.lims.api.model.TestWorkItemSnapshot;
|
import jnpf.model.tenant.TenantVO;
|
import jnpf.util.UserProvider;
|
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.util.Collections;
|
import java.util.List;
|
|
@Service
|
public class ElnRecordRecalculationServiceImpl
|
implements ElnRecordRecalculationService {
|
|
private final ElnRecordMapper recordMapper;
|
private final ElnRecordRevisionMapper revisionMapper;
|
private final ElnRecordFieldValueMapper valueMapper;
|
private final ElnRecordRepeatValueMapper repeatValueMapper;
|
private final ElnTestWorkItemSnapshotProvider taskProvider;
|
private final ElnRecordFormulaCalculationService calculationService;
|
private final CurrentUserProvider currentUserProvider;
|
|
@Autowired
|
public ElnRecordRecalculationServiceImpl(
|
ElnRecordMapper recordMapper,
|
ElnRecordRevisionMapper revisionMapper,
|
ElnRecordFieldValueMapper valueMapper,
|
ElnRecordRepeatValueMapper repeatValueMapper,
|
ElnTestWorkItemSnapshotProvider taskProvider,
|
ElnRecordFormulaCalculationService calculationService) {
|
this(recordMapper, revisionMapper, valueMapper, repeatValueMapper, taskProvider,
|
calculationService, ElnRecordRecalculationServiceImpl::currentUser);
|
}
|
|
ElnRecordRecalculationServiceImpl(
|
ElnRecordMapper recordMapper,
|
ElnRecordRevisionMapper revisionMapper,
|
ElnRecordFieldValueMapper valueMapper,
|
ElnTestWorkItemSnapshotProvider taskProvider,
|
ElnRecordFormulaCalculationService calculationService,
|
CurrentUserProvider currentUserProvider) {
|
this(recordMapper, revisionMapper, valueMapper, null, taskProvider,
|
calculationService, currentUserProvider);
|
}
|
|
ElnRecordRecalculationServiceImpl(
|
ElnRecordMapper recordMapper,
|
ElnRecordRevisionMapper revisionMapper,
|
ElnRecordFieldValueMapper valueMapper,
|
ElnRecordRepeatValueMapper repeatValueMapper,
|
ElnTestWorkItemSnapshotProvider taskProvider,
|
ElnRecordFormulaCalculationService calculationService,
|
CurrentUserProvider currentUserProvider) {
|
this.recordMapper = recordMapper;
|
this.revisionMapper = revisionMapper;
|
this.valueMapper = valueMapper;
|
this.repeatValueMapper = repeatValueMapper;
|
this.taskProvider = taskProvider;
|
this.calculationService = calculationService;
|
this.currentUserProvider = currentUserProvider;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public ElnRecordVos.Recalculated recalculateAll(
|
String recordId, ElnRecordForms.Recalculate command) {
|
String actualRecordId = required(recordId, "电子记录不能为空");
|
String operationCode = required(
|
command == null ? null : command.getOperationCode(), "计算操作码不能为空");
|
Integer expectedVersion = command == null ? null : command.getExpectedRecordVersion();
|
if (expectedVersion == null || expectedVersion < 0) {
|
throw new DataException("电子记录版本不能为空");
|
}
|
UserContext user = currentUserProvider.get();
|
ElnRecordEntity record = recordMapper.selectOne(
|
Wrappers.<ElnRecordEntity>lambdaQuery()
|
.eq(ElnRecordEntity::getFTenantId, user.tenantId)
|
.eq(ElnRecordEntity::getId, actualRecordId)
|
.and(q -> q.isNull(ElnRecordEntity::getFDeleteMark)
|
.or().eq(ElnRecordEntity::getFDeleteMark, 0)).last("limit 1"));
|
if (record == null || !StringUtils.hasText(record.getDangqianXiudingId())) {
|
throw new DataException("电子记录不存在或当前修订无效");
|
}
|
ElnRecordRevisionEntity revision = revisionMapper.selectOne(
|
Wrappers.<ElnRecordRevisionEntity>lambdaQuery()
|
.eq(ElnRecordRevisionEntity::getFTenantId, user.tenantId)
|
.eq(ElnRecordRevisionEntity::getId, record.getDangqianXiudingId())
|
.eq(ElnRecordRevisionEntity::getDianziJiluId, record.getId())
|
.and(q -> q.isNull(ElnRecordRevisionEntity::getFDeleteMark)
|
.or().eq(ElnRecordRevisionEntity::getFDeleteMark, 0)).last("limit 1"));
|
if (revision == null || !"DRAFT".equals(revision.getBizStatus())) {
|
throw new DataException("电子记录当前修订不允许重新计算");
|
}
|
assertTaskAccess(record);
|
if (!expectedVersion.equals(record.getFVersion())
|
|| recordMapper.advanceVersion(user.tenantId, record.getId(),
|
expectedVersion, user.userId) != 1) {
|
throw new DataException("电子记录已被其他操作更新");
|
}
|
List<ElnRecordFieldValueEntity> values = valueMapper.selectList(
|
Wrappers.<ElnRecordFieldValueEntity>lambdaQuery()
|
.eq(ElnRecordFieldValueEntity::getFTenantId, user.tenantId)
|
.eq(ElnRecordFieldValueEntity::getDianziJiluId, record.getId())
|
.eq(ElnRecordFieldValueEntity::getXiudingId, revision.getId())
|
.and(q -> q.isNull(ElnRecordFieldValueEntity::getFDeleteMark)
|
.or().eq(ElnRecordFieldValueEntity::getFDeleteMark, 0)));
|
ElnRecordFormulaCalculationResult calculated = calculationService.recalculateAllWithRepeats(
|
user.tenantId, record, revision, values, operationCode, user.userId);
|
for (ElnRecordFieldValueEntity value : calculated.getFieldValues()) {
|
if (valueMapper.updateById(value) != 1) {
|
throw new DataException("公式结果字段保存冲突");
|
}
|
}
|
for (ElnRecordRepeatValueEntity value : calculated.getRepeatValues()) {
|
if (repeatValueMapper == null || repeatValueMapper.updateById(value) != 1) {
|
throw new DataException("重复公式结果字段保存冲突");
|
}
|
}
|
return result(record, revision, operationCode, expectedVersion + 1, calculated);
|
}
|
|
private void assertTaskAccess(ElnRecordEntity record) {
|
TestWorkItemSnapshotBatch batch = taskProvider.resolve(
|
Collections.singletonList(record.getJianyanXiangId()),
|
Collections.<String>emptyList());
|
if (batch == null || batch.getItems() == null || batch.getItems().size() != 1) {
|
throw new DataException("LIMS 检验任务快照返回无效");
|
}
|
TestWorkItemSnapshot item = batch.getItems().get(0);
|
if (item == null || !record.getJianyanXiangId().equals(item.getTestWorkItemId())
|
|| !"SUCCESS".equals(item.getOutcomeCode())) {
|
throw new DataException(item != null && StringUtils.hasText(item.getReason())
|
? item.getReason() : "当前用户或检验项状态不允许重新计算电子记录");
|
}
|
}
|
|
private static ElnRecordVos.Recalculated result(
|
ElnRecordEntity record, ElnRecordRevisionEntity revision,
|
String operationCode, int recordVersion,
|
ElnRecordFormulaCalculationResult calculated) {
|
ElnRecordVos.Recalculated result = new ElnRecordVos.Recalculated();
|
result.setRecordId(record.getId());
|
result.setRevisionId(revision.getId());
|
result.setOperationCode(operationCode);
|
result.setRecordVersion(recordVersion);
|
List<String> statuses = new java.util.ArrayList<>();
|
for (ElnRecordFieldValueEntity value : calculated.getFieldValues()) {
|
statuses.add(value.getJisuanZhuangtai());
|
}
|
for (ElnRecordRepeatValueEntity value : calculated.getRepeatValues()) {
|
statuses.add(value.getJisuanZhuangtai());
|
}
|
for (String status : statuses) {
|
if ("SUCCESS".equals(status)) {
|
result.setSuccessCount(result.getSuccessCount() + 1);
|
} else if ("MISSING_INPUT".equals(status)) {
|
result.setMissingInputCount(result.getMissingInputCount() + 1);
|
} else {
|
result.setErrorCount(result.getErrorCount() + 1);
|
}
|
}
|
return result;
|
}
|
|
private static String required(String value, String message) {
|
if (!StringUtils.hasText(value)) throw new DataException(message);
|
return value.trim();
|
}
|
|
private static UserContext currentUser() {
|
UserInfo user = UserProvider.getUser();
|
if (user == null || !StringUtils.hasText(user.getUserId())) {
|
throw new DataException("当前登录用户无效");
|
}
|
TenantVO routed = TenantDataSourceUtil.getTenantInfo();
|
String tenantId = routed != null && StringUtils.hasText(routed.getEnCode())
|
? routed.getEnCode().trim() : user.getTenantId();
|
return new UserContext(StringUtils.hasText(tenantId) ? tenantId.trim() : "0",
|
user.getUserId().trim());
|
}
|
|
@FunctionalInterface
|
interface CurrentUserProvider {
|
UserContext get();
|
}
|
|
static final class UserContext {
|
private final String tenantId;
|
private final String userId;
|
|
UserContext(String tenantId, String userId) {
|
this.tenantId = tenantId;
|
this.userId = userId;
|
}
|
}
|
}
|