package cn.iocoder.yudao.module.mes.service.safety; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.safety.vo.ticket.MesSafetyWorkTicketApproveReqVO; import cn.iocoder.yudao.module.mes.controller.admin.safety.vo.ticket.MesSafetyWorkTicketCloseReqVO; import cn.iocoder.yudao.module.mes.controller.admin.safety.vo.ticket.MesSafetyWorkTicketPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.safety.vo.ticket.MesSafetyWorkTicketSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.safety.MesSafetyWorkTicketDO; import cn.iocoder.yudao.module.mes.dal.mysql.safety.MesSafetyWorkTicketMapper; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** * 安全生产 - 特种作业票证 Service 实现 * * @author 超级管理员 */ @Service @Validated public class MesSafetyWorkTicketServiceImpl implements MesSafetyWorkTicketService { @Resource private MesSafetyWorkTicketMapper ticketMapper; @Override public PageResult getTicketPage(MesSafetyWorkTicketPageReqVO pageReqVO) { return ticketMapper.selectPage(pageReqVO); } @Override public MesSafetyWorkTicketDO getTicket(Long id) { return ticketMapper.selectById(id); } @Override public Long createTicket(MesSafetyWorkTicketSaveReqVO createReqVO) { validateCodeUnique(null, createReqVO.getCode()); validateTimeRange(createReqVO.getPlanStartTime(), createReqVO.getPlanEndTime()); MesSafetyWorkTicketDO ticket = BeanUtils.toBean(createReqVO, MesSafetyWorkTicketDO.class); // 新建即待审批 ticket.setStatus(MesSafetyWorkTicketDO.STATUS_PENDING); ticket.setGuardianConfirm(false); ticketMapper.insert(ticket); return ticket.getId(); } @Override public void updateTicket(MesSafetyWorkTicketSaveReqVO updateReqVO) { MesSafetyWorkTicketDO exists = validateTicketExists(updateReqVO.getId()); // 审批通过后不允许再改作业信息,需作废重开 if (!MesSafetyWorkTicketDO.STATUS_PENDING.equals(exists.getStatus()) && !MesSafetyWorkTicketDO.STATUS_REJECTED.equals(exists.getStatus())) { throw exception(MES_SAFETY_TICKET_STATUS_INVALID); } validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); validateTimeRange(updateReqVO.getPlanStartTime(), updateReqVO.getPlanEndTime()); MesSafetyWorkTicketDO updateObj = BeanUtils.toBean(updateReqVO, MesSafetyWorkTicketDO.class); // 状态与审批/归档信息不走此接口 updateObj.setStatus(null); updateObj.setApproverUserId(null); updateObj.setApproveTime(null); updateObj.setApproveComment(null); updateObj.setRejectReason(null); updateObj.setCloseTime(null); updateObj.setCloseUserId(null); updateObj.setCloseRemark(null); updateObj.setActualStartTime(null); updateObj.setActualEndTime(null); // 重新提交时清空驳回原因 if (MesSafetyWorkTicketDO.STATUS_REJECTED.equals(exists.getStatus())) { updateObj.setStatus(MesSafetyWorkTicketDO.STATUS_PENDING); updateObj.setRejectReason(""); } ticketMapper.updateById(updateObj); } @Override public void deleteTicket(Long id) { MesSafetyWorkTicketDO exists = validateTicketExists(id); // 已批准及之后的作业票不允许删除(需保留追溯记录) if (MesSafetyWorkTicketDO.STATUS_APPROVED.equals(exists.getStatus()) || MesSafetyWorkTicketDO.STATUS_FINISHED.equals(exists.getStatus()) || MesSafetyWorkTicketDO.STATUS_ARCHIVED.equals(exists.getStatus())) { throw exception(MES_SAFETY_TICKET_STATUS_INVALID); } ticketMapper.deleteById(id); } @Override public void approveTicket(Long userId, MesSafetyWorkTicketApproveReqVO reqVO) { MesSafetyWorkTicketDO ticket = validateTicketExists(reqVO.getId()); if (!MesSafetyWorkTicketDO.STATUS_PENDING.equals(ticket.getStatus())) { throw exception(MES_SAFETY_TICKET_STATUS_INVALID); } MesSafetyWorkTicketDO updateObj = new MesSafetyWorkTicketDO(); updateObj.setId(reqVO.getId()); updateObj.setApproverUserId(userId); updateObj.setApproveTime(LocalDateTime.now()); updateObj.setApproveComment(reqVO.getApproveComment()); if (Boolean.TRUE.equals(reqVO.getPass())) { updateObj.setStatus(MesSafetyWorkTicketDO.STATUS_APPROVED); updateObj.setRejectReason(""); } else { if (reqVO.getRejectReason() == null || reqVO.getRejectReason().trim().isEmpty()) { throw exception(MES_SAFETY_TICKET_REJECT_REASON_REQUIRED); } updateObj.setStatus(MesSafetyWorkTicketDO.STATUS_REJECTED); updateObj.setRejectReason(reqVO.getRejectReason()); } ticketMapper.updateById(updateObj); } @Override public void closeTicket(Long userId, MesSafetyWorkTicketCloseReqVO reqVO) { MesSafetyWorkTicketDO ticket = validateTicketExists(reqVO.getId()); Integer status = ticket.getStatus(); // 已批准 → 完工;已完工 → 归档 boolean canFinish = MesSafetyWorkTicketDO.STATUS_APPROVED.equals(status); boolean canArchive = MesSafetyWorkTicketDO.STATUS_FINISHED.equals(status); if (!canFinish && !canArchive) { throw exception(MES_SAFETY_TICKET_STATUS_INVALID); } MesSafetyWorkTicketDO updateObj = new MesSafetyWorkTicketDO(); updateObj.setId(reqVO.getId()); updateObj.setActualStartTime(reqVO.getActualStartTime()); updateObj.setActualEndTime(reqVO.getActualEndTime()); if (reqVO.getCloseRemark() != null) { updateObj.setCloseRemark(reqVO.getCloseRemark()); } if (canFinish) { // 完工登记;若同时选择归档则直接进入已归档 boolean archiveNow = Boolean.TRUE.equals(reqVO.getArchive()); updateObj.setStatus(archiveNow ? MesSafetyWorkTicketDO.STATUS_ARCHIVED : MesSafetyWorkTicketDO.STATUS_FINISHED); if (archiveNow) { updateObj.setCloseTime(LocalDateTime.now()); updateObj.setCloseUserId(userId); } } else { // 已完工 → 归档 updateObj.setStatus(MesSafetyWorkTicketDO.STATUS_ARCHIVED); updateObj.setCloseTime(LocalDateTime.now()); updateObj.setCloseUserId(userId); } ticketMapper.updateById(updateObj); } @Override public MesSafetyWorkTicketDO validateTicketExists(Long id) { if (id == null) { throw exception(MES_SAFETY_TICKET_NOT_EXISTS); } MesSafetyWorkTicketDO ticket = ticketMapper.selectById(id); if (ticket == null) { throw exception(MES_SAFETY_TICKET_NOT_EXISTS); } return ticket; } /** * 校验计划时间区间合法 */ private void validateTimeRange(LocalDateTime start, LocalDateTime end) { if (start != null && end != null && !end.isAfter(start)) { throw exception(MES_SAFETY_TICKET_TIME_INVALID); } } private void validateCodeUnique(Long id, String code) { MesSafetyWorkTicketDO exists = ticketMapper.selectByCode(code); if (exists == null) { return; } if (id == null || !Objects.equals(exists.getId(), id)) { throw exception(MES_SAFETY_TICKET_CODE_DUPLICATE); } } }