package cn.iocoder.yudao.module.ums.service.application; import cn.hutool.core.collection.CollUtil; 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.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO; import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; import cn.iocoder.yudao.module.ums.controller.admin.application.vo.UmsApplicationPageReqVO; import cn.iocoder.yudao.module.ums.controller.admin.application.vo.UmsApplicationSaveReqVO; import cn.iocoder.yudao.module.ums.dal.dataobject.application.UmsApplicationDO; import cn.iocoder.yudao.module.ums.dal.mysql.application.UmsApplicationMapper; import cn.iocoder.yudao.module.ums.dal.redis.UmsNoRedisDAO; import cn.iocoder.yudao.module.ums.enums.UmsApplicationStatusEnum; import cn.iocoder.yudao.module.ums.service.member.UmsMemberService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.repository.ProcessDefinition; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 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.ums.enums.ErrorCodeConstants.*; @Service @Validated @Slf4j public class UmsApplicationServiceImpl implements UmsApplicationService { private static final String APPLICATION_APPROVE_CATEGORY_CODE = "ums_membership_approve"; public static final String APPLICATION_RECORD_TYPE = "ums_application"; @Resource private UmsApplicationMapper applicationMapper; @Resource private UmsNoRedisDAO noRedisDAO; @Resource private StorageAttachmentApi storageAttachmentApi; @Resource private BpmProcessInstanceApi processInstanceApi; @Resource private BpmCategoryService bpmCategoryService; @Resource private BpmProcessDefinitionService bpmProcessDefinitionService; @Resource private UmsMemberService memberService; @Override @Transactional(rollbackFor = Exception.class) public Long createApplication(UmsApplicationSaveReqVO createReqVO) { String no = noRedisDAO.generate(UmsNoRedisDAO.APPLICATION_NO_PREFIX); if (applicationMapper.selectByNo(no) != null) { throw exception(APPLICATION_NO_EXISTS); } UmsApplicationDO application = BeanUtils.toBean(createReqVO, UmsApplicationDO.class, in -> in .setNo(no) .setStatus(UmsApplicationStatusEnum.DRAFT.getStatus())); applicationMapper.insert(application); storageAttachmentApi.bindAttachments("file", APPLICATION_RECORD_TYPE, application.getId(), createReqVO.getBlobIds()); return application.getId(); } @Override @Transactional(rollbackFor = Exception.class) public void updateApplication(UmsApplicationSaveReqVO updateReqVO) { UmsApplicationDO application = validateApplicationExists(updateReqVO.getId()); Integer status = application.getStatus(); if (!UmsApplicationStatusEnum.DRAFT.getStatus().equals(status) && !UmsApplicationStatusEnum.REJECTED.getStatus().equals(status)) { throw exception(APPLICATION_UPDATE_FAIL_NOT_DRAFT, application.getNo()); } UmsApplicationDO updateObj = BeanUtils.toBean(updateReqVO, UmsApplicationDO.class); applicationMapper.updateById(updateObj); storageAttachmentApi.updateAttachments("file", APPLICATION_RECORD_TYPE, updateReqVO.getId(), updateReqVO.getBlobIds()); } @Override @Transactional(rollbackFor = Exception.class) public void deleteApplication(Long id) { UmsApplicationDO application = validateApplicationExists(id); if (!UmsApplicationStatusEnum.DRAFT.getStatus().equals(application.getStatus())) { throw exception(APPLICATION_DELETE_FAIL_NOT_DRAFT, application.getNo()); } applicationMapper.deleteById(id); storageAttachmentApi.deleteAttachmentsByRecord(APPLICATION_RECORD_TYPE, id); } @Override public UmsApplicationDO getApplication(Long id) { return applicationMapper.selectById(id); } @Override public PageResult getApplicationPage(UmsApplicationPageReqVO pageReqVO) { return applicationMapper.selectPage(pageReqVO); } @Override @Transactional(rollbackFor = Exception.class) public void submitApplication(Long id, String processDefinitionKey) { UmsApplicationDO application = validateApplicationExists(id); Integer status = application.getStatus(); if (!UmsApplicationStatusEnum.DRAFT.getStatus().equals(status) && !UmsApplicationStatusEnum.REJECTED.getStatus().equals(status)) { throw exception(APPLICATION_SUBMIT_FAIL_STATUS); } String processInstanceId = processInstanceApi.createProcessInstance(getLoginUserId(), new BpmProcessInstanceCreateReqDTO() .setProcessDefinitionKey(processDefinitionKey) .setBusinessKey(String.valueOf(id))); applicationMapper.updateById(new UmsApplicationDO() .setId(id) .setStatus(UmsApplicationStatusEnum.APPROVING.getStatus()) .setProcessInstanceId(processInstanceId)); } @Override public List> getApproveProcessDefinitionList() { validateApplicationApproveCategory(); List definitionInfoList = bpmProcessDefinitionService.getProcessDefinitionInfoListByCategory(APPLICATION_APPROVE_CATEGORY_CODE); if (CollUtil.isEmpty(definitionInfoList)) { return Collections.emptyList(); } Map latestVersionMap = new HashMap<>(); for (cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionInfoDO info : definitionInfoList) { ProcessDefinition pd = bpmProcessDefinitionService.getProcessDefinition(info.getProcessDefinitionId()); if (pd == null || pd.isSuspended()) { continue; } ProcessDefinition existing = latestVersionMap.get(pd.getKey()); if (existing == null || pd.getVersion() > existing.getVersion()) { latestVersionMap.put(pd.getKey(), pd); } } List> result = new ArrayList<>(); for (ProcessDefinition pd : latestVersionMap.values()) { Map item = new HashMap<>(); item.put("id", pd.getId()); item.put("key", pd.getKey()); item.put("name", pd.getName()); result.add(item); } return result; } @Override @Transactional(rollbackFor = Exception.class) public void updateApplicationAuditStatus(Long id, Integer bpmResult) { UmsApplicationDO application = validateApplicationExists(id); if (!UmsApplicationStatusEnum.APPROVING.getStatus().equals(application.getStatus())) { log.warn("[updateApplicationAuditStatus] 入会申请({}) 不处于审批中状态", id); return; } Integer newStatus = convertBpmResultToStatus(bpmResult); if (newStatus != null) { applicationMapper.updateById(new UmsApplicationDO() .setId(id).setStatus(newStatus)); } } // =================== 内部方法 =================== private UmsApplicationDO validateApplicationExists(Long id) { UmsApplicationDO application = applicationMapper.selectById(id); if (application == null) { throw exception(APPLICATION_NOT_EXISTS); } return application; } private void validateApplicationApproveCategory() { List categories = bpmCategoryService.getCategoryListByCode( Collections.singletonList(APPLICATION_APPROVE_CATEGORY_CODE)); if (CollUtil.isEmpty(categories)) { throw exception(APPLICATION_BPM_CATEGORY_NOT_EXISTS); } } private Integer convertBpmResultToStatus(Integer bpmResult) { if (cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum.APPROVE.getStatus().equals(bpmResult)) { return UmsApplicationStatusEnum.APPROVED.getStatus(); } else if (cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum.REJECT.getStatus().equals(bpmResult)) { return UmsApplicationStatusEnum.REJECTED.getStatus(); } else if (cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum.CANCEL.getStatus().equals(bpmResult)) { return UmsApplicationStatusEnum.DRAFT.getStatus(); } return null; } @Override @Transactional(rollbackFor = Exception.class) public void createMemberFromApplicationOnApproved(Long id) { UmsApplicationDO application = validateApplicationExists(id); if (!UmsApplicationStatusEnum.APPROVED.getStatus().equals(application.getStatus())) { log.warn("[createMemberFromApplicationOnApproved] 入会申请({}) 不是已通过状态,跳过建会员", id); return; } memberService.createMemberFromApplication(application); } }