| | |
| | | import cn.iocoder.yudao.module.crm.controller.admin.invoice.vo.invoice.CrmInvoicePageReqVO; |
| | | import cn.iocoder.yudao.module.crm.controller.admin.invoice.vo.invoice.CrmInvoiceSaveReqVO; |
| | | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; |
| | | import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; |
| | | import cn.iocoder.yudao.module.crm.dal.dataobject.invoice.CrmInvoiceDO; |
| | | import cn.iocoder.yudao.module.crm.dal.mysql.invoice.CrmInvoiceMapper; |
| | | import cn.iocoder.yudao.module.crm.dal.redis.no.CrmNoRedisDAO; |
| | |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | | import cn.iocoder.yudao.module.mdm.enums.MdmItemTypeEnum; |
| | | import com.mzt.logapi.context.LogRecordContext; |
| | | import com.mzt.logapi.service.impl.DiffParseFunction; |
| | | import com.mzt.logapi.starter.annotation.LogRecord; |
| | |
| | | private CrmContractService contractService; |
| | | @Resource |
| | | private CrmPermissionService permissionService; |
| | | @Resource |
| | | private MdmItemApi mdmItemApi; |
| | | |
| | | @Resource |
| | | private AdminUserApi adminUserApi; |
| | |
| | | public Long createInvoice(CrmInvoiceSaveReqVO createReqVO) { |
| | | // 1.1 校验关联数据存在(开票金额不再受合同金额限制,仅前端提示可开票金额) |
| | | validateRelationDataExists(createReqVO); |
| | | validateContractItemsInvoiceable(createReqVO.getContractId()); |
| | | // 1.3 生成开票编号 |
| | | String no = noRedisDAO.generate(CrmNoRedisDAO.INVOICE_PREFIX); |
| | | if (invoiceMapper.selectByNo(no) != null) { |
| | |
| | | throw exception(INVOICE_CREATE_FAIL_CONTRACT_NOT_APPROVE); |
| | | } |
| | | reqVO.setCustomerId(contract.getCustomerId()); // 设置客户编号 |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 合同中包含物料时不允许开票,只有产品类销售内容才可进入开票流程。 |
| | | */ |
| | | void validateContractItemsInvoiceable(Long contractId) { |
| | | if (contractId == null) { |
| | | return; |
| | | } |
| | | List<CrmContractProductDO> contractProducts = contractService.getContractProductListByContractId(contractId); |
| | | if (CollUtil.isEmpty(contractProducts)) { |
| | | return; |
| | | } |
| | | Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap( |
| | | CollectionUtils.convertSet(contractProducts, CrmContractProductDO::getItemId)); |
| | | boolean containsMaterial = contractProducts.stream() |
| | | .map(CrmContractProductDO::getItemId) |
| | | .map(itemMap::get) |
| | | .filter(ObjectUtil::isNotNull) |
| | | .anyMatch(item -> MdmItemTypeEnum.MATERIAL.getType().equals(item.getItemType())); |
| | | if (containsMaterial) { |
| | | throw exception(INVOICE_CREATE_FAIL_MATERIAL_NOT_ALLOWED); |
| | | } |
| | | } |
| | | |
| | |
| | | && ObjUtil.notEqual(invoice.getAuditStatus(), CrmAuditStatusEnum.REJECT.getStatus())) { |
| | | throw exception(INVOICE_SUBMIT_FAIL_NOT_EDITABLE); |
| | | } |
| | | validateContractItemsInvoiceable(invoice.getContractId()); |
| | | |
| | | // 2. 校验审批配置已启用且配置了有效审批人(未配置时抛出带明确提示的业务异常) |
| | | approvalConfigApi.validateApprovalEnabledAndGetApprovers(INVOICE_APPROVE_BIZ_TYPE); |