package cn.iocoder.yudao.module.aftersales.service.problem;
|
|
import cn.hutool.core.collection.CollUtil;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.module.aftersales.controller.admin.problem.vo.AfterSaleProblemPageReqVO;
|
import cn.iocoder.yudao.module.aftersales.controller.admin.problem.vo.AfterSaleProblemSaveReqVO;
|
import cn.iocoder.yudao.module.aftersales.dal.dataobject.problem.AfterSaleProblemDO;
|
import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketDO;
|
import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketItemDO;
|
import cn.iocoder.yudao.module.aftersales.dal.mysql.problem.AfterSaleProblemMapper;
|
import cn.iocoder.yudao.module.aftersales.dal.mysql.ticket.AfterSaleTicketItemMapper;
|
import cn.iocoder.yudao.module.aftersales.dal.mysql.ticket.AfterSaleTicketMapper;
|
import cn.iocoder.yudao.module.aftersales.dal.redis.no.AfterSaleNoRedisDAO;
|
import cn.iocoder.yudao.module.aftersales.enums.AfterSaleProblemStatusEnum;
|
import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import jakarta.annotation.Resource;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.validation.annotation.Validated;
|
|
import java.time.LocalDateTime;
|
import java.util.Collection;
|
import java.util.List;
|
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
import static cn.iocoder.yudao.module.aftersales.enums.ErrorCodeConstants.*;
|
|
/**
|
* 售后问题库 Service 实现类
|
*/
|
@Service
|
@Validated
|
@Slf4j
|
public class AfterSaleProblemServiceImpl implements AfterSaleProblemService {
|
|
@Resource
|
private AfterSaleProblemMapper problemMapper;
|
@Resource
|
private AfterSaleTicketMapper ticketMapper;
|
@Resource
|
private AfterSaleTicketItemMapper ticketItemMapper;
|
@Resource
|
private AfterSaleNoRedisDAO noRedisDAO;
|
@Resource
|
private StorageAttachmentApi storageAttachmentApi;
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Long createProblem(AfterSaleProblemSaveReqVO createReqVO, Long userId) {
|
AfterSaleProblemDO problem = BeanUtils.toBean(createReqVO, AfterSaleProblemDO.class);
|
// 来源工单存在时补全冗余单号与默认客户
|
if (createReqVO.getSourceTicketId() != null) {
|
AfterSaleTicketDO ticket = ticketMapper.selectById(createReqVO.getSourceTicketId());
|
if (ticket == null) {
|
throw exception(TICKET_NOT_EXISTS);
|
}
|
problem.setSourceTicketNo(ticket.getNo());
|
if (problem.getCustomerId() == null) {
|
problem.setCustomerId(ticket.getCustomerId());
|
}
|
}
|
problem.setNo(generateNo())
|
.setStatus(AfterSaleProblemStatusEnum.DRAFT.getStatus())
|
.setOwnerUserId(userId);
|
problemMapper.insert(problem);
|
// 绑定附件
|
if (CollUtil.isNotEmpty(createReqVO.getBlobIds())) {
|
storageAttachmentApi.bindAttachments("file", "aftersales_after_sale_problem",
|
problem.getId(), createReqVO.getBlobIds());
|
}
|
return problem.getId();
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void updateProblem(AfterSaleProblemSaveReqVO updateReqVO) {
|
AfterSaleProblemDO problem = validateProblemExists(updateReqVO.getId());
|
if (!AfterSaleProblemStatusEnum.DRAFT.getStatus().equals(problem.getStatus())) {
|
throw exception(PROBLEM_UPDATE_FAIL_STATUS);
|
}
|
AfterSaleProblemDO update = BeanUtils.toBean(updateReqVO, AfterSaleProblemDO.class);
|
problemMapper.updateById(update);
|
if (CollUtil.isNotEmpty(updateReqVO.getBlobIds())) {
|
storageAttachmentApi.updateAttachments("file", "aftersales_after_sale_problem",
|
updateReqVO.getId(), updateReqVO.getBlobIds());
|
}
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void deleteProblem(Long id) {
|
AfterSaleProblemDO problem = validateProblemExists(id);
|
if (!AfterSaleProblemStatusEnum.DRAFT.getStatus().equals(problem.getStatus())) {
|
throw exception(PROBLEM_DELETE_FAIL_STATUS);
|
}
|
problemMapper.deleteById(id);
|
storageAttachmentApi.deleteAttachmentsByRecord("aftersales_after_sale_problem", id);
|
// 解除工单对问题的关联
|
ticketMapper.update(null, new LambdaUpdateWrapper<AfterSaleTicketDO>()
|
.eq(AfterSaleTicketDO::getProblemId, id)
|
.set(AfterSaleTicketDO::getProblemId, null)
|
.set(AfterSaleTicketDO::getProblemNo, null));
|
}
|
|
@Override
|
public AfterSaleProblemDO getProblem(Long id) {
|
return validateProblemExists(id);
|
}
|
|
@Override
|
public List<AfterSaleProblemDO> getProblemList(Collection<Long> ids) {
|
if (CollUtil.isEmpty(ids)) {
|
return List.of();
|
}
|
return problemMapper.selectBatchIds(ids);
|
}
|
|
@Override
|
public PageResult<AfterSaleProblemDO> getProblemPage(AfterSaleProblemPageReqVO pageReqVO) {
|
return problemMapper.selectPage(pageReqVO, pageReqVO.getNo(), pageReqVO.getKeyword(),
|
pageReqVO.getSourceTicketId(), pageReqVO.getItemId(), pageReqVO.getItemCode(),
|
pageReqVO.getIssueCategory(),
|
pageReqVO.getIssueType(), pageReqVO.getRootCauseCategory(), pageReqVO.getStatus());
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void publishProblem(Long id) {
|
AfterSaleProblemDO problem = validateProblemExists(id);
|
if (!(AfterSaleProblemStatusEnum.DRAFT.getStatus().equals(problem.getStatus())
|
|| AfterSaleProblemStatusEnum.DISABLED.getStatus().equals(problem.getStatus()))) {
|
throw exception(PROBLEM_PUBLISH_FAIL_STATUS);
|
}
|
problemMapper.updateById(new AfterSaleProblemDO().setId(id)
|
.setStatus(AfterSaleProblemStatusEnum.PUBLISHED.getStatus())
|
.setPublishTime(LocalDateTime.now()));
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void disableProblem(Long id) {
|
AfterSaleProblemDO problem = validateProblemExists(id);
|
if (!AfterSaleProblemStatusEnum.PUBLISHED.getStatus().equals(problem.getStatus())) {
|
throw exception(PROBLEM_DISABLE_FAIL_STATUS);
|
}
|
problemMapper.updateById(new AfterSaleProblemDO().setId(id)
|
.setStatus(AfterSaleProblemStatusEnum.DISABLED.getStatus()));
|
}
|
|
@Override
|
public List<AfterSaleProblemDO> getReferenceList(AfterSaleProblemPageReqVO pageReqVO) {
|
return problemMapper.selectReferenceList(pageReqVO.getItemId(), pageReqVO.getIssueCategory(),
|
pageReqVO.getIssueType(), pageReqVO.getRootCauseCategory(), pageReqVO.getKeyword());
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public AfterSaleProblemDO createProblemFromTicket(AfterSaleTicketDO ticket) {
|
// 幂等:同一工单已沉淀过则直接复用
|
AfterSaleProblemDO exist = problemMapper.selectBySourceTicketId(ticket.getId());
|
if (exist != null) {
|
return exist;
|
}
|
AfterSaleProblemDO problem = new AfterSaleProblemDO()
|
.setNo(generateNo())
|
.setTitle(ticket.getName())
|
.setSourceTicketId(ticket.getId())
|
.setSourceTicketNo(ticket.getNo())
|
.setCustomerId(ticket.getCustomerId())
|
.setIssueType(ticket.getIssueType())
|
.setIssueCategory(ticket.getIssueCategory())
|
.setSeverityLevel(ticket.getSeverityLevel())
|
.setDescription(ticket.getIssueDescription())
|
.setStatus(AfterSaleProblemStatusEnum.DRAFT.getStatus())
|
.setOwnerUserId(getLoginUserId());
|
// 取工单首条明细作为物料快照(允许无明细行)
|
AfterSaleTicketItemDO firstItem = CollUtil.getFirst(ticketItemMapper.selectListByTicketId(ticket.getId()));
|
if (firstItem != null) {
|
problem.setItemId(firstItem.getItemId())
|
.setItemCode(firstItem.getItemCode())
|
.setItemName(firstItem.getItemName())
|
.setBatchId(firstItem.getBatchId())
|
.setBatchCode(firstItem.getBatchCode());
|
}
|
problemMapper.insert(problem);
|
return problem;
|
}
|
|
// ========== 内部方法 ==========
|
|
private AfterSaleProblemDO validateProblemExists(Long id) {
|
AfterSaleProblemDO problem = problemMapper.selectById(id);
|
if (problem == null) {
|
throw exception(PROBLEM_NOT_EXISTS);
|
}
|
return problem;
|
}
|
|
private String generateNo() {
|
String no = noRedisDAO.generate(AfterSaleNoRedisDAO.PROBLEM_NO_PREFIX);
|
if (problemMapper.selectByNo(no) != null) {
|
throw exception(PROBLEM_NO_EXISTS);
|
}
|
return no;
|
}
|
|
}
|