| | |
| | | @LogRecord(type = CRM_INVOICE_TYPE, subType = CRM_INVOICE_CREATE_SUB_TYPE, bizNo = "{{#invoice.id}}", |
| | | success = CRM_INVOICE_CREATE_SUCCESS) |
| | | public Long createInvoice(CrmInvoiceSaveReqVO createReqVO) { |
| | | // 1.1 校验可开票金额超过上限 |
| | | validateInvoicePriceExceedsLimit(createReqVO); |
| | | // 1.2 校验关联数据存在 |
| | | // 1.1 校验关联数据存在(开票金额不再受合同金额限制,仅前端提示可开票金额) |
| | | validateRelationDataExists(createReqVO); |
| | | // 1.3 生成开票编号 |
| | | String no = noRedisDAO.generate(CrmNoRedisDAO.INVOICE_PREFIX); |
| | |
| | | return invoice.getId(); |
| | | } |
| | | |
| | | private void validateInvoicePriceExceedsLimit(CrmInvoiceSaveReqVO reqVO) { |
| | | // 1. 计算剩余可开票金额,不包括 reqVO 自身(审批中也占用额度,防止累计开票超过合同金额) |
| | | CrmContractDO contract = contractService.validateContract(reqVO.getContractId()); |
| | | List<CrmInvoiceDO> invoices = invoiceMapper.selectListByContractIdAndStatus(reqVO.getContractId(), |
| | | List.of(CrmAuditStatusEnum.APPROVE.getStatus(), CrmAuditStatusEnum.PROCESS.getStatus())); |
| | | if (reqVO.getId() != null) { |
| | | invoices.removeIf(invoice -> ObjectUtil.equal(invoice.getId(), reqVO.getId())); |
| | | } |
| | | BigDecimal notInvoicePrice = contract.getTotalPrice().subtract( |
| | | CollectionUtils.getSumValue(invoices, CrmInvoiceDO::getPrice, BigDecimal::add, BigDecimal.ZERO)); |
| | | // 2. 校验金额是否超过 |
| | | if (reqVO.getPrice().compareTo(notInvoicePrice) > 0) { |
| | | throw exception(INVOICE_CREATE_FAIL_PRICE_EXCEEDS_LIMIT, notInvoicePrice); |
| | | } |
| | | } |
| | | |
| | | private void validateRelationDataExists(CrmInvoiceSaveReqVO reqVO) { |
| | | if (reqVO.getOwnerUserId() != null) { |
| | | adminUserApi.validateUser(reqVO.getOwnerUserId()); // 校验负责人存在 |
| | |
| | | CrmInvoiceDO oldInvoice = validateInvoiceExists(updateReqVO.getId()); |
| | | updateReqVO.setOwnerUserId(oldInvoice.getOwnerUserId()).setCustomerId(oldInvoice.getCustomerId()) |
| | | .setContractId(oldInvoice.getContractId()); // 设置已存在的值 |
| | | // 1.2 校验可开票金额超过上限 |
| | | validateInvoicePriceExceedsLimit(updateReqVO); |
| | | |
| | | // 1.3 只有草稿、审核不通过,可以编辑; |
| | | // 1.2 只有草稿、审核不通过,可以编辑; |
| | | if (!ObjectUtils.equalsAny(oldInvoice.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(), |
| | | CrmAuditStatusEnum.REJECT.getStatus())) { |
| | | throw exception(INVOICE_UPDATE_FAIL_EDITING_PROHIBITED); |
| | |
| | | throw exception(INVOICE_SUBMIT_FAIL_NOT_EDITABLE); |
| | | } |
| | | |
| | | // 2. 重新校验可开票金额,防止累计开票超过合同金额(草稿期后可能有其他单进入审批中) |
| | | validateInvoicePriceExceedsLimit(new CrmInvoiceSaveReqVO() |
| | | .setId(invoice.getId()).setContractId(invoice.getContractId()).setPrice(invoice.getPrice())); |
| | | |
| | | // 3. 校验审批配置已启用且配置了有效审批人(未配置时抛出带明确提示的业务异常) |
| | | // 2. 校验审批配置已启用且配置了有效审批人(未配置时抛出带明确提示的业务异常) |
| | | approvalConfigApi.validateApprovalEnabledAndGetApprovers(INVOICE_APPROVE_BIZ_TYPE); |
| | | |
| | | // 4. 状态置为审批中,并清空上一轮审核结果,避免残留「审核不通过」的原因 |