package com.emergencyrepair.business.service;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.emergencyrepair.business.dto.Requests;
|
import com.emergencyrepair.business.entity.Acceptance;
|
import com.emergencyrepair.business.entity.CompletionInfo;
|
import com.emergencyrepair.business.entity.Contractor;
|
import com.emergencyrepair.business.entity.Fault;
|
import com.emergencyrepair.business.entity.TeamMajor;
|
import com.emergencyrepair.business.entity.WorkOrder;
|
import com.emergencyrepair.business.mapper.AcceptanceMapper;
|
import com.emergencyrepair.business.mapper.CompletionInfoMapper;
|
import com.emergencyrepair.business.mapper.ContractorMapper;
|
import com.emergencyrepair.business.mapper.FaultMapper;
|
import com.emergencyrepair.business.mapper.TeamMajorMapper;
|
import com.emergencyrepair.business.mapper.WorkOrderMapper;
|
import com.emergencyrepair.common.BusinessException;
|
import com.emergencyrepair.common.StatusConstants;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.StringUtils;
|
|
import java.time.LocalDate;
|
import java.time.LocalDateTime;
|
import java.time.format.DateTimeFormatter;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.LinkedHashMap;
|
import java.util.LinkedHashSet;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Set;
|
import java.util.function.Function;
|
import java.util.stream.Collectors;
|
|
@Service
|
@RequiredArgsConstructor
|
public class BusinessService {
|
private static final DateTimeFormatter FAULT_DATE_FORMAT = DateTimeFormatter.ofPattern("yyMMdd");
|
private static final String FAULT_CODE_PREFIX = "\u6f5c1\u57fa-";
|
private static final Object FAULT_CODE_LOCK = new Object();
|
private final FaultMapper faultMapper;
|
private final TeamMajorMapper teamMajorMapper;
|
private final WorkOrderMapper workOrderMapper;
|
private final ContractorMapper contractorMapper;
|
private final CompletionInfoMapper completionInfoMapper;
|
private final AcceptanceMapper acceptanceMapper;
|
private final ObjectMapper objectMapper;
|
|
public List<Fault> listFaults(String status, String keyword) {
|
return listFaults(status, keyword, null, null, null, null, null, null, null, null, null);
|
}
|
|
public List<Fault> listFaults(String status, String keyword, String xNo, String teamMajor,
|
String engineeringMajor, String reportUnit, String owner,
|
LocalDate reportDateStart, LocalDate reportDateEnd,
|
String contractorName, String faultNature) {
|
return faultMapper.selectList(faultQuery(status, keyword, xNo, teamMajor, engineeringMajor,
|
reportUnit, owner, reportDateStart, reportDateEnd, contractorName, faultNature));
|
}
|
|
public Page<Fault> pageFaults(String status, String keyword, String xNo, String teamMajor,
|
String engineeringMajor, String reportUnit, String owner,
|
LocalDate reportDateStart, LocalDate reportDateEnd,
|
String contractorName, String faultNature,
|
long current, long size) {
|
long safeCurrent = Math.max(current, 1L);
|
long safeSize = Math.min(Math.max(size, 1L), 200L);
|
return faultMapper.selectPage(new Page<>(safeCurrent, safeSize),
|
faultQuery(status, keyword, xNo, teamMajor, engineeringMajor, reportUnit, owner,
|
reportDateStart, reportDateEnd, contractorName, faultNature));
|
}
|
|
private LambdaQueryWrapper<Fault> faultQuery(String status, String keyword) {
|
return faultQuery(status, keyword, null, null, null, null, null, null, null, null, null);
|
}
|
|
private LambdaQueryWrapper<Fault> faultQuery(String status, String keyword, String xNo,
|
String teamMajor, String engineeringMajor,
|
String reportUnit, String owner,
|
LocalDate reportDateStart, LocalDate reportDateEnd,
|
String contractorName, String faultNature) {
|
LambdaQueryWrapper<Fault> query = Wrappers.lambdaQuery();
|
if (StringUtils.hasText(status)) {
|
query.in(Fault::getTaskStatus, Arrays.asList(status.split(",")));
|
}
|
if (StringUtils.hasText(keyword)) {
|
query.and(wrapper -> wrapper
|
.like(Fault::getFaultCode, keyword)
|
.or().like(Fault::getEquipmentName, keyword)
|
.or().like(Fault::getEngineeringNameDesc, keyword));
|
}
|
if (StringUtils.hasText(xNo)) {
|
query.eq(Fault::getXNo, xNo.trim());
|
}
|
if (StringUtils.hasText(teamMajor)) {
|
query.eq(Fault::getTeamMajor, teamMajor);
|
}
|
if (StringUtils.hasText(engineeringMajor)) {
|
query.eq(Fault::getEngineeringMajor, engineeringMajor);
|
}
|
if (StringUtils.hasText(reportUnit)) {
|
query.like(Fault::getReportUnit, reportUnit.trim());
|
}
|
if (StringUtils.hasText(owner)) {
|
query.like(Fault::getOwner, owner.trim());
|
}
|
if (reportDateStart != null) {
|
query.ge(Fault::getReportDate, reportDateStart);
|
}
|
if (reportDateEnd != null) {
|
query.le(Fault::getReportDate, reportDateEnd);
|
}
|
if (StringUtils.hasText(contractorName)) {
|
query.like(Fault::getContractorNames, contractorName.trim());
|
}
|
if (StringUtils.hasText(faultNature)) {
|
query.eq(Fault::getFaultNature, faultNature);
|
}
|
query.orderByDesc(Fault::getReportDate).orderByDesc(Fault::getCreateTime);
|
return query;
|
}
|
|
@Transactional
|
public Fault saveFault(Fault fault) {
|
if (fault == null) {
|
throw new BusinessException("故障信息不能为空");
|
}
|
LocalDateTime now = LocalDateTime.now();
|
normalizeEquipmentIds(fault);
|
normalizeParentSystemSeparators(fault);
|
fault.setUpdateTime(now);
|
if (fault.getId() == null) {
|
if (fault.getReportDate() == null) {
|
fault.setReportDate(LocalDate.now());
|
}
|
synchronized (FAULT_CODE_LOCK) {
|
fault.setFaultCode(generateFaultCode(fault));
|
fault.setTaskStatus(StatusConstants.Task.UNREPORTED);
|
fault.setCreateTime(now);
|
faultMapper.insert(fault);
|
}
|
} else {
|
Fault existing = requireFault(fault.getId());
|
if (!canEdit(existing)) {
|
throw new BusinessException("当前任务状态不允许修改");
|
}
|
// The fault code is generated once on create and never edited afterwards.
|
fault.setFaultCode(existing.getFaultCode());
|
if (!StringUtils.hasText(fault.getTaskStatus())) {
|
fault.setTaskStatus(existing.getTaskStatus());
|
}
|
faultMapper.updateById(fault);
|
}
|
return faultMapper.selectById(fault.getId());
|
}
|
|
/**
|
* Builds the fault code as: prefix + three digit X number + "/" + team major category
|
* + "-" + report date (yyMMdd) + "-" + three digit sequence.
|
* The sequence restarts at 001 for each X number + team major + report date.
|
*/
|
private String generateFaultCode(Fault fault) {
|
String xNo = normalizeXNo(fault.getXNo());
|
if (xNo == null) {
|
throw new BusinessException("请选择X号,格式为3位数字");
|
}
|
if (!StringUtils.hasText(fault.getTeamMajor())) {
|
throw new BusinessException("请选择T队专业");
|
}
|
TeamMajor teamMajor = teamMajorMapper.selectOne(Wrappers.<TeamMajor>lambdaQuery()
|
.eq(TeamMajor::getName, fault.getTeamMajor().trim())
|
.last("LIMIT 1"));
|
if (teamMajor == null) {
|
throw new BusinessException("T队专业未配置,请先在系统管理 > T队专业配置中维护:" + fault.getTeamMajor());
|
}
|
String category = teamMajor.getCategory() == null ? "" : teamMajor.getCategory().trim().toUpperCase();
|
if (!"A".equals(category) && !"B".equals(category)) {
|
throw new BusinessException("T队专业分类只能为A或B:" + fault.getTeamMajor());
|
}
|
String prefix = FAULT_CODE_PREFIX + xNo + "/" + category + "-" + fault.getReportDate().format(FAULT_DATE_FORMAT) + "-";
|
int next = 1;
|
for (Fault item : faultMapper.selectList(Wrappers.<Fault>lambdaQuery()
|
.likeRight(Fault::getFaultCode, prefix))) {
|
next = Math.max(next, parseFaultSequence(item.getFaultCode(), prefix) + 1);
|
}
|
return prefix + String.format("%03d", next);
|
}
|
|
private int parseFaultSequence(String faultCode, String prefix) {
|
if (faultCode == null || !faultCode.startsWith(prefix)) {
|
return 0;
|
}
|
String suffix = faultCode.substring(prefix.length());
|
if (suffix.length() < 3) {
|
return 0;
|
}
|
try {
|
return Integer.parseInt(suffix.substring(0, 3));
|
} catch (NumberFormatException ex) {
|
return 0;
|
}
|
}
|
|
private String normalizeXNo(String xNo) {
|
if (!StringUtils.hasText(xNo)) {
|
return null;
|
}
|
String digits = xNo.replaceAll("[^0-9]", "");
|
if (digits.isEmpty()) {
|
return null;
|
}
|
if (digits.length() > 3) {
|
digits = digits.substring(digits.length() - 3);
|
}
|
StringBuilder builder = new StringBuilder();
|
for (int i = digits.length(); i < 3; i++) {
|
builder.append('0');
|
}
|
return builder.append(digits).toString();
|
}
|
|
@Transactional
|
public void deleteFault(Long id) {
|
Fault fault = requireFault(id);
|
if (!StatusConstants.Task.UNREPORTED.equals(fault.getTaskStatus())
|
&& !StatusConstants.Task.RETURNED.equals(fault.getTaskStatus())) {
|
throw new BusinessException("仅未上报或上级打回的故障可以删除");
|
}
|
faultMapper.deleteById(id);
|
}
|
|
@Transactional
|
public void cancelFaults(Requests.CancelRequest request) {
|
if (request.getIds() == null || request.getIds().isEmpty()) {
|
throw new BusinessException("请选择故障");
|
}
|
if (!StringUtils.hasText(request.getReason())) {
|
throw new BusinessException("请填写销项理由");
|
}
|
String cancelledBy = StringUtils.hasText(request.getCancelledBy())
|
? request.getCancelledBy().trim() : "XCB助理";
|
for (Long id : request.getIds()) {
|
Fault fault = requireFault(id);
|
if (!StatusConstants.Task.REPORTED_XCB.equals(fault.getTaskStatus())
|
&& !StatusConstants.Task.RETURNED.equals(fault.getTaskStatus())) {
|
throw new BusinessException("故障 " + fault.getFaultCode() + " 当前状态不允许销项");
|
}
|
fault.setCancelReason(request.getReason().trim());
|
fault.setCancelledBy(cancelledBy);
|
fault.setCancelTime(LocalDateTime.now());
|
fault.setTaskStatus(StatusConstants.Task.CANCELLED);
|
fault.setUpdateTime(LocalDateTime.now());
|
faultMapper.updateById(fault);
|
}
|
}
|
|
@Transactional
|
public void reportFaults(List<Long> ids) {
|
for (Long id : ids) {
|
Fault fault = requireFault(id);
|
if (!StatusConstants.Task.UNREPORTED.equals(fault.getTaskStatus())) {
|
throw new BusinessException("故障 " + fault.getFaultCode() + " 不是未上报状态");
|
}
|
fault.setTaskStatus(StatusConstants.Task.REPORTED_XCB);
|
fault.setUpdateTime(LocalDateTime.now());
|
faultMapper.updateById(fault);
|
}
|
}
|
|
@Transactional
|
public void xcbReview(Requests.ReviewRequest request) {
|
if (request.getIds() == null || request.getIds().isEmpty()) {
|
throw new BusinessException("请选择故障");
|
}
|
if (request.getContractorIds() == null || request.getContractorIds().isEmpty()) {
|
throw new BusinessException("至少分配一个承修单位");
|
}
|
List<Contractor> contractors = contractorMapper.selectBatchIds(request.getContractorIds());
|
Map<Long, Contractor> contractorMap = contractors.stream()
|
.collect(Collectors.toMap(Contractor::getId, Function.identity()));
|
String contractorIds = request.getContractorIds().stream()
|
.map(String::valueOf)
|
.collect(Collectors.joining(","));
|
String contractorNames = request.getContractorIds().stream()
|
.map(contractorMap::get)
|
.filter(item -> item != null)
|
.map(Contractor::getName)
|
.collect(Collectors.joining("、"));
|
|
int index = 0;
|
for (Long id : request.getIds()) {
|
Fault fault = requireFault(id);
|
if (!StatusConstants.Task.REPORTED_XCB.equals(fault.getTaskStatus())
|
&& !StatusConstants.Task.RETURNED.equals(fault.getTaskStatus())) {
|
throw new BusinessException("故障 " + fault.getFaultCode() + " 当前状态不允许XCB助理审核");
|
}
|
index++;
|
fault.setContractorIds(contractorIds);
|
fault.setContractorNames(contractorNames);
|
fault.setTrackingTeam(request.getTrackingTeam());
|
fault.setRequestedFinishDate(request.getRequestedFinishDate());
|
fault.setEngineeringNo(buildEngineeringNo(fault, index));
|
fault.setTaskStatus(StatusConstants.Task.XCB_REVIEWED);
|
fault.setXcbReviewTime(LocalDateTime.now());
|
fault.setUpdateTime(LocalDateTime.now());
|
faultMapper.updateById(fault);
|
}
|
}
|
|
@Transactional
|
public void approve(Requests.ApprovalRequest request) {
|
if (request.getIds() == null || request.getIds().isEmpty()) {
|
throw new BusinessException("请选择故障");
|
}
|
boolean pass = "PASS".equalsIgnoreCase(request.getResult())
|
|| "通过".equals(request.getResult());
|
for (Long id : request.getIds()) {
|
Fault fault = requireFault(id);
|
LocalDateTime now = LocalDateTime.now();
|
switch (request.getStage()) {
|
case "CMB":
|
requireStatus(fault, StatusConstants.Task.XCB_REVIEWED, "CMB领导审批");
|
fault.setCmbOpinion(request.getOpinion());
|
fault.setCmbResult(pass ? "通过" : "不通过");
|
fault.setCmbTime(now);
|
fault.setTaskStatus(pass ? StatusConstants.Task.CMB_APPROVED : StatusConstants.Task.RETURNED);
|
break;
|
case "JCC_ASSISTANT":
|
requireStatus(fault, StatusConstants.Task.CMB_APPROVED, "JCC助理审批");
|
fault.setJccAssistantOpinion(request.getOpinion());
|
fault.setJccAssistantResult(pass ? "通过" : "不通过");
|
fault.setJccAssistantTime(now);
|
fault.setTaskStatus(pass ? StatusConstants.Task.JCC_ASSISTANT_APPROVED : StatusConstants.Task.RETURNED);
|
break;
|
case "JCC_DIRECTOR":
|
requireStatus(fault, StatusConstants.Task.JCC_ASSISTANT_APPROVED, "JCC处长审批");
|
fault.setJccDirectorOpinion(request.getOpinion());
|
fault.setJccDirectorResult(pass ? "通过" : "不通过");
|
fault.setJccDirectorTime(now);
|
fault.setTaskStatus(pass ? StatusConstants.Task.JCC_DIRECTOR_APPROVED : StatusConstants.Task.RETURNED);
|
break;
|
default:
|
throw new BusinessException("未知审批环节");
|
}
|
fault.setUpdateTime(now);
|
faultMapper.updateById(fault);
|
}
|
}
|
|
@Transactional
|
public List<WorkOrder> dispatch(Requests.DispatchRequest request) {
|
if (request.getFaultIds() == null || request.getFaultIds().isEmpty()) {
|
throw new BusinessException("请选择未派单故障");
|
}
|
List<WorkOrder> created = new ArrayList<>();
|
for (Long faultId : request.getFaultIds()) {
|
Fault fault = requireFault(faultId);
|
if (!StatusConstants.Task.JCC_DIRECTOR_APPROVED.equals(fault.getTaskStatus())) {
|
throw new BusinessException("故障 " + fault.getFaultCode() + " 未完成审批,不能派单");
|
}
|
List<Long> contractorIds = parseIds(fault.getContractorIds());
|
if (contractorIds.isEmpty()) {
|
throw new BusinessException("故障 " + fault.getFaultCode() + " 未分配承修单位");
|
}
|
long exists = workOrderMapper.selectCount(Wrappers.<WorkOrder>lambdaQuery()
|
.eq(WorkOrder::getFaultId, fault.getId()));
|
if (exists > 0) {
|
throw new BusinessException("故障 " + fault.getFaultCode() + " 已经派单");
|
}
|
List<Contractor> contractors = contractorMapper.selectBatchIds(contractorIds);
|
Map<Long, Contractor> contractorMap = contractors.stream()
|
.collect(Collectors.toMap(Contractor::getId, Function.identity()));
|
int sequence = 1;
|
for (Long contractorId : contractorIds) {
|
Contractor contractor = contractorMap.get(contractorId);
|
if (contractor == null) {
|
continue;
|
}
|
WorkOrder workOrder = workOrderFromFault(fault);
|
workOrder.setWorkOrderNo(fault.getFaultCode() + "/" + String.format("%02d", sequence++));
|
workOrder.setContractorId(contractor.getId());
|
workOrder.setContractorName(contractor.getName());
|
workOrder.setCompletionStatus(StatusConstants.Completion.UNFINISHED);
|
workOrder.setDispatchTime(LocalDateTime.now());
|
workOrder.setCreateTime(LocalDateTime.now());
|
workOrder.setUpdateTime(LocalDateTime.now());
|
workOrderMapper.insert(workOrder);
|
created.add(workOrder);
|
}
|
fault.setTaskStatus(StatusConstants.Task.DISPATCHED);
|
fault.setDispatchTime(LocalDateTime.now());
|
fault.setUpdateTime(LocalDateTime.now());
|
faultMapper.updateById(fault);
|
}
|
return created;
|
}
|
|
public List<WorkOrder> listWorkOrders(String status, String keyword) {
|
LambdaQueryWrapper<WorkOrder> query = Wrappers.lambdaQuery();
|
if (StringUtils.hasText(status)) {
|
query.in(WorkOrder::getCompletionStatus, Arrays.asList(status.split(",")));
|
}
|
if (StringUtils.hasText(keyword)) {
|
query.and(wrapper -> wrapper
|
.like(WorkOrder::getWorkOrderNo, keyword)
|
.or().like(WorkOrder::getFaultCode, keyword)
|
.or().like(WorkOrder::getEquipmentName, keyword)
|
.or().like(WorkOrder::getContractorName, keyword));
|
}
|
query.orderByDesc(WorkOrder::getDispatchTime).orderByAsc(WorkOrder::getWorkOrderNo);
|
return workOrderMapper.selectList(query);
|
}
|
|
public WorkOrder getWorkOrder(Long id) {
|
return workOrderMapper.selectById(id);
|
}
|
|
@Transactional
|
public void updateCompletionStatus(Requests.StatusRequest request) {
|
WorkOrder workOrder = requireWorkOrder(request.getId());
|
if (StatusConstants.Completion.COMPLETED.equals(workOrder.getCompletionStatus())) {
|
throw new BusinessException("已完工派工单不能退回普通完工状态");
|
}
|
if (!Arrays.asList(
|
StatusConstants.Completion.UNFINISHED,
|
StatusConstants.Completion.WAIT_PARTS,
|
StatusConstants.Completion.WAIT_TEST).contains(request.getStatus())) {
|
throw new BusinessException("完工状态不合法");
|
}
|
workOrder.setCompletionStatus(request.getStatus());
|
workOrder.setUpdateTime(LocalDateTime.now());
|
workOrderMapper.updateById(workOrder);
|
}
|
|
@Transactional
|
public void scoreWorkOrder(Requests.ScoreRequest request) {
|
WorkOrder workOrder = requireWorkOrder(request.getId());
|
if (request.getScore() == null || request.getScore() < 1 || request.getScore() > 5) {
|
throw new BusinessException("修后质量评分必须在1至5之间");
|
}
|
workOrder.setScore(request.getScore());
|
workOrder.setQualityOpinion(request.getOpinion());
|
workOrder.setUpdateTime(LocalDateTime.now());
|
workOrderMapper.updateById(workOrder);
|
}
|
|
@Transactional
|
public CompletionInfo submitCompletion(Requests.CompletionRequest request) {
|
WorkOrder workOrder = requireWorkOrder(request.getWorkOrderId());
|
if (StatusConstants.Completion.COMPLETED.equals(workOrder.getCompletionStatus())) {
|
throw new BusinessException("该派工单已完工上报,不能重复提交");
|
}
|
LocalDateTime now = LocalDateTime.now();
|
workOrder.setCompletionStatus(StatusConstants.Completion.COMPLETED);
|
workOrder.setUpdateTime(now);
|
workOrderMapper.updateById(workOrder);
|
|
CompletionInfo info = completionInfoMapper.selectOne(Wrappers.<CompletionInfo>lambdaQuery()
|
.eq(CompletionInfo::getWorkOrderId, workOrder.getId()).last("LIMIT 1"));
|
if (info == null) {
|
info = new CompletionInfo();
|
info.setWorkOrderId(workOrder.getId());
|
info.setCreateTime(now);
|
}
|
info.setWorkOrderNo(workOrder.getWorkOrderNo());
|
info.setXNo(workOrder.getXNo());
|
info.setContractorName(workOrder.getContractorName());
|
info.setEngineeringNo(request.getEngineeringNo());
|
info.setStartDate(request.getStartDate());
|
info.setFinishDate(request.getFinishDate());
|
info.setContractorPerson(request.getContractorPerson());
|
info.setTInternalConstruction(request.getTInternalConstruction());
|
info.setRelatedProject(request.getRelatedProject());
|
info.setDurationDays(request.getDurationDays());
|
info.setPersonCount(request.getPersonCount());
|
info.setAcceptanceMode(request.getAcceptanceMode());
|
info.setQualityInfo(request.getQualityInfo());
|
info.setReasonAnalysis(request.getReasonAnalysis());
|
info.setFaultDescription(request.getFaultDescription());
|
info.setItemName(request.getItemName());
|
info.setSolution(joinSolutions(request));
|
try {
|
info.setSolutionsJson(objectMapper.writeValueAsString(request.getSolutions()));
|
info.setConsumablesJson(objectMapper.writeValueAsString(request.getMaterials()));
|
info.setConsumableCount(materialQuantity(request.getMaterials()));
|
} catch (Exception exception) {
|
info.setSolutionsJson("[]");
|
info.setConsumablesJson("[]");
|
}
|
info.setSubmitTime(now);
|
info.setUpdateTime(now);
|
if (info.getId() == null) {
|
completionInfoMapper.insert(info);
|
} else {
|
completionInfoMapper.updateById(info);
|
}
|
|
Acceptance acceptance = acceptanceMapper.selectOne(Wrappers.<Acceptance>lambdaQuery()
|
.eq(Acceptance::getWorkOrderId, workOrder.getId()).last("LIMIT 1"));
|
if (acceptance == null) {
|
acceptance = new Acceptance();
|
acceptance.setWorkOrderId(workOrder.getId());
|
acceptance.setWorkOrderNo(workOrder.getWorkOrderNo());
|
acceptance.setXNo(workOrder.getXNo());
|
acceptance.setContractorName(workOrder.getContractorName());
|
acceptance.setStage("APPLICATION");
|
acceptance.setStatus(StatusConstants.Acceptance.APPLICATION_PENDING);
|
acceptance.setApplyTime(now);
|
acceptance.setCreateTime(now);
|
acceptance.setUpdateTime(now);
|
acceptanceMapper.insert(acceptance);
|
}
|
return info;
|
}
|
|
public List<Acceptance> listAcceptances(String stage) {
|
LambdaQueryWrapper<Acceptance> query = Wrappers.lambdaQuery();
|
if (StringUtils.hasText(stage)) {
|
switch (stage) {
|
case "APPLICATION":
|
query.in(Acceptance::getStatus,
|
StatusConstants.Acceptance.APPLICATION_PENDING,
|
StatusConstants.Acceptance.RETURNED_APPLICATION);
|
break;
|
case "INSPECTOR":
|
query.in(Acceptance::getStatus,
|
StatusConstants.Acceptance.QUALITY_INSPECTOR_PENDING,
|
StatusConstants.Acceptance.RETURNED_INSPECTOR);
|
break;
|
case "LEADER":
|
query.eq(Acceptance::getStatus, StatusConstants.Acceptance.QUALITY_LEADER_PENDING);
|
break;
|
case "PRINT":
|
query.eq(Acceptance::getStatus, StatusConstants.Acceptance.PRINT_PENDING);
|
break;
|
case "RATING":
|
query.eq(Acceptance::getStatus, StatusConstants.Acceptance.RATING_PENDING);
|
break;
|
case "COMPLETED":
|
query.eq(Acceptance::getStatus, StatusConstants.Acceptance.COMPLETED);
|
break;
|
default:
|
break;
|
}
|
}
|
query.orderByDesc(Acceptance::getUpdateTime);
|
return acceptanceMapper.selectList(query);
|
}
|
|
public Map<String, Object> acceptanceDetail(Long id) {
|
Acceptance acceptance = acceptanceMapper.selectById(id);
|
if (acceptance == null) {
|
throw new BusinessException("验收记录不存在");
|
}
|
WorkOrder workOrder = requireWorkOrder(acceptance.getWorkOrderId());
|
CompletionInfo completion = completionInfoMapper.selectOne(Wrappers.<CompletionInfo>lambdaQuery()
|
.eq(CompletionInfo::getWorkOrderId, workOrder.getId()).last("LIMIT 1"));
|
Map<String, Object> data = new LinkedHashMap<>();
|
data.put("acceptance", acceptance);
|
data.put("workOrder", workOrder);
|
data.put("completion", completion);
|
return data;
|
}
|
|
@Transactional
|
public void acceptanceAction(Requests.AcceptanceActionRequest request) {
|
Acceptance acceptance = acceptanceMapper.selectById(request.getId());
|
if (acceptance == null) {
|
throw new BusinessException("验收记录不存在");
|
}
|
WorkOrder workOrder = requireWorkOrder(acceptance.getWorkOrderId());
|
if (!StatusConstants.Completion.COMPLETED.equals(workOrder.getCompletionStatus())) {
|
throw new BusinessException("只有完工状态的派工单才能进入验收流程");
|
}
|
LocalDateTime now = LocalDateTime.now();
|
String action = request.getAction();
|
if ("SUBMIT".equalsIgnoreCase(action)) {
|
requireAcceptance(acceptance, StatusConstants.Acceptance.APPLICATION_PENDING,
|
StatusConstants.Acceptance.RETURNED_APPLICATION);
|
acceptance.setStage("QUALITY_INSPECTOR");
|
acceptance.setStatus(StatusConstants.Acceptance.QUALITY_INSPECTOR_PENDING);
|
acceptance.setApplyTime(now);
|
acceptance.setApplyRemark(request.getOpinion());
|
} else if ("PASS".equalsIgnoreCase(action)) {
|
if (StatusConstants.Acceptance.QUALITY_INSPECTOR_PENDING.equals(acceptance.getStatus())
|
|| StatusConstants.Acceptance.RETURNED_INSPECTOR.equals(acceptance.getStatus())) {
|
acceptance.setInspectorResult("通过");
|
acceptance.setInspectorOpinion(request.getOpinion());
|
acceptance.setInspectorTime(now);
|
acceptance.setStage("QUALITY_LEADER");
|
acceptance.setStatus(StatusConstants.Acceptance.QUALITY_LEADER_PENDING);
|
} else if (StatusConstants.Acceptance.QUALITY_LEADER_PENDING.equals(acceptance.getStatus())) {
|
acceptance.setLeaderResult("通过");
|
acceptance.setLeaderOpinion(request.getOpinion());
|
acceptance.setLeaderTime(now);
|
acceptance.setStage("PRINT");
|
acceptance.setStatus(StatusConstants.Acceptance.PRINT_PENDING);
|
} else {
|
throw new BusinessException("当前验收状态不允许通过");
|
}
|
} else if ("REJECT".equalsIgnoreCase(action)) {
|
if (StatusConstants.Acceptance.QUALITY_INSPECTOR_PENDING.equals(acceptance.getStatus())) {
|
acceptance.setInspectorResult("打回");
|
acceptance.setInspectorOpinion(request.getOpinion());
|
acceptance.setInspectorTime(now);
|
acceptance.setStage("APPLICATION");
|
acceptance.setStatus(StatusConstants.Acceptance.RETURNED_APPLICATION);
|
} else if (StatusConstants.Acceptance.QUALITY_LEADER_PENDING.equals(acceptance.getStatus())) {
|
acceptance.setLeaderResult("打回");
|
acceptance.setLeaderOpinion(request.getOpinion());
|
acceptance.setLeaderTime(now);
|
acceptance.setStage("QUALITY_INSPECTOR");
|
acceptance.setStatus(StatusConstants.Acceptance.RETURNED_INSPECTOR);
|
} else {
|
throw new BusinessException("当前验收状态不允许打回");
|
}
|
} else if ("PRINT".equalsIgnoreCase(action)) {
|
requireAcceptance(acceptance, StatusConstants.Acceptance.PRINT_PENDING);
|
acceptance.setPrintTime(now);
|
acceptance.setStage("RATING");
|
acceptance.setStatus(StatusConstants.Acceptance.RATING_PENDING);
|
} else if ("RATING".equalsIgnoreCase(action)) {
|
requireAcceptance(acceptance, StatusConstants.Acceptance.RATING_PENDING);
|
if (!StringUtils.hasText(request.getRating())) {
|
throw new BusinessException("请选择修后质量评级");
|
}
|
acceptance.setRating(request.getRating());
|
acceptance.setRatingRemark(request.getRatingRemark());
|
acceptance.setRatingTime(now);
|
acceptance.setStage("COMPLETED");
|
acceptance.setStatus(StatusConstants.Acceptance.COMPLETED);
|
} else {
|
throw new BusinessException("未知验收动作");
|
}
|
acceptance.setUpdateTime(now);
|
acceptanceMapper.updateById(acceptance);
|
}
|
|
/**
|
* The 处理解决情况 field is a repeatable list; the legacy SOLUTION column keeps a joined copy.
|
*/
|
private String joinSolutions(Requests.CompletionRequest request) {
|
List<Requests.SolutionItem> items = request.getSolutions();
|
if (items == null || items.isEmpty()) {
|
return request.getSolution();
|
}
|
String joined = items.stream()
|
.filter(item -> item != null && StringUtils.hasText(item.getContent()))
|
.map(item -> item.getContent().trim())
|
.collect(Collectors.joining("\uFF1B"));
|
return joined.length() > 2000 ? joined.substring(0, 2000) : joined;
|
}
|
|
private int materialQuantity(List<Requests.MaterialItem> materials) {
|
if (materials == null || materials.isEmpty()) {
|
return 0;
|
}
|
return materials.stream()
|
.filter(item -> item != null && item.getQuantity() != null)
|
.mapToInt(Requests.MaterialItem::getQuantity)
|
.sum();
|
}
|
|
private Fault requireFault(Long id) {
|
Fault fault = faultMapper.selectById(id);
|
if (fault == null) {
|
throw new BusinessException("故障不存在");
|
}
|
return fault;
|
}
|
|
private WorkOrder requireWorkOrder(Long id) {
|
WorkOrder workOrder = workOrderMapper.selectById(id);
|
if (workOrder == null) {
|
throw new BusinessException("派工单不存在");
|
}
|
return workOrder;
|
}
|
|
private void requireStatus(Fault fault, String status, String action) {
|
if (!status.equals(fault.getTaskStatus())) {
|
throw new BusinessException("故障 " + fault.getFaultCode() + " 当前状态不能执行" + action);
|
}
|
}
|
|
private void requireAcceptance(Acceptance acceptance, String... statuses) {
|
if (!Arrays.asList(statuses).contains(acceptance.getStatus())) {
|
throw new BusinessException("当前验收状态不允许该操作");
|
}
|
}
|
|
private boolean canEdit(Fault fault) {
|
return StatusConstants.Task.UNREPORTED.equals(fault.getTaskStatus())
|
|| StatusConstants.Task.REPORTED_XCB.equals(fault.getTaskStatus())
|
|| StatusConstants.Task.RETURNED.equals(fault.getTaskStatus());
|
}
|
|
private void normalizeParentSystemSeparators(Fault fault) {
|
if (StringUtils.hasText(fault.getParentSystem())) {
|
fault.setParentSystem(fault.getParentSystem().replace(";", "、").replace(";", "、"));
|
}
|
}
|
|
private void normalizeEquipmentIds(Fault fault) {
|
Set<Long> ids = new LinkedHashSet<>(parseIds(fault.getEquipmentIds()));
|
if (fault.getEquipmentId() != null) {
|
ids.add(fault.getEquipmentId());
|
}
|
if (ids.isEmpty()) {
|
throw new BusinessException("请选择装备名称");
|
}
|
List<Long> normalized = new ArrayList<>(ids);
|
fault.setEquipmentIds(normalized.stream().map(String::valueOf).collect(Collectors.joining(",")));
|
fault.setEquipmentId(normalized.get(0));
|
}
|
|
private List<Long> parseIds(String text) {
|
if (!StringUtils.hasText(text)) {
|
return Collections.emptyList();
|
}
|
return Arrays.stream(text.split(","))
|
.filter(StringUtils::hasText)
|
.map(Long::valueOf)
|
.collect(Collectors.toList());
|
}
|
|
private WorkOrder workOrderFromFault(Fault fault) {
|
WorkOrder workOrder = new WorkOrder();
|
workOrder.setFaultId(fault.getId());
|
workOrder.setFaultCode(fault.getFaultCode());
|
workOrder.setXNo(fault.getXNo());
|
workOrder.setEquipmentName(fault.getEquipmentName());
|
workOrder.setEngineeringMajor(fault.getEngineeringMajor());
|
workOrder.setTeamMajor(fault.getTeamMajor());
|
workOrder.setParentSystem(fault.getParentSystem());
|
workOrder.setReportUnit(fault.getReportUnit());
|
workOrder.setReportDate(fault.getReportDate());
|
workOrder.setReviewTime(fault.getXcbReviewTime());
|
workOrder.setOwner(fault.getOwner());
|
workOrder.setRequestedFinishDate(fault.getRequestedFinishDate());
|
workOrder.setEngineeringNameDesc(fault.getEngineeringNameDesc());
|
workOrder.setRepairRequirement(fault.getRepairRequirement());
|
workOrder.setFaultImpact(fault.getFaultImpact());
|
workOrder.setFaultNature(fault.getFaultNature());
|
workOrder.setIsSelfRepair(fault.getIsSelfRepair());
|
workOrder.setIsHRelated(fault.getIsHRelated());
|
workOrder.setIsMonitorItem(fault.getIsMonitorItem());
|
workOrder.setMonitorItem(fault.getMonitorItem());
|
workOrder.setMonitorValue(fault.getMonitorValue());
|
workOrder.setRemark(fault.getRemark());
|
return workOrder;
|
}
|
|
private String buildEngineeringNo(Fault fault, int index) {
|
String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
|
return "LX-" + fault.getXNo() + "-" + date + "-" + String.format("%03d", index);
|
}
|
}
|