| | |
| | | import cn.iocoder.yudao.module.crm.service.invoice.CrmInvoiceService; |
| | | import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; |
| | | import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; |
| | | 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.enums.task.BpmTaskStatusEnum; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.approval.ApprovalConfigApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.enums.storage.StorageRecordTypeEnum; |
| | | import com.mzt.logapi.context.LogRecordContext; |
| | | import com.mzt.logapi.service.impl.DiffParseFunction; |
| | | import com.mzt.logapi.starter.annotation.LogRecord; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | import java.util.*; |
| | | |
| | | 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.crm.enums.ErrorCodeConstants.*; |
| | | import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; |
| | | |
| | |
| | | */ |
| | | @Service |
| | | @Validated |
| | | @Slf4j |
| | | public class CrmReceivableServiceImpl implements CrmReceivableService { |
| | | |
| | | private static final String RECEIVABLE_PROCESS_KEY = "crm-receivable-audit"; |
| | | private static final String RECEIVABLE_APPROVE_BIZ_TYPE = "crm_receivable_approve"; |
| | | |
| | | @Resource |
| | | private CrmReceivableMapper receivableMapper; |
| | |
| | | private AdminUserApi adminUserApi; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | @Resource |
| | | private BpmProcessInstanceApi bpmProcessInstanceApi; |
| | | @Resource |
| | | private ApprovalConfigApi approvalConfigApi; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | throw exception(RECEIVABLE_NO_EXISTS); |
| | | } |
| | | |
| | | // 2.1 插入回款(创建后即为未审核状态) |
| | | // 2.1 插入草稿;提交时再创建 BPM 流程 |
| | | CrmReceivableDO receivable = BeanUtils.toBean(createReqVO, CrmReceivableDO.class) |
| | | .setNo(no).setAuditStatus(CrmAuditStatusEnum.PROCESS.getStatus()); |
| | | .setNo(no).setAuditStatus(CrmAuditStatusEnum.DRAFT.getStatus()); |
| | | receivableMapper.insert(receivable); |
| | | // 2.2 |
| | | |
| | |
| | | // 1.5 校验可回款金额不超过该开票剩余可回款金额 |
| | | validateReceivablePriceExceedsInvoiceRemaining(updateReqVO); |
| | | |
| | | // 1.6 只有未审核,可以编辑; |
| | | if (ObjectUtil.notEqual(oldReceivable.getAuditStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { |
| | | // 1.6 只有草稿或驳回后可以编辑 |
| | | if (ObjectUtil.notEqual(oldReceivable.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus()) |
| | | && ObjectUtil.notEqual(oldReceivable.getAuditStatus(), CrmAuditStatusEnum.REJECT.getStatus())) { |
| | | throw exception(RECEIVABLE_UPDATE_FAIL_EDITING_PROHIBITED); |
| | | } |
| | | |
| | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateReceivableStatus(Long id, Integer status) { |
| | | boolean approve = CrmAuditStatusEnum.APPROVE.getStatus().equals(status); |
| | | // 1.1 校验存在 |
| | | @CrmPermission(bizType = CrmBizTypeEnum.CRM_RECEIVABLE, bizId = "#id", level = CrmPermissionLevelEnum.WRITE) |
| | | public void submitReceivable(Long id) { |
| | | CrmReceivableDO receivable = validateReceivableExists(id); |
| | | // 1.2 校验状态 |
| | | if (receivable.getAuditStatus().equals(status)) { |
| | | throw exception(approve ? RECEIVABLE_APPROVE_FAIL : RECEIVABLE_PROCESS_FAIL); |
| | | if (ObjectUtil.notEqual(receivable.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus()) |
| | | && ObjectUtil.notEqual(receivable.getAuditStatus(), CrmAuditStatusEnum.REJECT.getStatus())) { |
| | | throw exception(RECEIVABLE_SUBMIT_FAIL_NOT_DRAFT); |
| | | } |
| | | // 草稿期可能已产生其他回款,提交时重新校验合同及开票额度。 |
| | | CrmReceivableSaveReqVO req = new CrmReceivableSaveReqVO().setId(id) |
| | | .setContractId(receivable.getContractId()).setInvoiceId(receivable.getInvoiceId()) |
| | | .setCustomerId(receivable.getCustomerId()).setPrice(receivable.getPrice()); |
| | | validateInvoiceForReceivable(req); |
| | | validateReceivablePriceExceedsLimit(req); |
| | | validateReceivablePriceExceedsInvoiceRemaining(req); |
| | | approvalConfigApi.validateApprovalEnabledAndGetApprovers(RECEIVABLE_APPROVE_BIZ_TYPE); |
| | | int updateCount = receivableMapper.updateByIdAndStatus(id, receivable.getAuditStatus(), |
| | | new CrmReceivableDO().setAuditStatus(CrmAuditStatusEnum.PROCESS.getStatus())); |
| | | if (updateCount == 0) { |
| | | throw exception(RECEIVABLE_SUBMIT_FAIL_NOT_DRAFT); |
| | | } |
| | | String processInstanceId = bpmProcessInstanceApi.createProcessInstance(getLoginUserId(), |
| | | new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(RECEIVABLE_PROCESS_KEY) |
| | | .setBusinessKey(String.valueOf(id))); |
| | | receivableMapper.updateById(new CrmReceivableDO().setId(id).setProcessInstanceId(processInstanceId)); |
| | | } |
| | | |
| | | // 2. 更新状态 |
| | | int updateCount = receivableMapper.updateByIdAndStatus(id, receivable.getAuditStatus(), |
| | | new CrmReceivableDO().setAuditStatus(status)); |
| | | if (updateCount == 0) { |
| | | throw exception(approve ? RECEIVABLE_APPROVE_FAIL : RECEIVABLE_PROCESS_FAIL); |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateReceivableAuditStatus(Long id, Integer bpmStatus) { |
| | | Integer auditStatus; |
| | | if (BpmTaskStatusEnum.APPROVE.getStatus().equals(bpmStatus)) { |
| | | auditStatus = CrmAuditStatusEnum.APPROVE.getStatus(); |
| | | } else if (BpmTaskStatusEnum.REJECT.getStatus().equals(bpmStatus)) { |
| | | auditStatus = CrmAuditStatusEnum.REJECT.getStatus(); |
| | | } else if (BpmTaskStatusEnum.CANCEL.getStatus().equals(bpmStatus)) { |
| | | auditStatus = CrmAuditStatusEnum.CANCEL.getStatus(); |
| | | } else { |
| | | return; |
| | | } |
| | | if (receivableMapper.updateByIdAndStatus(id, CrmAuditStatusEnum.PROCESS.getStatus(), |
| | | new CrmReceivableDO().setAuditStatus(auditStatus)) != 1) { |
| | | log.warn("[updateReceivableAuditStatus] 回款({}) 已不处于审批中,忽略 BPM 状态({})", id, bpmStatus); |
| | | } |
| | | } |
| | | |
| | |
| | | if (receivable.getPlanId() != null && receivablePlanService.getReceivablePlan(receivable.getPlanId()) != null) { |
| | | throw exception(RECEIVABLE_DELETE_FAIL); |
| | | } |
| | | // 1.3 审批通过时,不允许删除 |
| | | if (ObjUtil.equal(receivable.getAuditStatus(), CrmAuditStatusEnum.APPROVE.getStatus())) { |
| | | // 审批中、审核通过不可删除 |
| | | if (ObjUtil.equal(receivable.getAuditStatus(), CrmAuditStatusEnum.APPROVE.getStatus()) |
| | | || ObjUtil.equal(receivable.getAuditStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { |
| | | throw exception(RECEIVABLE_DELETE_FAIL_IS_APPROVE); |
| | | } |
| | | |