package cn.iocoder.yudao.module.mes.service.safety;
|
|
import cn.hutool.core.util.StrUtil;
|
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.permit.*;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.safety.SafetyWorkPermitDO;
|
import cn.iocoder.yudao.module.mes.dal.dataobject.safety.SafetyWorkPermitMonitorDO;
|
import cn.iocoder.yudao.module.mes.dal.mysql.safety.SafetyWorkPermitMapper;
|
import cn.iocoder.yudao.module.mes.dal.mysql.safety.SafetyWorkPermitMonitorMapper;
|
import cn.iocoder.yudao.module.mes.enums.safety.SafetyPermitStatusEnum;
|
import cn.iocoder.yudao.module.mes.enums.safety.SafetyPermitTypeEnum;
|
import cn.iocoder.yudao.module.mes.enums.safety.SafetyRiskLevelEnum;
|
import jakarta.annotation.Resource;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.validation.annotation.Validated;
|
|
import java.time.LocalDate;
|
import java.time.LocalDateTime;
|
import java.time.format.DateTimeFormatter;
|
import java.util.List;
|
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.module.mes.enums.SafetyErrorCodeConstants.*;
|
|
/**
|
* 安全生产 - 高危作业票 Service
|
*
|
* <p>动火、高压带电、有限空间等作业的线上审批与电子留存。
|
* 状态流转:草稿 → 待审批 → 已批准 → 作业中 → 已完结;驳回/作废为终止态。</p>
|
*
|
* @author 超级管理员
|
*/
|
@Service
|
@Validated
|
public class SafetyWorkPermitService {
|
|
private static final DateTimeFormatter CODE_DATE = DateTimeFormatter.ofPattern("yyyyMMdd");
|
|
@Resource
|
private SafetyWorkPermitMapper permitMapper;
|
@Resource
|
private SafetyWorkPermitMonitorMapper monitorMapper;
|
|
/**
|
* 提交作业申请(草稿或待审批)
|
*/
|
@Transactional(rollbackFor = Exception.class)
|
public Long createPermit(SafetyWorkPermitSaveReqVO reqVO) {
|
reqVO.setId(null);
|
validateTimeRange(reqVO);
|
SafetyWorkPermitDO permit = BeanUtils.toBean(reqVO, SafetyWorkPermitDO.class);
|
permit.setCode(permitMapper.selectNextCode("WP" + LocalDate.now().format(CODE_DATE)));
|
permit.setTitle(StrUtil.trim(reqVO.getTitle()));
|
permit.setApplicant(StrUtil.trim(reqVO.getApplicant()));
|
permit.setApplyTime(reqVO.getApplyTime() == null ? LocalDateTime.now() : reqVO.getApplyTime());
|
permit.setRiskLevel(StrUtil.blankToDefault(reqVO.getRiskLevel(), SafetyRiskLevelEnum.NORMAL.getLevel()));
|
permit.setStatus(SafetyPermitStatusEnum.PENDING.getStatus());
|
permit.setRemark(reqVO.getRemark() == null ? "" : reqVO.getRemark().trim());
|
permitMapper.insert(permit);
|
return permit.getId();
|
}
|
|
/**
|
* 修改作业票(仅草稿/待审批可改)
|
*/
|
public void updatePermit(SafetyWorkPermitSaveReqVO reqVO) {
|
SafetyWorkPermitDO old = validatePermitExists(reqVO.getId());
|
ensureStatus(old, SafetyPermitStatusEnum.DRAFT, SafetyPermitStatusEnum.PENDING);
|
validateTimeRange(reqVO);
|
SafetyWorkPermitDO update = BeanUtils.toBean(reqVO, SafetyWorkPermitDO.class);
|
update.setCode(null);
|
update.setStatus(null);
|
permitMapper.updateById(update);
|
}
|
|
/**
|
* 审批作业票
|
*
|
* <p>批准时校验高危作业(动火/高压带电/有限空间)必须指定监护人,
|
* 保证作业票电子留存的完整性。</p>
|
*/
|
@Transactional(rollbackFor = Exception.class)
|
public void approvePermit(SafetyWorkPermitApproveReqVO reqVO) {
|
SafetyWorkPermitDO permit = validatePermitExists(reqVO.getId());
|
ensureStatus(permit, SafetyPermitStatusEnum.PENDING);
|
String approver = StrUtil.trim(reqVO.getApprover());
|
// 申请人不能审批自己的作业票
|
if (approver.equals(permit.getApplicant())) {
|
throw exception(SAFETY_PERMIT_STATUS_ERROR);
|
}
|
boolean approved = "APPROVED".equals(reqVO.getDecision());
|
if (approved && SafetyPermitTypeEnum.requiresGuardian(permit.getPermitType())
|
&& StrUtil.isBlank(permit.getGuardian())) {
|
throw exception(SAFETY_PERMIT_GUARDIAN_REQUIRED);
|
}
|
SafetyWorkPermitDO update = new SafetyWorkPermitDO();
|
update.setId(permit.getId());
|
update.setApprover(approver);
|
update.setApproveTime(LocalDateTime.now());
|
update.setApproveComment(reqVO.getApproveComment());
|
update.setStatus(approved ? SafetyPermitStatusEnum.APPROVED.getStatus()
|
: SafetyPermitStatusEnum.REJECTED.getStatus());
|
permitMapper.updateById(update);
|
}
|
|
/**
|
* 开始作业(须已批准)
|
*/
|
public void startPermit(Long id) {
|
SafetyWorkPermitDO permit = validatePermitExists(id);
|
if (!SafetyPermitStatusEnum.APPROVED.getStatus().equals(permit.getStatus())) {
|
throw exception(SAFETY_PERMIT_NOT_APPROVED);
|
}
|
SafetyWorkPermitDO update = new SafetyWorkPermitDO();
|
update.setId(id);
|
update.setActualStartTime(LocalDateTime.now());
|
update.setStatus(SafetyPermitStatusEnum.IN_PROGRESS.getStatus());
|
permitMapper.updateById(update);
|
}
|
|
/**
|
* 结束作业并归档
|
*/
|
public void closePermit(Long id) {
|
SafetyWorkPermitDO permit = validatePermitExists(id);
|
ensureStatus(permit, SafetyPermitStatusEnum.IN_PROGRESS);
|
SafetyWorkPermitDO update = new SafetyWorkPermitDO();
|
update.setId(id);
|
update.setActualEndTime(LocalDateTime.now());
|
update.setStatus(SafetyPermitStatusEnum.CLOSED.getStatus());
|
permitMapper.updateById(update);
|
}
|
|
/**
|
* 作废作业票(未完结前均可作废)
|
*/
|
public void cancelPermit(Long id) {
|
SafetyWorkPermitDO permit = validatePermitExists(id);
|
if (SafetyPermitStatusEnum.CLOSED.getStatus().equals(permit.getStatus())
|
|| SafetyPermitStatusEnum.CANCELLED.getStatus().equals(permit.getStatus())) {
|
throw exception(SAFETY_PERMIT_STATUS_ERROR);
|
}
|
SafetyWorkPermitDO update = new SafetyWorkPermitDO();
|
update.setId(id);
|
update.setStatus(SafetyPermitStatusEnum.CANCELLED.getStatus());
|
permitMapper.updateById(update);
|
}
|
|
@Transactional(rollbackFor = Exception.class)
|
public void deletePermit(Long id) {
|
validatePermitExists(id);
|
monitorMapper.deleteByPermitId(id);
|
permitMapper.deleteById(id);
|
}
|
|
public SafetyWorkPermitDO getPermit(Long id) {
|
return validatePermitExists(id);
|
}
|
|
public PageResult<SafetyWorkPermitDO> getPermitPage(SafetyWorkPermitPageReqVO reqVO) {
|
return permitMapper.selectPage(reqVO);
|
}
|
|
// ==================== 监护记录 ====================
|
|
public Long createMonitor(SafetyWorkPermitMonitorSaveReqVO reqVO) {
|
SafetyWorkPermitDO permit = validatePermitExists(reqVO.getPermitId());
|
if (!SafetyPermitStatusEnum.IN_PROGRESS.getStatus().equals(permit.getStatus())
|
&& !SafetyPermitStatusEnum.APPROVED.getStatus().equals(permit.getStatus())) {
|
throw exception(SAFETY_PERMIT_STATUS_ERROR);
|
}
|
SafetyWorkPermitMonitorDO monitor = BeanUtils.toBean(reqVO, SafetyWorkPermitMonitorDO.class);
|
monitor.setId(null);
|
monitor.setGuardian(StrUtil.trim(reqVO.getGuardian()));
|
monitor.setMonitorTime(reqVO.getMonitorTime() == null ? LocalDateTime.now() : reqVO.getMonitorTime());
|
monitorMapper.insert(monitor);
|
return monitor.getId();
|
}
|
|
public void deleteMonitor(Long id) {
|
if (id == null || monitorMapper.selectById(id) == null) {
|
throw exception(SAFETY_PERMIT_MONITOR_NOT_EXISTS);
|
}
|
monitorMapper.deleteById(id);
|
}
|
|
public List<SafetyWorkPermitMonitorDO> getMonitorList(Long permitId) {
|
return monitorMapper.selectListByPermitId(permitId);
|
}
|
|
// ==================== 展示字段 ====================
|
|
public static void fillPermitDisplay(SafetyWorkPermitDO permit, SafetyWorkPermitRespVO respVO) {
|
respVO.setPermitTypeName(SafetyPermitTypeEnum.getNameByType(permit.getPermitType()));
|
respVO.setRiskLevelName(SafetyRiskLevelEnum.getNameByLevel(permit.getRiskLevel()));
|
respVO.setStatusName(SafetyPermitStatusEnum.getNameByStatus(permit.getStatus()));
|
respVO.setGuardianRequired(SafetyPermitTypeEnum.requiresGuardian(permit.getPermitType()));
|
}
|
|
private void validateTimeRange(SafetyWorkPermitSaveReqVO reqVO) {
|
if (reqVO.getPlanStartTime() != null && reqVO.getPlanEndTime() != null
|
&& !reqVO.getPlanEndTime().isAfter(reqVO.getPlanStartTime())) {
|
throw exception(SAFETY_PERMIT_TIME_INVALID);
|
}
|
}
|
|
private void ensureStatus(SafetyWorkPermitDO permit, SafetyPermitStatusEnum... allowed) {
|
for (SafetyPermitStatusEnum status : allowed) {
|
if (status.getStatus().equals(permit.getStatus())) {
|
return;
|
}
|
}
|
throw exception(SAFETY_PERMIT_STATUS_ERROR);
|
}
|
|
private SafetyWorkPermitDO validatePermitExists(Long id) {
|
SafetyWorkPermitDO permit = id == null ? null : permitMapper.selectById(id);
|
if (permit == null) {
|
throw exception(SAFETY_PERMIT_NOT_EXISTS);
|
}
|
return permit;
|
}
|
|
}
|