141 lines
6.1 KiB
Java
141 lines
6.1 KiB
Java
|
|
package com.labelsys.backend.service;
|
||
|
|
|
||
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||
|
|
import com.labelsys.backend.common.ResultCode;
|
||
|
|
import com.labelsys.backend.common.exception.BusinessException;
|
||
|
|
import com.labelsys.backend.context.LoginUser;
|
||
|
|
import com.labelsys.backend.dto.request.MergeReviewResultRequest;
|
||
|
|
import com.labelsys.backend.dto.response.MergeReviewResultResponse;
|
||
|
|
import com.labelsys.backend.entity.AnnotationResult;
|
||
|
|
import com.labelsys.backend.entity.AnnotationResultHistory;
|
||
|
|
import com.labelsys.backend.enums.QaContentStorageMode;
|
||
|
|
import com.labelsys.backend.enums.UserPosition;
|
||
|
|
import com.labelsys.backend.mapper.AnnotationResultHistoryMapper;
|
||
|
|
import com.labelsys.backend.mapper.AnnotationResultMapper;
|
||
|
|
import com.labelsys.backend.util.IdGenerator;
|
||
|
|
import java.time.Duration;
|
||
|
|
import java.time.LocalDateTime;
|
||
|
|
import java.util.List;
|
||
|
|
import lombok.RequiredArgsConstructor;
|
||
|
|
import lombok.extern.slf4j.Slf4j;
|
||
|
|
import org.springframework.beans.factory.annotation.Value;
|
||
|
|
import org.springframework.stereotype.Service;
|
||
|
|
import org.springframework.transaction.annotation.Transactional;
|
||
|
|
|
||
|
|
@Slf4j
|
||
|
|
@Service
|
||
|
|
@RequiredArgsConstructor
|
||
|
|
public class AnnotationResultArchiveService {
|
||
|
|
|
||
|
|
private static final String MANUAL_ARCHIVE_REASON = "MANUAL_REVIEW";
|
||
|
|
|
||
|
|
private final AnnotationResultMapper annotationResultMapper;
|
||
|
|
private final AnnotationResultHistoryMapper annotationResultHistoryMapper;
|
||
|
|
@Value("${labelsys.annotation.auto-archive-timeout:PT2H}")
|
||
|
|
private Duration autoArchiveTimeout;
|
||
|
|
|
||
|
|
@Transactional
|
||
|
|
public MergeReviewResultResponse mergeReview(LoginUser currentUser, Long resultId, MergeReviewResultRequest request) {
|
||
|
|
assertReviewer(currentUser);
|
||
|
|
AnnotationResult result = annotationResultMapper.findActiveByIdAndCompanyId(resultId, currentUser.companyId());
|
||
|
|
if (result == null) {
|
||
|
|
throw new BusinessException(ResultCode.NOT_FOUND, "运行态结果不存在");
|
||
|
|
}
|
||
|
|
|
||
|
|
LocalDateTime archivedAt = LocalDateTime.now();
|
||
|
|
AnnotationResultHistory history = AnnotationResultHistory.builder()
|
||
|
|
.id(IdGenerator.nextId())
|
||
|
|
.companyId(result.getCompanyId())
|
||
|
|
.creatorId(result.getCreatorId())
|
||
|
|
.creatorRole(result.getCreatorRole())
|
||
|
|
.sourceResultId(result.getId())
|
||
|
|
.taskId(result.getTaskId())
|
||
|
|
.resourceId(result.getResourceId())
|
||
|
|
.qaContentJson(request.qaContentJson())
|
||
|
|
.qaContentStorageMode(resolveStorageMode(result))
|
||
|
|
.qaContentFilePath(result.getQaContentFilePath())
|
||
|
|
.archiveReason(MANUAL_ARCHIVE_REASON)
|
||
|
|
.archivedBy(currentUser.userId())
|
||
|
|
.archivedAt(archivedAt)
|
||
|
|
.build();
|
||
|
|
annotationResultHistoryMapper.insert(history);
|
||
|
|
|
||
|
|
int updated = annotationResultMapper.markArchived(
|
||
|
|
result.getId(),
|
||
|
|
currentUser.companyId(),
|
||
|
|
currentUser.userId(),
|
||
|
|
request.reviewComment(),
|
||
|
|
archivedAt);
|
||
|
|
if (updated == 0) {
|
||
|
|
throw new BusinessException(ResultCode.CONFLICT, "结果已被其他操作处理");
|
||
|
|
}
|
||
|
|
|
||
|
|
log.info("merged review result, companyId={}, reviewerId={}, resultId={}, historyId={}",
|
||
|
|
currentUser.companyId(), currentUser.userId(), resultId, history.getId());
|
||
|
|
return new MergeReviewResultResponse(resultId, history.getId(), MANUAL_ARCHIVE_REASON, archivedAt);
|
||
|
|
}
|
||
|
|
|
||
|
|
@Transactional
|
||
|
|
public int autoArchiveEligibleResults() {
|
||
|
|
LocalDateTime cutoff = LocalDateTime.now().minus(autoArchiveTimeout);
|
||
|
|
List<AnnotationResult> results = annotationResultMapper.selectList(new LambdaQueryWrapper<AnnotationResult>()
|
||
|
|
.eq(AnnotationResult::getIsDeleted, false)
|
||
|
|
.eq(AnnotationResult::getRequiresManualReview, false)
|
||
|
|
.lt(AnnotationResult::getCreatedAt, cutoff));
|
||
|
|
int archivedCount = 0;
|
||
|
|
for (AnnotationResult result : results) {
|
||
|
|
if (archiveRuntimeResult(result, null, "AUTO_ARCHIVE", null) != null) {
|
||
|
|
archivedCount++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return archivedCount;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void assertReviewer(LoginUser currentUser) {
|
||
|
|
if (currentUser.position() != UserPosition.REVIEWER && currentUser.position() != UserPosition.ADMIN) {
|
||
|
|
throw new BusinessException(ResultCode.FORBIDDEN, "当前用户没有审核权限");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private String resolveStorageMode(AnnotationResult result) {
|
||
|
|
if (QaContentStorageMode.isValid(result.getQaContentStorageMode())) {
|
||
|
|
return result.getQaContentStorageMode();
|
||
|
|
}
|
||
|
|
return QaContentStorageMode.INLINE.name();
|
||
|
|
}
|
||
|
|
|
||
|
|
private MergeReviewResultResponse archiveRuntimeResult(AnnotationResult result,
|
||
|
|
Long reviewerId,
|
||
|
|
String archiveReason,
|
||
|
|
String reviewComment) {
|
||
|
|
LocalDateTime archivedAt = LocalDateTime.now();
|
||
|
|
AnnotationResultHistory history = AnnotationResultHistory.builder()
|
||
|
|
.id(IdGenerator.nextId())
|
||
|
|
.companyId(result.getCompanyId())
|
||
|
|
.creatorId(result.getCreatorId())
|
||
|
|
.creatorRole(result.getCreatorRole())
|
||
|
|
.sourceResultId(result.getId())
|
||
|
|
.taskId(result.getTaskId())
|
||
|
|
.resourceId(result.getResourceId())
|
||
|
|
.qaContentJson(result.getQaContentJson())
|
||
|
|
.qaContentStorageMode(resolveStorageMode(result))
|
||
|
|
.qaContentFilePath(result.getQaContentFilePath())
|
||
|
|
.archiveReason(archiveReason)
|
||
|
|
.archivedBy(reviewerId)
|
||
|
|
.archivedAt(archivedAt)
|
||
|
|
.build();
|
||
|
|
annotationResultHistoryMapper.insert(history);
|
||
|
|
|
||
|
|
int updated = annotationResultMapper.markArchived(
|
||
|
|
result.getId(),
|
||
|
|
result.getCompanyId(),
|
||
|
|
reviewerId,
|
||
|
|
reviewComment,
|
||
|
|
archivedAt);
|
||
|
|
if (updated == 0) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
return new MergeReviewResultResponse(result.getId(), history.getId(), archiveReason, archivedAt);
|
||
|
|
}
|
||
|
|
}
|