yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java
@@ -176,11 +176,12 @@ }); } @PutMapping("/submit") @Operation(summary = "æäº¤å款审æ¹") @PutMapping("/update-status") @Operation(summary = "æ´æ°å款çç¶æï¼å®¡æ ¸/åå®¡æ ¸ï¼") @PreAuthorize("@ss.hasPermission('crm:receivable:update')") public CommonResult<Boolean> submitContract(@RequestParam("id") Long id) { receivableService.submitReceivable(id, getLoginUserId()); public CommonResult<Boolean> updateReceivableStatus(@RequestParam("id") Long id, @RequestParam("status") Integer status) { receivableService.updateReceivableStatus(id, status); return success(true); } yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java
@@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.math.BigDecimal; @@ -35,6 +36,11 @@ return selectOne(CrmReceivableDO::getNo, no); } default int updateByIdAndStatus(Long id, Integer status, CrmReceivableDO updateObj) { return update(updateObj, new LambdaUpdateWrapper<CrmReceivableDO>() .eq(CrmReceivableDO::getId, id).eq(CrmReceivableDO::getAuditStatus, status)); } default PageResult<CrmReceivableDO> selectPageByCustomerId(CrmReceivablePageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX<CrmReceivableDO>() .eq(CrmReceivableDO::getCustomerId, reqVO.getCustomerId()) // å¿ é¡»ä¼ é yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java
@@ -47,6 +47,8 @@ ErrorCode RECEIVABLE_CREATE_FAIL_CONTRACT_NOT_APPROVE = new ErrorCode(1_020_004_006, "åå»ºåæ¬¾å¤±è´¥ï¼åå ï¼åå䏿¯å®¡æ ¸éè¿ç¶æ"); ErrorCode RECEIVABLE_CREATE_FAIL_PRICE_EXCEEDS_LIMIT = new ErrorCode(1_020_004_007, "åå»ºåæ¬¾å¤±è´¥ï¼åå ï¼å款éé¢è¶ åºååéé¢ï¼ç®åå©ä½å¯éï¼{} å "); ErrorCode RECEIVABLE_DELETE_FAIL_IS_APPROVE = new ErrorCode(1_020_004_008, "å é¤å款失败ï¼åå ï¼å款审æ¹å·²éè¿"); ErrorCode RECEIVABLE_APPROVE_FAIL = new ErrorCode(1_020_004_009, "å®¡æ ¸å¤±è´¥ï¼åªææªå®¡æ ¸ç忬¾æè½å®¡æ ¸"); ErrorCode RECEIVABLE_PROCESS_FAIL = new ErrorCode(1_020_004_010, "åå®¡æ ¸å¤±è´¥ï¼åªæå·²å®¡æ ¸ç忬¾æè½åå®¡æ ¸"); // ========== 忬¾è®¡å 1-020-005-000 ========== ErrorCode RECEIVABLE_PLAN_NOT_EXISTS = new ErrorCode(1_020_005_000, "忬¾è®¡åä¸åå¨"); yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableService.java
@@ -37,12 +37,12 @@ void updateReceivable(@Valid CrmReceivableSaveReqVO updateReqVO); /** * æ´æ°å款æµç¨å®¡æ¹ç»æ * æ´æ°å款çç¶æï¼å®¡æ ¸/åå®¡æ ¸ï¼ * * @param id 忬¾ç¼å· * @param bpmResult BPM 审æ¹ç»æ * @param id ç¼å· * @param status ç¶æ */ void updateReceivableAuditStatus(Long id, Integer bpmResult); void updateReceivableStatus(Long id, Integer status); /** * å é¤å款 @@ -50,14 +50,6 @@ * @param id ç¼å· */ void deleteReceivable(Long id); /** * åèµ·åæ¬¾å®¡æ¹æµç¨ * * @param id 忬¾ç¼å· * @param userId ç¨æ·ç¼å· */ void submitReceivable(Long id, Long userId); /** * è·å¾å款 yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java
@@ -8,9 +8,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivablePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; @@ -34,7 +31,6 @@ 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; @@ -46,7 +42,6 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; import static cn.iocoder.yudao.module.crm.util.CrmAuditStatusUtils.convertBpmResultToAuditStatus; /** * CRM 忬¾ Service å®ç°ç±» @@ -55,13 +50,7 @@ */ @Service @Validated @Slf4j public class CrmReceivableServiceImpl implements CrmReceivableService { /** * BPM ååå®¡æ¹æµç¨æ è¯ */ public static final String BPM_PROCESS_DEFINITION_KEY = "crm-receivable-audit"; @Resource private CrmReceivableMapper receivableMapper; @@ -81,8 +70,6 @@ @Resource private AdminUserApi adminUserApi; @Resource private BpmProcessInstanceApi bpmProcessInstanceApi; @Resource private StorageAttachmentApi storageAttachmentApi; @@ -105,9 +92,9 @@ throw exception(RECEIVABLE_NO_EXISTS); } // 2.1 æå ¥å款 // 2.1 æå ¥å款ï¼å建åå³ä¸ºæªå®¡æ ¸ç¶æï¼ CrmReceivableDO receivable = BeanUtils.toBean(createReqVO, CrmReceivableDO.class) .setNo(no).setAuditStatus(CrmAuditStatusEnum.DRAFT.getStatus()); .setNo(no).setAuditStatus(CrmAuditStatusEnum.PROCESS.getStatus()); receivableMapper.insert(receivable); // 2.2 @@ -240,9 +227,8 @@ // 1.5 æ ¡éªå¯å款éé¢ä¸è¶ è¿è¯¥å¼ç¥¨å©ä½å¯å款éé¢ validateReceivablePriceExceedsInvoiceRemaining(updateReqVO); // 1.6 åªæè稿ã审æ¹ä¸ï¼å¯ä»¥ç¼è¾ï¼ if (!ObjectUtils.equalsAny(oldReceivable.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { // 1.6 åªææªå®¡æ ¸ï¼å¯ä»¥ç¼è¾ï¼ if (ObjectUtil.notEqual(oldReceivable.getAuditStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { throw exception(RECEIVABLE_UPDATE_FAIL_EDITING_PROHIBITED); } @@ -266,19 +252,22 @@ } @Override public void updateReceivableAuditStatus(Long id, Integer bpmResult) { @Transactional(rollbackFor = Exception.class) public void updateReceivableStatus(Long id, Integer status) { boolean approve = CrmAuditStatusEnum.APPROVE.getStatus().equals(status); // 1.1 æ ¡éªåå¨ CrmReceivableDO receivable = validateReceivableExists(id); // 1.2 åªæå®¡æ¹ä¸ï¼å¯ä»¥æ´æ°å®¡æ¹ç»æ if (ObjUtil.notEqual(receivable.getAuditStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { log.error("[updateReceivableAuditStatus][receivable({}) ä¸å¤äºå®¡æ¹ä¸ï¼æ æ³æ´æ°å®¡æ¹ç»æ({})]", receivable.getId(), bpmResult); throw exception(RECEIVABLE_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS); // 1.2 æ ¡éªç¶æ if (receivable.getAuditStatus().equals(status)) { throw exception(approve ? RECEIVABLE_APPROVE_FAIL : RECEIVABLE_PROCESS_FAIL); } // 2. æ´æ°å款审æ¹ç¶æ Integer auditStatus = convertBpmResultToAuditStatus(bpmResult); receivableMapper.updateById(new CrmReceivableDO().setId(id).setAuditStatus(auditStatus)); // 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 @@ -306,29 +295,6 @@ // 3. è®°å½æä½æ¥å¿ä¸ä¸æ LogRecordContext.putVariable("receivable", receivable); LogRecordContext.putVariable("period", getReceivablePeriod(receivable.getPlanId())); } @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_RECEIVABLE_TYPE, subType = CRM_RECEIVABLE_SUBMIT_SUB_TYPE, bizNo = "{{#id}}", success = CRM_RECEIVABLE_SUBMIT_SUCCESS) public void submitReceivable(Long id, Long userId) { // 1. æ ¡éªå款æ¯å¦å¨å®¡æ¹ CrmReceivableDO receivable = validateReceivableExists(id); if (ObjUtil.notEqual(receivable.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus())) { throw exception(RECEIVABLE_SUBMIT_FAIL_NOT_DRAFT); } // 2. åå»ºåæ¬¾å®¡æ¹æµç¨å®ä¾ String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() .setProcessDefinitionKey(BPM_PROCESS_DEFINITION_KEY).setBusinessKey(String.valueOf(id))); // 3. æ´æ°åæ¬¾å·¥ä½æµç¼å· receivableMapper.updateById(new CrmReceivableDO().setId(id).setProcessInstanceId(processInstanceId) .setAuditStatus(CrmAuditStatusEnum.PROCESS.getStatus())); // 4. è®°å½æ¥å¿ LogRecordContext.putVariable("receivableNo", receivable.getNo()); } private CrmReceivableDO validateReceivableExists(Long id) { yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/listener/CrmReceivableStatusListener.java
ÎļþÒÑɾ³ý yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java
@@ -43,6 +43,7 @@ import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管çåå° - ERP 仿¬¾å") @RestController @@ -79,15 +80,23 @@ return success(true); } @PutMapping("/update-status") @Operation(summary = "æ´æ°ä»æ¬¾åçç¶æ") @PreAuthorize("@ss.hasPermission('erp:finance-payment:update-status')") public CommonResult<Boolean> updateFinancePaymentStatus(@RequestParam("id") Long id, @RequestParam("status") Integer status) { financePaymentService.updateFinancePaymentStatus(id, status); @PostMapping("/submit") @Operation(summary = "æäº¤ä»æ¬¾å审æ¹") @PreAuthorize("@ss.hasPermission('erp:finance-payment:update')") public CommonResult<Boolean> submitFinancePayment(@RequestParam("id") Long id, @RequestParam("processDefinitionKey") String processDefinitionKey) { Long userId = getLoginUserId(); financePaymentService.submitFinancePayment(id, processDefinitionKey, userId); return success(true); } @GetMapping("/approve-process-list") @Operation(summary = "è·å仿¬¾åå®¡æ¹æµç¨å表") @PreAuthorize("@ss.hasPermission('erp:finance-payment:query')") public CommonResult<List<Map<String, Object>>> getApproveProcessList() { return success(financePaymentService.getFinancePaymentApproveProcessDefinitionList()); } @DeleteMapping("/delete") @Operation(summary = "å é¤ä»æ¬¾å") @Parameter(name = "ids", description = "ç¼å·æ°ç»", required = true) yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java
@@ -26,6 +26,9 @@ @Schema(description = "仿¬¾ç¶æ", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer status; @Schema(description = "工使µç¼å·", example = "3cc7f8e6") private String processInstanceId; @Schema(description = "仿¬¾æ¶é´", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime paymentTime; yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInvoiceController.java
@@ -49,7 +49,6 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管çåå° - ERP éè´æ¥ç¥¨") @RestController @@ -170,11 +169,12 @@ }); } @PutMapping("/submit") @Operation(summary = "æäº¤æ¥ç¥¨å®¡æ¹") @PreAuthorize("@ss.hasPermission('erp:purchase-invoice:update')") public CommonResult<Boolean> submitPurchaseInvoice(@RequestParam("id") Long id) { invoiceService.submitPurchaseInvoice(id, getLoginUserId()); @PutMapping("/update-status") @Operation(summary = "æ´æ°æ¥ç¥¨çç¶æï¼å®¡æ ¸/åå®¡æ ¸ï¼") @PreAuthorize("@ss.hasPermission('erp:purchase-invoice:update-status')") public CommonResult<Boolean> updatePurchaseInvoiceStatus(@RequestParam("id") Long id, @RequestParam("status") Integer status) { invoiceService.updatePurchaseInvoiceStatus(id, status); return success(true); } yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentDO.java
@@ -42,6 +42,12 @@ */ private Integer status; /** * 工使µç¼å· * * å ³è BPM æµç¨å®ä¾ç id */ private String processInstanceId; /** * 仿¬¾æ¶é´ */ private LocalDateTime paymentTime; yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInvoiceMapper.java
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.invoice.ErpPurchaseInvoicePageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInvoiceDO; import cn.iocoder.yudao.module.erp.enums.ErpPurchaseInvoiceAuditStatusEnum; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.Collection; @@ -23,6 +24,11 @@ return selectOne(ErpPurchaseInvoiceDO::getNo, no); } default int updateByIdAndStatus(Long id, Integer status, ErpPurchaseInvoiceDO updateObj) { return update(updateObj, new LambdaUpdateWrapper<ErpPurchaseInvoiceDO>() .eq(ErpPurchaseInvoiceDO::getId, id).eq(ErpPurchaseInvoiceDO::getAuditStatus, status)); } default PageResult<ErpPurchaseInvoiceDO> selectPage(ErpPurchaseInvoicePageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX<ErpPurchaseInvoiceDO>() .likeIfPresent(ErpPurchaseInvoiceDO::getNo, reqVO.getNo()) yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java
@@ -57,13 +57,14 @@ // ========== ERP éè´æ¥ç¥¨ï¼1-030-105-000ï¼ ========== ErrorCode PURCHASE_INVOICE_NOT_EXISTS = new ErrorCode(1_030_105_000, "æ¥ç¥¨ä¸åå¨"); ErrorCode PURCHASE_INVOICE_NO_EXISTS = new ErrorCode(1_030_105_001, "çææ¥ç¥¨ç¼å·å¤±è´¥ï¼è¯·éæ°æäº¤"); ErrorCode PURCHASE_INVOICE_UPDATE_FAIL_EDITING_PROHIBITED = new ErrorCode(1_030_105_002, "æ¥ç¥¨({})䏿¯èç¨¿ç¶æï¼æ æ³ä¿®æ¹"); ErrorCode PURCHASE_INVOICE_UPDATE_FAIL_EDITING_PROHIBITED = new ErrorCode(1_030_105_002, "æ¥ç¥¨({})䏿¯æªå®¡æ ¸ç¶æï¼æ æ³ä¿®æ¹"); ErrorCode PURCHASE_INVOICE_DELETE_FAIL_IS_APPROVE = new ErrorCode(1_030_105_003, "å 餿¥ç¥¨å¤±è´¥ï¼åå ï¼æ¥ç¥¨å®¡æ¹å·²éè¿"); ErrorCode PURCHASE_INVOICE_SUBMIT_FAIL_NOT_DRAFT = new ErrorCode(1_030_105_004, "æ¥ç¥¨æäº¤å®¡æ ¸å¤±è´¥ï¼åå ï¼æ¥ç¥¨æ²¡å¤å¨æªæäº¤ç¶æ"); ErrorCode PURCHASE_INVOICE_UPDATE_AUDIT_STATUS_FAIL_NOT_PROCESS = new ErrorCode(1_030_105_005, "æ´æ°æ¥ç¥¨å®¡æ ¸ç¶æå¤±è´¥ï¼åå ï¼æ¥ç¥¨ä¸æ¯å®¡æ ¸ä¸ç¶æ"); ErrorCode PURCHASE_INVOICE_CREATE_FAIL_ORDER_NOT_APPROVE = new ErrorCode(1_030_105_006, "å建æ¥ç¥¨å¤±è´¥ï¼åå ï¼éè´è®¢å䏿¯å®¡æ ¸éè¿ç¶æ"); ErrorCode PURCHASE_INVOICE_CREATE_FAIL_SUPPLIER_MISMATCH = new ErrorCode(1_030_105_007, "å建æ¥ç¥¨å¤±è´¥ï¼åå ï¼æ¥ç¥¨ä¾åºåä¸éè´è®¢åä¸ä¸è´"); ErrorCode PURCHASE_INVOICE_CREATE_FAIL_PRICE_EXCEEDS_LIMIT = new ErrorCode(1_030_105_008, "å建æ¥ç¥¨å¤±è´¥ï¼åå ï¼æ¥ç¥¨éé¢è¶ åºéè´è®¢åéé¢ï¼ç®åå¯å¼ç¥¨ï¼{} å "); ErrorCode PURCHASE_INVOICE_APPROVE_FAIL = new ErrorCode(1_030_105_009, "å®¡æ ¸å¤±è´¥ï¼åªææªå®¡æ ¸çæ¥ç¥¨æè½å®¡æ ¸"); ErrorCode PURCHASE_INVOICE_PROCESS_FAIL = new ErrorCode(1_030_105_010, "åå®¡æ ¸å¤±è´¥ï¼åªæå·²å®¡æ ¸çæ¥ç¥¨æè½åå®¡æ ¸"); // ========== ERP éè´éè´§ï¼1-030-103-000ï¼ ========== ErrorCode PURCHASE_RETURN_NOT_EXISTS = new ErrorCode(1_030_103_000, "éè´éè´§åä¸åå¨"); @@ -196,6 +197,11 @@ ErrorCode FINANCE_PAYMENT_CREATE_FAIL_INVOICE_NOT_ATTACHMENT = new ErrorCode(1_030_601_008, "åå»ºä»æ¬¾å失败ï¼åå ï¼å ³èçæ¥ç¥¨æªä¸ä¼ å票éä»¶"); ErrorCode FINANCE_PAYMENT_CREATE_FAIL_INVOICE_SUPPLIER_MISMATCH = new ErrorCode(1_030_601_009, "åå»ºä»æ¬¾å失败ï¼åå ï¼å ³èçæ¥ç¥¨ä¸æéä¾åºåä¸å¹é "); ErrorCode FINANCE_PAYMENT_CREATE_FAIL_INVOICE_PRICE_EXCEEDS = new ErrorCode(1_030_601_010, "åå»ºä»æ¬¾å失败ï¼åå ï¼ä»æ¬¾éé¢è¶ åºè¯¥æ¥ç¥¨å©ä½å¯ä»éé¢ï¼ç®åå¯ä»ï¼{} å "); ErrorCode FINANCE_PAYMENT_SUBMIT_FAIL_STATUS = new ErrorCode(1_030_601_011, "æäº¤å®¡æ¹å¤±è´¥ï¼åªææªå®¡æ ¸ç¶æç仿¬¾åæè½æäº¤"); ErrorCode FINANCE_PAYMENT_BPM_CATEGORY_NOT_EXISTS = new ErrorCode(1_030_601_012, "仿¬¾å审æ¹åç±»ä¸åå¨ï¼è¯·å å¨BPM模åå建éè´å®¡æ ¸æµç¨åç±»"); ErrorCode FINANCE_PAYMENT_BPM_PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_030_601_013, "仿¬¾å审æ¹åç±»ä¸æ²¡æå¯ç¨çæµç¨æ¨¡åï¼è¯·å å建并å叿µç¨"); ErrorCode FINANCE_PAYMENT_UPDATE_FAIL_APPROVING = new ErrorCode(1_030_601_014, "仿¬¾å({})审æ¹ä¸ï¼æ æ³ä¿®æ¹"); ErrorCode FINANCE_PAYMENT_DELETE_FAIL_APPROVING = new ErrorCode(1_030_601_015, "仿¬¾å({})审æ¹ä¸ï¼æ æ³å é¤"); // ========== ERP æ¶æ¬¾å 1-030-602-000 ========== ErrorCode FINANCE_RECEIPT_NOT_EXISTS = new ErrorCode(1_030_602_000, "æ¶æ¬¾åä¸åå¨"); yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentService.java
@@ -35,12 +35,28 @@ void updateFinancePayment(@Valid ErpFinancePaymentSaveReqVO updateReqVO); /** * æ´æ°ä»æ¬¾åçç¶æ * æäº¤ä»æ¬¾åå®¡æ¹ * * @param id ç¼å· * @param status ç¶æ * @param processDefinitionKey æµç¨å®ä¹çç¼å· * @param userId ç¨æ·ç¼å· */ void updateFinancePaymentStatus(Long id, Integer status); void submitFinancePayment(Long id, String processDefinitionKey, Long userId); /** * è·å¾ä»æ¬¾åå®¡æ¹æµç¨å®ä¹å表 * * @return æµç¨å®ä¹å表 */ List<Map<String, Object>> getFinancePaymentApproveProcessDefinitionList(); /** * æ´æ°ä»æ¬¾åç审æ¹ç¶æï¼ç± BPM æµç¨å®ä¾çåè°è§¦åï¼ * * @param id ç¼å· * @param bpmResult BPM 审æ¹ç»æ */ void updateFinancePaymentAuditStatus(Long id, Integer bpmResult); /** * å é¤ä»æ¬¾å yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java
@@ -4,6 +4,13 @@ import cn.hutool.core.util.ObjectUtil; 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.dal.dataobject.definition.BpmProcessDefinitionInfoDO; import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum; import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryService; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO; @@ -20,15 +27,14 @@ import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 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.math.BigDecimal; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; @@ -41,7 +47,13 @@ */ @Service @Validated @Slf4j public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService { /** * BPM 仿¬¾å审æ¹åç±»ç¼ç */ private static final String BPM_PROCESS_DEFINITION_CATEGORY_CODE = "erp_finance_payment_approve"; @Resource private ErpFinancePaymentMapper financePaymentMapper; @@ -63,6 +75,13 @@ @Resource private StorageAttachmentApi storageAttachmentApi; @Resource private BpmProcessInstanceApi processInstanceApi; @Resource private BpmCategoryService bpmCategoryService; @Resource private BpmProcessDefinitionService bpmProcessDefinitionService; @Override @Transactional(rollbackFor = Exception.class) @@ -118,6 +137,9 @@ if (ErpAuditStatus.APPROVE.getStatus().equals(payment.getStatus())) { throw exception(FINANCE_PAYMENT_UPDATE_FAIL_APPROVE, payment.getNo()); } if (ErpAuditStatus.APPROVING.getStatus().equals(payment.getStatus())) { throw exception(FINANCE_PAYMENT_UPDATE_FAIL_APPROVING, payment.getNo()); } // 1.2 æ ¡éªä¾åºå supplierService.validateSupplier(updateReqVO.getSupplierId()); // 1.3 æ ¡éªç»ç®è´¦æ· @@ -155,21 +177,105 @@ @Override @Transactional(rollbackFor = Exception.class) public void updateFinancePaymentStatus(Long id, Integer status) { boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); // 1.1 æ ¡éªåå¨ public void submitFinancePayment(Long id, String processDefinitionKey, Long userId) { // 1. æ ¡éªåå¨ + æªå®¡æ ¸ç¶æ ErpFinancePaymentDO payment = validateFinancePaymentExists(id); // 1.2 æ ¡éªç¶æ if (payment.getStatus().equals(status)) { throw exception(approve ? FINANCE_PAYMENT_APPROVE_FAIL : FINANCE_PAYMENT_PROCESS_FAIL); if (!ErpAuditStatus.PROCESS.getStatus().equals(payment.getStatus())) { throw exception(FINANCE_PAYMENT_SUBMIT_FAIL_STATUS); } // 2. æ´æ°ç¶æ int updateCount = financePaymentMapper.updateByIdAndStatus(id, payment.getStatus(), new ErpFinancePaymentDO().setStatus(status)); if (updateCount == 0) { throw exception(approve ? FINANCE_PAYMENT_APPROVE_FAIL : FINANCE_PAYMENT_PROCESS_FAIL); // 2. å建 BPM æµç¨å®ä¾ String processInstanceId = processInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() .setProcessDefinitionKey(processDefinitionKey) .setBusinessKey(String.valueOf(id))); // 3. æ´æ°ä»æ¬¾åç¶æä¸ºå®¡æ¹ä¸ financePaymentMapper.updateById(new ErpFinancePaymentDO() .setId(id) .setStatus(ErpAuditStatus.APPROVING.getStatus()) .setProcessInstanceId(processInstanceId)); } @Override public List<Map<String, Object>> getFinancePaymentApproveProcessDefinitionList() { // 1. æ ¡éªåç±»åæµç¨å®ä¹æ¯å¦åå¨ validateFinancePaymentApproveCategoryAndProcessDefinition(); // 2. è·ååç±»ä¸çæµç¨å®ä¹ä¿¡æ¯ List<BpmProcessDefinitionInfoDO> definitionInfoList = bpmProcessDefinitionService .getProcessDefinitionInfoListByCategory(BPM_PROCESS_DEFINITION_CATEGORY_CODE); if (CollUtil.isEmpty(definitionInfoList)) { return Collections.emptyList(); } // 3. éåè·åæµç¨å®ä¹è¯¦æ ï¼è¿æ»¤æ¿æ´»ç¶æï¼ä¿çææ°çæ¬ Map<String, ProcessDefinition> latestVersionMap = new HashMap<>(); for (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); } } // 4. è¿åæµç¨å®ä¹å表 List<Map<String, Object>> result = new ArrayList<>(); for (ProcessDefinition pd : latestVersionMap.values()) { Map<String, Object> 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 updateFinancePaymentAuditStatus(Long id, Integer bpmResult) { // 1. æ ¡éªåå¨ ErpFinancePaymentDO payment = validateFinancePaymentExists(id); if (!ErpAuditStatus.APPROVING.getStatus().equals(payment.getStatus())) { log.warn("[updateFinancePaymentAuditStatus] 仿¬¾å({}) ä¸å¤äºå®¡æ¹ä¸ç¶æ", id); return; } // 2. æ ¹æ®å®¡æ¹ç»ææ´æ°ç¶æ Integer newStatus = convertBpmResultToAuditStatus(bpmResult); if (newStatus != null) { financePaymentMapper.updateById(new ErpFinancePaymentDO() .setId(id).setStatus(newStatus)); } } /** * æ ¡éªä»æ¬¾å审æ¹åç±»åæµç¨å®ä¹æ¯å¦åå¨ */ private void validateFinancePaymentApproveCategoryAndProcessDefinition() { // 1. æ ¡éªåç±»æ¯å¦åå¨ List<BpmCategoryDO> categories = bpmCategoryService.getCategoryListByCode( Collections.singletonList(BPM_PROCESS_DEFINITION_CATEGORY_CODE)); if (CollUtil.isEmpty(categories)) { throw exception(FINANCE_PAYMENT_BPM_CATEGORY_NOT_EXISTS); } } /** * è½¬æ¢ BPM 审æ¹ç»æä¸ºå®¡æ ¸ç¶æ */ private Integer convertBpmResultToAuditStatus(Integer bpmResult) { if (BpmTaskStatusEnum.APPROVE.getStatus().equals(bpmResult)) { return ErpAuditStatus.APPROVE.getStatus(); } else if (BpmTaskStatusEnum.REJECT.getStatus().equals(bpmResult)) { return ErpAuditStatus.PROCESS.getStatus(); } else if (BpmTaskStatusEnum.CANCEL.getStatus().equals(bpmResult)) { return ErpAuditStatus.CANCEL.getStatus(); } return null; } private List<ErpFinancePaymentItemDO> validateFinancePaymentItems( @@ -219,6 +325,9 @@ if (ErpAuditStatus.APPROVE.getStatus().equals(payment.getStatus())) { throw exception(FINANCE_PAYMENT_DELETE_FAIL_APPROVE, payment.getNo()); } if (ErpAuditStatus.APPROVING.getStatus().equals(payment.getStatus())) { throw exception(FINANCE_PAYMENT_DELETE_FAIL_APPROVING, payment.getNo()); } }); // 2. éåå é¤ï¼å¹¶è®°å½æä½æ¥å¿ yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/finance/listener/ErpFinancePaymentStatusListener.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,47 @@ package cn.iocoder.yudao.module.erp.service.finance.listener; import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent; import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEventListener; import cn.iocoder.yudao.module.erp.service.finance.ErpFinancePaymentService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; /** * 仿¬¾å审æ¹ç¶æçå¬å¨ * * çå¬ BPM æµç¨å®ä¾ç¶æåæ´äºä»¶ï¼æ´æ°ä»æ¬¾åç审æ¹ç¶æ * * @author è¶ çº§ç®¡çå */ @Component @Slf4j public class ErpFinancePaymentStatusListener extends BpmProcessInstanceStatusEventListener { /** * BPM 仿¬¾åå®¡æ¹æµç¨å®ä¹ key */ private static final String BPM_PROCESS_DEFINITION_KEY = "erp-finance-payment-audit"; @Resource private ErpFinancePaymentService financePaymentService; @Override protected String getProcessDefinitionKey() { return BPM_PROCESS_DEFINITION_KEY; } @Override protected void onEvent(BpmProcessInstanceStatusEvent event) { Long paymentId; try { paymentId = Long.parseLong(event.getBusinessKey()); } catch (NumberFormatException e) { log.warn("[onEvent] businessKey({}) 䏿¯ææç仿¬¾åç¼å·", event.getBusinessKey()); return; } log.info("[onEvent] æ¶å°BPM审æ¹äºä»¶ï¼paymentId={}, status={}", paymentId, event.getStatus()); financePaymentService.updateFinancePaymentAuditStatus(paymentId, event.getStatus()); } } yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInvoiceService.java
@@ -42,20 +42,12 @@ void deletePurchaseInvoice(Long id); /** * æäº¤æ¥ç¥¨å®¡æ¹ * æ´æ°æ¥ç¥¨çç¶æï¼å®¡æ ¸/åå®¡æ ¸ï¼ * * @param id ç¼å· * @param userId ç¨æ·ç¼å· * @param status ç¶æ */ void submitPurchaseInvoice(Long id, Long userId); /** * æ´æ°æ¥ç¥¨å®¡æ¹ç»æï¼BPM åè°ï¼ * * @param id ç¼å· * @param bpmResult BPM 审æ¹ç»æ */ void updatePurchaseInvoiceAuditStatus(Long id, Integer bpmResult); void updatePurchaseInvoiceStatus(Long id, Integer status); /** * è·å¾æ¥ç¥¨ yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInvoiceServiceImpl.java
@@ -5,9 +5,6 @@ import cn.hutool.core.util.ObjectUtil; 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.enums.task.BpmTaskStatusEnum; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.invoice.ErpPurchaseInvoicePageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.invoice.ErpPurchaseInvoiceSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInvoiceDO; @@ -17,7 +14,6 @@ import cn.iocoder.yudao.module.erp.enums.ErpPurchaseInvoiceAuditStatusEnum; import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -37,13 +33,7 @@ */ @Service @Validated @Slf4j public class ErpPurchaseInvoiceServiceImpl implements ErpPurchaseInvoiceService { /** * BPM æ¥ç¥¨å®¡æ¹æµç¨æ è¯ */ public static final String BPM_PROCESS_DEFINITION_KEY = "erp-purchase-invoice-audit"; /** * æ¥ç¥¨éä»¶çä¸å¡è®°å½ç±»åï¼å¯¹åº {@link cn.iocoder.yudao.module.system.enums.storage.StorageRecordTypeEnum#ERP_PURCHASE_INVOICE} @@ -60,8 +50,6 @@ private ErpPurchaseOrderService purchaseOrderService; @Resource private BpmProcessInstanceApi bpmProcessInstanceApi; @Resource private StorageAttachmentApi storageAttachmentApi; @Override @@ -77,9 +65,9 @@ throw exception(PURCHASE_INVOICE_NO_EXISTS); } // 2.1 æå ¥æ¥ç¥¨ // 2.1 æå ¥æ¥ç¥¨ï¼å建åå³ä¸ºæªå®¡æ ¸ç¶æï¼ ErpPurchaseInvoiceDO invoice = BeanUtils.toBean(createReqVO, ErpPurchaseInvoiceDO.class) .setNo(no).setAuditStatus(ErpPurchaseInvoiceAuditStatusEnum.DRAFT.getStatus()); .setNo(no).setAuditStatus(ErpPurchaseInvoiceAuditStatusEnum.PROCESS.getStatus()); invoiceMapper.insert(invoice); // 2.2 ç»å®å票éä»¶ @@ -123,8 +111,8 @@ Assert.notNull(updateReqVO.getId(), "æ¥ç¥¨ç¼å·ä¸è½ä¸ºç©º"); // 1.1 æ ¡éªåå¨ ErpPurchaseInvoiceDO oldInvoice = validatePurchaseInvoiceExists(updateReqVO.getId()); // 1.2 åªæè稿å¯ä»¥ç¼è¾ if (ObjectUtil.notEqual(oldInvoice.getAuditStatus(), ErpPurchaseInvoiceAuditStatusEnum.DRAFT.getStatus())) { // 1.2 åªææªå®¡æ ¸å¯ä»¥ç¼è¾ if (ObjectUtil.notEqual(oldInvoice.getAuditStatus(), ErpPurchaseInvoiceAuditStatusEnum.PROCESS.getStatus())) { throw exception(PURCHASE_INVOICE_UPDATE_FAIL_EDITING_PROHIBITED, oldInvoice.getNo()); } // 1.3 æ ¡éªå ³èæ°æ® + å¯å¼ç¥¨éé¢ @@ -157,51 +145,21 @@ @Override @Transactional(rollbackFor = Exception.class) public void submitPurchaseInvoice(Long id, Long userId) { // 1. æ ¡éªæ¥ç¥¨æ¯å¦å¨å®¡æ¹ public void updatePurchaseInvoiceStatus(Long id, Integer status) { boolean approve = ErpPurchaseInvoiceAuditStatusEnum.APPROVE.getStatus().equals(status); // 1.1 æ ¡éªåå¨ ErpPurchaseInvoiceDO invoice = validatePurchaseInvoiceExists(id); if (ObjectUtil.notEqual(invoice.getAuditStatus(), ErpPurchaseInvoiceAuditStatusEnum.DRAFT.getStatus())) { throw exception(PURCHASE_INVOICE_SUBMIT_FAIL_NOT_DRAFT); // 1.2 æ ¡éªç¶æ if (invoice.getAuditStatus().equals(status)) { throw exception(approve ? PURCHASE_INVOICE_APPROVE_FAIL : PURCHASE_INVOICE_PROCESS_FAIL); } // 1.1 éæ°æ ¡éªå¯å¼ç¥¨éé¢ï¼é²æ¢ç´¯è®¡æ¥ç¥¨è¶ è¿éè´è®¢åéé¢ï¼è稿æåå¯è½æå ¶ä»åè¿å ¥å®¡æ¹ä¸ï¼ validatePurchaseInvoicePriceExceedsLimit(new ErpPurchaseInvoiceSaveReqVO() .setId(invoice.getId()).setPurchaseOrderId(invoice.getPurchaseOrderId()) .setSupplierId(invoice.getSupplierId()).setPrice(invoice.getPrice())); // 2. å建æ¥ç¥¨å®¡æ¹æµç¨å®ä¾ String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() .setProcessDefinitionKey(BPM_PROCESS_DEFINITION_KEY).setBusinessKey(String.valueOf(id))); // 3. æ´æ°æ¥ç¥¨å·¥ä½æµç¼å· invoiceMapper.updateById(new ErpPurchaseInvoiceDO().setId(id).setProcessInstanceId(processInstanceId) .setAuditStatus(ErpPurchaseInvoiceAuditStatusEnum.PROCESS.getStatus())); // 2. æ´æ°ç¶æ int updateCount = invoiceMapper.updateByIdAndStatus(id, invoice.getAuditStatus(), new ErpPurchaseInvoiceDO().setAuditStatus(status)); if (updateCount == 0) { throw exception(approve ? PURCHASE_INVOICE_APPROVE_FAIL : PURCHASE_INVOICE_PROCESS_FAIL); } @Override public void updatePurchaseInvoiceAuditStatus(Long id, Integer bpmResult) { // 1. æ ¡éªåå¨ + 审æ¹ä¸ç¶æ ErpPurchaseInvoiceDO invoice = validatePurchaseInvoiceExists(id); if (ObjectUtil.notEqual(invoice.getAuditStatus(), ErpPurchaseInvoiceAuditStatusEnum.PROCESS.getStatus())) { log.warn("[updatePurchaseInvoiceAuditStatus][æ¥ç¥¨({}) ä¸å¤äºå®¡æ¹ä¸ï¼æ æ³æ´æ°å®¡æ¹ç»æ({})]", id, bpmResult); return; } // 2. æ ¹æ®å®¡æ¹ç»ææ´æ°ç¶æ Integer auditStatus = convertBpmResultToAuditStatus(bpmResult); if (auditStatus != null) { invoiceMapper.updateById(new ErpPurchaseInvoiceDO().setId(id).setAuditStatus(auditStatus)); } } private Integer convertBpmResultToAuditStatus(Integer bpmResult) { if (BpmTaskStatusEnum.APPROVE.getStatus().equals(bpmResult)) { return ErpPurchaseInvoiceAuditStatusEnum.APPROVE.getStatus(); } else if (BpmTaskStatusEnum.REJECT.getStatus().equals(bpmResult)) { return ErpPurchaseInvoiceAuditStatusEnum.REJECT.getStatus(); } else if (BpmTaskStatusEnum.CANCEL.getStatus().equals(bpmResult)) { return ErpPurchaseInvoiceAuditStatusEnum.CANCEL.getStatus(); } return null; } private ErpPurchaseInvoiceDO validatePurchaseInvoiceExists(Long id) { yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/listener/ErpPurchaseInvoiceStatusListener.java
ÎļþÒÑɾ³ý