Jelajahi Sumber

✨ ERP:初始化 payment 付款单的逻辑 30%

YunaiV 1 tahun lalu
induk
melakukan
0d551a4408
44 mengubah file dengan 1063 tambahan dan 702 penghapusan
  1. 9 0
      yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java
  2. 43 0
      yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/common/ErpBizTypeEnum.java
  3. 3 3
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java
  4. 145 0
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java
  5. 1 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountPageReqVO.java
  6. 1 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java
  7. 1 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountSaveReqVO.java
  8. 48 0
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentPageReqVO.java
  9. 95 0
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java
  10. 78 0
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java
  11. 2 2
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java
  12. 9 10
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java
  13. 1 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java
  14. 2 2
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java
  15. 1 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java
  16. 1 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java
  17. 2 2
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java
  18. 1 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java
  19. 2 2
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java
  20. 1 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java
  21. 1 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java
  22. 86 0
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentDO.java
  23. 75 0
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentItemDO.java
  24. 1 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java
  25. 30 0
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentItemMapper.java
  26. 48 0
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentMapper.java
  27. 5 0
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java
  28. 2 2
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java
  29. 2 2
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java
  30. 84 0
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentService.java
  31. 241 0
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java
  32. 8 0
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java
  33. 11 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java
  34. 1 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java
  35. 8 0
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java
  36. 11 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java
  37. 1 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java
  38. 1 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java
  39. 1 1
      yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java
  40. 0 142
      yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImplTest.java
  41. 0 131
      yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java
  42. 0 131
      yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java
  43. 0 131
      yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImplTest.java
  44. 0 126
      yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImplTest.java

+ 9 - 0
yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java

@@ -33,6 +33,7 @@ ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_00
     ErrorCode PURCHASE_IN_APPROVE_FAIL = new ErrorCode(1_030_102_003, "审核失败,只有未审核的入库单才能审核");
     ErrorCode PURCHASE_IN_NO_EXISTS = new ErrorCode(1_030_102_004, "生成入库单失败,请重新提交");
     ErrorCode PURCHASE_IN_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_102_005, "采购入库单({})已审核,无法修改");
+    ErrorCode PURCHASE_IN_NOT_APPROVE = new ErrorCode(1_030_102_006, "采购入库单未审核,无法操作");
 
     // ========== ERP 采购退货(1-030-103-000) ==========
     ErrorCode PURCHASE_RETURN_NOT_EXISTS = new ErrorCode(1_030_103_000, "采购退货单不存在");
@@ -41,6 +42,7 @@ ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_00
     ErrorCode PURCHASE_RETURN_APPROVE_FAIL = new ErrorCode(1_030_103_003, "审核失败,只有未审核的退货单才能审核");
     ErrorCode PURCHASE_RETURN_NO_EXISTS = new ErrorCode(1_030_103_004, "生成退货单失败,请重新提交");
     ErrorCode PURCHASE_RETURN_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_103_005, "采购退货单({})已审核,无法修改");
+    ErrorCode PURCHASE_RETURN_NOT_APPROVE = new ErrorCode(1_030_103_006, "采购退货单未审核,无法操作");
 
     // ========== ERP 客户(1-030-200-000)==========
     ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_200_000, "客户不存在");
@@ -137,4 +139,11 @@ ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_00
     ErrorCode ACCOUNT_NOT_EXISTS = new ErrorCode(1_030_600_000, "结算账户不存在");
     ErrorCode ACCOUNT_NOT_ENABLE = new ErrorCode(1_030_600_001, "结算账户({})未启用");
 
+    // ========== ERP 付款单 1-030-601-000 ==========
+    ErrorCode FINANCE_PAYMENT_NOT_EXISTS = new ErrorCode(1_030_601_000, "付款单不存在");
+    ErrorCode FINANCE_PAYMENT_DELETE_FAIL_APPROVE = new ErrorCode(1_030_601_001, "付款单({})已审核,无法删除");
+    ErrorCode FINANCE_PAYMENT_PROCESS_FAIL = new ErrorCode(1_030_601_002, "反审核失败,只有已审核的付款单才能反审核");
+    ErrorCode FINANCE_PAYMENT_APPROVE_FAIL = new ErrorCode(1_030_601_003, "审核失败,只有未审核的付款单才能审核");
+    ErrorCode FINANCE_PAYMENT_NO_EXISTS = new ErrorCode(1_030_601_004, "生成付款单号失败,请重新提交");
+
 }

+ 43 - 0
yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/common/ErpBizTypeEnum.java

@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.erp.enums.common;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Arrays;
+
+/**
+ * ERP 业务类型枚举
+ *
+ * @author HUIHUI
+ */
+@RequiredArgsConstructor
+@Getter
+public enum ErpBizTypeEnum implements IntArrayValuable {
+
+    PURCHASE_ORDER(10, "采购订单"),
+    PURCHASE_IN(11, "采购入库"),
+    PURCHASE_RETURN(12, "采购退货"),
+
+    SALE_ORDER(20, "销售订单"),
+    SALE_OUT(21, "销售订单"),
+    SALE_RETURN(22, "销售退货"),
+    ;
+
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpBizTypeEnum::getType).toArray();
+
+    /**
+     * 类型
+     */
+    private final Integer type;
+    /**
+     * 名称
+     */
+    private final String name;
+
+    @Override
+    public int[] array() {
+        return ARRAYS;
+    }
+
+}

+ 3 - 3
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java

@@ -7,9 +7,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
-import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountPageReqVO;
-import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountRespVO;
-import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountSaveReqVO;
+import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountPageReqVO;
+import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountRespVO;
+import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountSaveReqVO;
 import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO;
 import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService;
 import io.swagger.v3.oas.annotations.Operation;

+ 145 - 0
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java

@@ -0,0 +1,145 @@
+package cn.iocoder.yudao.module.erp.controller.admin.finance;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
+import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentPageReqVO;
+import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentRespVO;
+import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentSaveReqVO;
+import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO;
+import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO;
+import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO;
+import cn.iocoder.yudao.module.erp.service.finance.ErpFinancePaymentService;
+import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+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.operatelog.core.enums.OperateTypeEnum.EXPORT;
+
+@Tag(name = "管理后台 - ERP 付款单")
+@RestController
+@RequestMapping("/erp/finance-payment")
+@Validated
+public class ErpFinancePaymentController {
+
+    @Resource
+    private ErpFinancePaymentService financePaymentService;
+    @Resource
+    private ErpSupplierService supplierService;
+
+    @Resource
+    private AdminUserApi adminUserApi;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建付款单")
+    @PreAuthorize("@ss.hasPermission('erp:finance-payment:create')")
+    public CommonResult<Long> createFinancePayment(@Valid @RequestBody ErpFinancePaymentSaveReqVO createReqVO) {
+        return success(financePaymentService.createFinancePayment(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新付款单")
+    @PreAuthorize("@ss.hasPermission('erp:finance-payment:update')")
+    public CommonResult<Boolean> updateFinancePayment(@Valid @RequestBody ErpFinancePaymentSaveReqVO updateReqVO) {
+        financePaymentService.updateFinancePayment(updateReqVO);
+        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);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除付款单")
+    @Parameter(name = "ids", description = "编号数组", required = true)
+    @PreAuthorize("@ss.hasPermission('erp:finance-payment:delete')")
+    public CommonResult<Boolean> deleteFinancePayment(@RequestParam("ids") List<Long> ids) {
+        financePaymentService.deleteFinancePayment(ids);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得付款单")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('erp:finance-payment:query')")
+    public CommonResult<ErpFinancePaymentRespVO> getFinancePayment(@RequestParam("id") Long id) {
+        ErpFinancePaymentDO payment = financePaymentService.getFinancePayment(id);
+        if (payment == null) {
+            return success(null);
+        }
+        List<ErpFinancePaymentItemDO> paymentItemList = financePaymentService.getFinancePaymentItemListByPaymentId(id);
+        return success(BeanUtils.toBean(payment, ErpFinancePaymentRespVO.class, financePaymentVO ->
+                financePaymentVO.setItems(BeanUtils.toBean(paymentItemList, ErpFinancePaymentRespVO.Item.class))));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得付款单分页")
+    @PreAuthorize("@ss.hasPermission('erp:finance-payment:query')")
+    public CommonResult<PageResult<ErpFinancePaymentRespVO>> getFinancePaymentPage(@Valid ErpFinancePaymentPageReqVO pageReqVO) {
+        PageResult<ErpFinancePaymentDO> pageResult = financePaymentService.getFinancePaymentPage(pageReqVO);
+        return success(buildFinancePaymentVOPageResult(pageResult));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出付款单 Excel")
+    @PreAuthorize("@ss.hasPermission('erp:finance-payment:export')")
+    @OperateLog(type = EXPORT)
+    public void exportFinancePaymentExcel(@Valid ErpFinancePaymentPageReqVO pageReqVO,
+                                         HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<ErpFinancePaymentRespVO> list = buildFinancePaymentVOPageResult(financePaymentService.getFinancePaymentPage(pageReqVO)).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "付款单.xls", "数据", ErpFinancePaymentRespVO.class, list);
+    }
+
+    private PageResult<ErpFinancePaymentRespVO> buildFinancePaymentVOPageResult(PageResult<ErpFinancePaymentDO> pageResult) {
+        if (CollUtil.isEmpty(pageResult.getList())) {
+            return PageResult.empty(pageResult.getTotal());
+        }
+        // 1.1 付款项
+        List<ErpFinancePaymentItemDO> paymentItemList = financePaymentService.getFinancePaymentItemListByPaymentIds(
+                convertSet(pageResult.getList(), ErpFinancePaymentDO::getId));
+        Map<Long, List<ErpFinancePaymentItemDO>> financePaymentItemMap = convertMultiMap(paymentItemList, ErpFinancePaymentItemDO::getPaymentId);
+        // 1.2 供应商信息
+        Map<Long, ErpSupplierDO> supplierMap = supplierService.getSupplierMap(
+                convertSet(pageResult.getList(), ErpFinancePaymentDO::getSupplierId));
+        // 1.3 管理员信息
+        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(pageResult.getList(),
+                contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getFinanceUserId())));
+        // 2. 开始拼接
+        return BeanUtils.toBean(pageResult, ErpFinancePaymentRespVO.class, payment -> {
+            payment.setItems(BeanUtils.toBean(financePaymentItemMap.get(payment.getId()), ErpFinancePaymentRespVO.Item.class));
+            MapUtils.findAndThen(supplierMap, payment.getSupplierId(), supplier -> payment.setSupplierName(supplier.getName()));
+            MapUtils.findAndThen(userMap, Long.parseLong(payment.getCreator()), user -> payment.setCreatorName(user.getNickname()));
+            MapUtils.findAndThen(userMap, payment.getFinanceUserId(), user -> payment.setFinanceUserName(user.getNickname()));
+        });
+    }
+
+}

+ 1 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountPageReqVO.java → yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountPageReqVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.erp.controller.admin.finance.vo;
+package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account;
 
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import io.swagger.v3.oas.annotations.media.Schema;

+ 1 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountRespVO.java → yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.erp.controller.admin.finance.vo;
+package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account;
 
 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
 import cn.iocoder.yudao.module.system.enums.DictTypeConstants;

+ 1 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountSaveReqVO.java → yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountSaveReqVO.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.erp.controller.admin.finance.vo;
+package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account;
 
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.validation.InEnum;

+ 48 - 0
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentPageReqVO.java

@@ -0,0 +1,48 @@
+package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - ERP 付款单分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class ErpFinancePaymentPageReqVO extends PageParam {
+
+    @Schema(description = "采购单编号", example = "XS001")
+    private String no;
+
+    @Schema(description = "付款时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] paymentTime;
+
+    @Schema(description = "供应商编号", example = "1724")
+    private Long supplierId;
+
+    @Schema(description = "创建者", example = "666")
+    private String creator;
+
+    @Schema(description = "财务人员编号", example = "888")
+    private String financeUserId;
+
+    @Schema(description = "结算账户编号", example = "31189")
+    private Long accountId;
+
+    @Schema(description = "付款状态", example = "2")
+    private Integer status;
+
+    @Schema(description = "备注", example = "你猜")
+    private String remark;
+
+    @Schema(description = "业务编号", example = "123")
+    private String bizNo;
+
+}

+ 95 - 0
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java

@@ -0,0 +1,95 @@
+package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Schema(description = "管理后台 - ERP 付款单 Response VO")
+@Data
+public class ErpFinancePaymentRespVO {
+
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752")
+    private Long id;
+
+    @Schema(description = "付款单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "FKD888")
+    private String no;
+
+    @Schema(description = "付款状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    private Integer status;
+
+    @Schema(description = "付款时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    private LocalDateTime paymentTime;
+
+    @Schema(description = "财务人员编号", example = "19690")
+    private Long financeUserId;
+    @Schema(description = "财务人员名称", example = "张三")
+    private String financeUserName;
+
+    @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29399")
+    private Long supplierId;
+    @Schema(description = "供应商名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小番茄公司")
+    private String supplierName;
+
+    @Schema(description = "付款账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28989")
+    private Long accountId;
+
+    @Schema(description = "合计价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "13832")
+    private BigDecimal totalPrice;
+
+    @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "11600")
+    private BigDecimal discountPrice;
+
+    @Schema(description = "实际价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000")
+    private BigDecimal paymentPrice;
+
+    @Schema(description = "备注", example = "你猜")
+    private String remark;
+
+    @Schema(description = "创建人", example = "芋道")
+    private String creator;
+    @Schema(description = "创建人名称", example = "芋道")
+    private String creatorName;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    @Schema(description = "付款项列表", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<Item> items;
+
+    @Data
+    public static class Item {
+
+        @Schema(description = "付款项编号", example = "11756")
+        private Long id;
+
+        @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+        private Integer bizType;
+
+        @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756")
+        private Long bizId;
+
+        @Schema(description = "业务单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756")
+        private String bizNo;
+
+        @Schema(description = "应付欠款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000")
+        private BigDecimal totalPrice;
+
+        @Schema(description = "已付欠款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000")
+        private BigDecimal paidPrice;
+
+        @Schema(description = "本次付款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000")
+        @NotNull(message = "本次付款不能为空")
+        private BigDecimal paymentPrice;
+
+        @Schema(description = "备注", example = "随便")
+        private String remark;
+
+    }
+
+}

+ 78 - 0
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java

@@ -0,0 +1,78 @@
+package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Schema(description = "管理后台 - ERP 付款单新增/修改 Request VO")
+@Data
+public class ErpFinancePaymentSaveReqVO {
+
+    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752")
+    private Long id;
+
+    @Schema(description = "付款单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "FKD888")
+    @NotEmpty(message = "付款单号不能为空")
+    private String no;
+
+    @Schema(description = "付款时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "付款时间不能为空")
+    private LocalDateTime paymentTime;
+
+    @Schema(description = "财务人员编号", example = "19690")
+    private Long financeUserId;
+
+    @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29399")
+    @NotNull(message = "供应商编号不能为空")
+    private Long supplierId;
+
+    @Schema(description = "付款账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28989")
+    @NotNull(message = "付款账户编号不能为空")
+    private Long accountId;
+
+    @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "11600")
+    @NotNull(message = "优惠金额不能为空")
+    private BigDecimal discountPrice;
+
+    @Schema(description = "备注", example = "你猜")
+    private String remark;
+
+    @Schema(description = "付款项列表", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotEmpty(message = "付款项列表不能为空")
+    @Valid
+    private List<Item> items;
+
+    @Data
+    public static class Item {
+
+        @Schema(description = "付款项编号", example = "11756")
+        private Long id;
+
+        @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+        @NotNull(message = "业务类型不能为空")
+        private Integer bizType;
+
+        @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756")
+        @NotNull(message = "业务编号不能为空")
+        private Long bizId;
+
+        @Schema(description = "已付欠款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000")
+        @NotNull(message = "已付欠款不能为空")
+        private BigDecimal paidPrice;
+
+        @Schema(description = "本次付款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000")
+        @NotNull(message = "本次付款不能为空")
+        private BigDecimal paymentPrice;
+
+        @Schema(description = "备注", example = "随便")
+        private String remark;
+
+    }
+
+}

+ 2 - 2
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java

@@ -138,7 +138,7 @@ public class ErpPurchaseInController {
         if (CollUtil.isEmpty(pageResult.getList())) {
             return PageResult.empty(pageResult.getTotal());
         }
-        // 1.1 库项
+        // 1.1 库项
         List<ErpPurchaseInItemDO> purchaseInItemList = purchaseInService.getPurchaseInItemListByInIds(
                 convertSet(pageResult.getList(), ErpPurchaseInDO::getId));
         Map<Long, List<ErpPurchaseInItemDO>> purchaseInItemMap = convertMultiMap(purchaseInItemList, ErpPurchaseInItemDO::getInId);
@@ -150,7 +150,7 @@ public class ErpPurchaseInController {
                 convertSet(pageResult.getList(), ErpPurchaseInDO::getSupplierId));
         // 1.4 管理员信息
         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
-                convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator())));
+                convertSet(pageResult.getList(), purchaseIn -> Long.parseLong(purchaseIn.getCreator())));
         // 2. 开始拼接
         return BeanUtils.toBean(pageResult, ErpPurchaseInRespVO.class, purchaseIn -> {
             purchaseIn.setItems(BeanUtils.toBean(purchaseInItemMap.get(purchaseIn.getId()), ErpPurchaseInRespVO.Item.class,

+ 9 - 10
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java

@@ -41,7 +41,6 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
 
-
 @Tag(name = "管理后台 - ERP 采购订单")
 @RestController
 @RequestMapping("/erp/purchase-order")
@@ -62,14 +61,14 @@ public class ErpPurchaseOrderController {
 
     @PostMapping("/create")
     @Operation(summary = "创建采购订单")
-    @PreAuthorize("@ss.hasPermission('erp:purchase-out:create')")
+    @PreAuthorize("@ss.hasPermission('erp:purchase-create:create')")
     public CommonResult<Long> createPurchaseOrder(@Valid @RequestBody ErpPurchaseOrderSaveReqVO createReqVO) {
         return success(purchaseOrderService.createPurchaseOrder(createReqVO));
     }
 
     @PutMapping("/update")
     @Operation(summary = "更新采购订单")
-    @PreAuthorize("@ss.hasPermission('erp:purchase-out:update')")
+    @PreAuthorize("@ss.hasPermission('erp:purchase-create:update')")
     public CommonResult<Boolean> updatePurchaseOrder(@Valid @RequestBody ErpPurchaseOrderSaveReqVO updateReqVO) {
         purchaseOrderService.updatePurchaseOrder(updateReqVO);
         return success(true);
@@ -77,7 +76,7 @@ public class ErpPurchaseOrderController {
 
     @PutMapping("/update-status")
     @Operation(summary = "更新采购订单的状态")
-    @PreAuthorize("@ss.hasPermission('erp:purchase-out:update-status')")
+    @PreAuthorize("@ss.hasPermission('erp:purchase-create:update-status')")
     public CommonResult<Boolean> updatePurchaseOrderStatus(@RequestParam("id") Long id,
                                                       @RequestParam("status") Integer status) {
         purchaseOrderService.updatePurchaseOrderStatus(id, status);
@@ -87,7 +86,7 @@ public class ErpPurchaseOrderController {
     @DeleteMapping("/delete")
     @Operation(summary = "删除采购订单")
     @Parameter(name = "ids", description = "编号数组", required = true)
-    @PreAuthorize("@ss.hasPermission('erp:purchase-out:delete')")
+    @PreAuthorize("@ss.hasPermission('erp:purchase-create:delete')")
     public CommonResult<Boolean> deletePurchaseOrder(@RequestParam("ids") List<Long> ids) {
         purchaseOrderService.deletePurchaseOrder(ids);
         return success(true);
@@ -96,7 +95,7 @@ public class ErpPurchaseOrderController {
     @GetMapping("/get")
     @Operation(summary = "获得采购订单")
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('erp:purchase-out:query')")
+    @PreAuthorize("@ss.hasPermission('erp:purchase-create:query')")
     public CommonResult<ErpPurchaseOrderRespVO> getPurchaseOrder(@RequestParam("id") Long id) {
         ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.getPurchaseOrder(id);
         if (purchaseOrder == null) {
@@ -116,7 +115,7 @@ public class ErpPurchaseOrderController {
 
     @GetMapping("/page")
     @Operation(summary = "获得采购订单分页")
-    @PreAuthorize("@ss.hasPermission('erp:purchase-out:query')")
+    @PreAuthorize("@ss.hasPermission('erp:purchase-create:query')")
     public CommonResult<PageResult<ErpPurchaseOrderRespVO>> getPurchaseOrderPage(@Valid ErpPurchaseOrderPageReqVO pageReqVO) {
         PageResult<ErpPurchaseOrderDO> pageResult = purchaseOrderService.getPurchaseOrderPage(pageReqVO);
         return success(buildPurchaseOrderVOPageResult(pageResult));
@@ -124,7 +123,7 @@ public class ErpPurchaseOrderController {
 
     @GetMapping("/export-excel")
     @Operation(summary = "导出采购订单 Excel")
-    @PreAuthorize("@ss.hasPermission('erp:purchase-out:export')")
+    @PreAuthorize("@ss.hasPermission('erp:purchase-create:export')")
     @OperateLog(type = EXPORT)
     public void exportPurchaseOrderExcel(@Valid ErpPurchaseOrderPageReqVO pageReqVO,
                                     HttpServletResponse response) throws IOException {
@@ -138,7 +137,7 @@ public class ErpPurchaseOrderController {
         if (CollUtil.isEmpty(pageResult.getList())) {
             return PageResult.empty(pageResult.getTotal());
         }
-        // 1.1 出库
+        // 1.1 订单
         List<ErpPurchaseOrderItemDO> purchaseOrderItemList = purchaseOrderService.getPurchaseOrderItemListByOrderIds(
                 convertSet(pageResult.getList(), ErpPurchaseOrderDO::getId));
         Map<Long, List<ErpPurchaseOrderItemDO>> purchaseOrderItemMap = convertMultiMap(purchaseOrderItemList, ErpPurchaseOrderItemDO::getOrderId);
@@ -150,7 +149,7 @@ public class ErpPurchaseOrderController {
                 convertSet(pageResult.getList(), ErpPurchaseOrderDO::getSupplierId));
         // 1.4 管理员信息
         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
-                convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator())));
+                convertSet(pageResult.getList(), purchaseOrder -> Long.parseLong(purchaseOrder.getCreator())));
         // 2. 开始拼接
         return BeanUtils.toBean(pageResult, ErpPurchaseOrderRespVO.class, purchaseOrder -> {
             purchaseOrder.setItems(BeanUtils.toBean(purchaseOrderItemMap.get(purchaseOrder.getId()), ErpPurchaseOrderRespVO.Item.class,

+ 1 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java

@@ -150,7 +150,7 @@ public class ErpPurchaseReturnController {
                 convertSet(pageResult.getList(), ErpPurchaseReturnDO::getSupplierId));
         // 1.4 管理员信息
         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
-                convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator())));
+                convertSet(pageResult.getList(), purchaseReturn -> Long.parseLong(purchaseReturn.getCreator())));
         // 2. 开始拼接
         return BeanUtils.toBean(pageResult, ErpPurchaseReturnRespVO.class, purchaseReturn -> {
             purchaseReturn.setItems(BeanUtils.toBean(purchaseReturnItemMap.get(purchaseReturn.getId()), ErpPurchaseReturnRespVO.Item.class,

+ 2 - 2
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java

@@ -138,7 +138,7 @@ public class ErpSaleOrderController {
         if (CollUtil.isEmpty(pageResult.getList())) {
             return PageResult.empty(pageResult.getTotal());
         }
-        // 1.1 出库
+        // 1.1 订单
         List<ErpSaleOrderItemDO> saleOrderItemList = saleOrderService.getSaleOrderItemListByOrderIds(
                 convertSet(pageResult.getList(), ErpSaleOrderDO::getId));
         Map<Long, List<ErpSaleOrderItemDO>> saleOrderItemMap = convertMultiMap(saleOrderItemList, ErpSaleOrderItemDO::getOrderId);
@@ -150,7 +150,7 @@ public class ErpSaleOrderController {
                 convertSet(pageResult.getList(), ErpSaleOrderDO::getCustomerId));
         // 1.4 管理员信息
         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
-                convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator())));
+                convertSet(pageResult.getList(), saleOrder -> Long.parseLong(saleOrder.getCreator())));
         // 2. 开始拼接
         return BeanUtils.toBean(pageResult, ErpSaleOrderRespVO.class, saleOrder -> {
             saleOrder.setItems(BeanUtils.toBean(saleOrderItemMap.get(saleOrder.getId()), ErpSaleOrderRespVO.Item.class,

+ 1 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java

@@ -150,7 +150,7 @@ public class ErpSaleOutController {
                 convertSet(pageResult.getList(), ErpSaleOutDO::getCustomerId));
         // 1.4 管理员信息
         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
-                convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator())));
+                convertSet(pageResult.getList(), stockOut -> Long.parseLong(stockOut.getCreator())));
         // 2. 开始拼接
         return BeanUtils.toBean(pageResult, ErpSaleOutRespVO.class, saleOut -> {
             saleOut.setItems(BeanUtils.toBean(saleOutItemMap.get(saleOut.getId()), ErpSaleOutRespVO.Item.class,

+ 1 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java

@@ -150,7 +150,7 @@ public class ErpSaleReturnController {
                 convertSet(pageResult.getList(), ErpSaleReturnDO::getCustomerId));
         // 1.4 管理员信息
         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
-                convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator())));
+                convertSet(pageResult.getList(), saleReturn -> Long.parseLong(saleReturn.getCreator())));
         // 2. 开始拼接
         return BeanUtils.toBean(pageResult, ErpSaleReturnRespVO.class, saleReturn -> {
             saleReturn.setItems(BeanUtils.toBean(saleReturnItemMap.get(saleReturn.getId()), ErpSaleReturnRespVO.Item.class,

+ 2 - 2
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java

@@ -126,7 +126,7 @@ public class ErpStockCheckController {
         if (CollUtil.isEmpty(pageResult.getList())) {
             return PageResult.empty(pageResult.getTotal());
         }
-        // 1.1 出库
+        // 1.1 盘点
         List<ErpStockCheckItemDO> stockCheckItemList = stockCheckService.getStockCheckItemListByCheckIds(
                 convertSet(pageResult.getList(), ErpStockCheckDO::getId));
         Map<Long, List<ErpStockCheckItemDO>> stockCheckItemMap = convertMultiMap(stockCheckItemList, ErpStockCheckItemDO::getCheckId);
@@ -135,7 +135,7 @@ public class ErpStockCheckController {
                 convertSet(stockCheckItemList, ErpStockCheckItemDO::getProductId));
         // 1.3 管理员信息
         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
-                convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator())));
+                convertSet(pageResult.getList(), stockCheck -> Long.parseLong(stockCheck.getCreator())));
         // 2. 开始拼接
         return BeanUtils.toBean(pageResult, ErpStockCheckRespVO.class, stockCheck -> {
             stockCheck.setItems(BeanUtils.toBean(stockCheckItemMap.get(stockCheck.getId()), ErpStockCheckRespVO.Item.class,

+ 1 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java

@@ -150,7 +150,7 @@ public class ErpStockInController {
                 convertSet(pageResult.getList(), ErpStockInDO::getSupplierId));
         // 1.4 管理员信息
         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
-                convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator())));
+                convertSet(pageResult.getList(), stockIn -> Long.parseLong(stockIn.getCreator())));
         // 2. 开始拼接
         return BeanUtils.toBean(pageResult, ErpStockInRespVO.class, stockIn -> {
             stockIn.setItems(BeanUtils.toBean(stockInItemMap.get(stockIn.getId()), ErpStockInRespVO.Item.class,

+ 2 - 2
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java

@@ -134,7 +134,7 @@ public class ErpStockMoveController {
         if (CollUtil.isEmpty(pageResult.getList())) {
             return PageResult.empty(pageResult.getTotal());
         }
-        // 1.1 出库
+        // 1.1 调拨
         List<ErpStockMoveItemDO> stockMoveItemList = stockMoveService.getStockMoveItemListByMoveIds(
                 convertSet(pageResult.getList(), ErpStockMoveDO::getId));
         Map<Long, List<ErpStockMoveItemDO>> stockMoveItemMap = convertMultiMap(stockMoveItemList, ErpStockMoveItemDO::getMoveId);
@@ -144,7 +144,7 @@ public class ErpStockMoveController {
         // 1.3 TODO 芋艿:搞仓库信息
         // 1.4 管理员信息
         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
-                convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator())));
+                convertSet(pageResult.getList(), stockMove -> Long.parseLong(stockMove.getCreator())));
         // 2. 开始拼接
         return BeanUtils.toBean(pageResult, ErpStockMoveRespVO.class, stockMove -> {
             stockMove.setItems(BeanUtils.toBean(stockMoveItemMap.get(stockMove.getId()), ErpStockMoveRespVO.Item.class,

+ 1 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java

@@ -150,7 +150,7 @@ public class ErpStockOutController {
                 convertSet(pageResult.getList(), ErpStockOutDO::getCustomerId));
         // 1.4 管理员信息
         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
-                convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator())));
+                convertSet(pageResult.getList(), stockOut -> Long.parseLong(stockOut.getCreator())));
         // 2. 开始拼接
         return BeanUtils.toBean(pageResult, ErpStockOutRespVO.class, stockOut -> {
             stockOut.setItems(BeanUtils.toBean(stockOutItemMap.get(stockOut.getId()), ErpStockOutRespVO.Item.class,

+ 1 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java

@@ -93,7 +93,7 @@ public class ErpStockRecordController {
         Map<Long, ErpWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
                 convertSet(pageResult.getList(), ErpStockRecordDO::getWarehouseId));
         Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
-                convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator())));
+                convertSet(pageResult.getList(), record -> Long.parseLong(record.getCreator())));
         return BeanUtils.toBean(pageResult, ErpStockRecordRespVO.class, stock -> {
             MapUtils.findAndThen(productMap, stock.getProductId(), product -> stock.setProductName(product.getName())
                     .setCategoryName(product.getCategoryName()).setUnitName(product.getUnitName()));

+ 86 - 0
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentDO.java

@@ -0,0 +1,86 @@
+package cn.iocoder.yudao.module.erp.dal.dataobject.finance;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * ERP 付款单 DO
+ *
+ * @author 芋道源码
+ */
+@TableName("erp_finance_payment")
+@KeySequence("erp_finance_payment_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ErpFinancePaymentDO extends BaseDO {
+
+    /**
+     * 编号
+     */
+    @TableId
+    private Long id;
+    /**
+     * 付款单号
+     */
+    private String no;
+    /**
+     * 付款状态
+     *
+     * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus}
+     */
+    private Integer status;
+    /**
+     * 付款时间
+     */
+    private LocalDateTime paymentTime;
+    /**
+     * 财务人员编号
+     *
+     * 关联 AdminUserDO 的 id 字段
+     */
+    private Long financeUserId;
+    /**
+     * 供应商编号
+     *
+     * 关联 {@link ErpSupplierDO#getId()}
+     */
+    private Long supplierId;
+    /**
+     * 付款账户编号
+     *
+     * 关联 {@link ErpAccountDO#getId()}
+     */
+    private Long accountId;
+
+    /**
+     * 合计价格,单位:元
+     */
+    private BigDecimal totalPrice;
+    /**
+     * 优惠金额,单位:元
+     */
+    private BigDecimal discountPrice;
+    /**
+     * 实付金额,单位:分
+     *
+     * paymentPrice = totalPrice - discountPrice
+     */
+    private BigDecimal paymentPrice;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 75 - 0
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentItemDO.java

@@ -0,0 +1,75 @@
+package cn.iocoder.yudao.module.erp.dal.dataobject.finance;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.math.BigDecimal;
+
+/**
+ * ERP 付款项 DO
+ *
+ * @author 芋道源码
+ */
+@TableName("erp_finance_payment_item")
+@KeySequence("erp_finance_payment_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ErpFinancePaymentItemDO extends BaseDO {
+
+    /**
+     * 入库项编号
+     */
+    @TableId
+    private Long id;
+    /**
+     * 付款单编号
+     *
+     * 关联 {@link ErpFinancePaymentDO#getId()}
+     */
+    private Long paymentId;
+
+    /**
+     * 业务类型
+     *
+     * 枚举 {@link cn.iocoder.yudao.module.erp.enums.common.ErpBizTypeEnum} 的采购入库、退货
+     */
+    private Integer bizType;
+    /**
+     * 业务编号
+     *
+     * 例如说:{@link ErpPurchaseInDO#getId()}
+     */
+    private Long bizId;
+    /**
+     * 业务单号
+     *
+     * 例如说:{@link ErpPurchaseInDO#getNo()}
+     */
+    private String bizNo;
+
+    /**
+     * 应付欠款,单位:分
+     */
+    private BigDecimal totalPrice;
+    /**
+     * 已付欠款,单位:分
+     */
+    private BigDecimal paidPrice;
+    /**
+     * 本次付款,单位:分
+     */
+    private BigDecimal paymentPrice;
+    /**
+     * 备注
+     */
+    private String remark;
+
+}

+ 1 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java

@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.erp.dal.mysql.finance;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountPageReqVO;
+import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountPageReqVO;
 import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO;
 import org.apache.ibatis.annotations.Mapper;
 

+ 30 - 0
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentItemMapper.java

@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.erp.dal.mysql.finance;
+
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * ERP 付款单项 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface ErpFinancePaymentItemMapper extends BaseMapperX<ErpFinancePaymentItemDO> {
+
+    default List<ErpFinancePaymentItemDO> selectListByPaymentId(Long paymentId) {
+        return selectList(ErpFinancePaymentItemDO::getPaymentId, paymentId);
+    }
+
+    default List<ErpFinancePaymentItemDO> selectListByPaymentIds(Collection<Long> paymentIds) {
+        return selectList(ErpFinancePaymentItemDO::getPaymentId, paymentIds);
+    }
+
+    default int deleteByPaymentId(Long paymentId) {
+        return delete(ErpFinancePaymentItemDO::getPaymentId, paymentId);
+    }
+
+}

+ 48 - 0
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentMapper.java

@@ -0,0 +1,48 @@
+package cn.iocoder.yudao.module.erp.dal.mysql.finance;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
+import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentPageReqVO;
+import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO;
+import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * ERP 付款单 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface ErpFinancePaymentMapper extends BaseMapperX<ErpFinancePaymentDO> {
+
+    default PageResult<ErpFinancePaymentDO> selectPage(ErpFinancePaymentPageReqVO reqVO) {
+        MPJLambdaWrapperX<ErpFinancePaymentDO> query = new MPJLambdaWrapperX<ErpFinancePaymentDO>()
+                .likeIfPresent(ErpFinancePaymentDO::getNo, reqVO.getNo())
+                .betweenIfPresent(ErpFinancePaymentDO::getPaymentTime, reqVO.getPaymentTime())
+                .eqIfPresent(ErpFinancePaymentDO::getSupplierId, reqVO.getSupplierId())
+                .eqIfPresent(ErpFinancePaymentDO::getCreator, reqVO.getCreator())
+                .eqIfPresent(ErpFinancePaymentDO::getFinanceUserId, reqVO.getFinanceUserId())
+                .eqIfPresent(ErpFinancePaymentDO::getAccountId, reqVO.getAccountId())
+                .eqIfPresent(ErpFinancePaymentDO::getStatus, reqVO.getStatus())
+                .likeIfPresent(ErpFinancePaymentDO::getRemark, reqVO.getRemark())
+                .orderByDesc(ErpFinancePaymentDO::getId);
+        if (reqVO.getBizNo() != null) {
+            query.leftJoin(ErpFinancePaymentItemDO.class, ErpFinancePaymentItemDO::getPaymentId, ErpFinancePaymentDO::getId)
+                    .eq(reqVO.getBizNo() != null, ErpFinancePaymentItemDO::getBizNo, reqVO.getBizNo())
+                    .groupBy(ErpFinancePaymentDO::getId); // 避免 1 对多查询,产生相同的 1
+        }
+        return selectJoinPage(reqVO, ErpFinancePaymentDO.class, query);
+    }
+
+    default int updateByIdAndStatus(Long id, Integer status, ErpFinancePaymentDO updateObj) {
+        return update(updateObj, new LambdaUpdateWrapper<ErpFinancePaymentDO>()
+                .eq(ErpFinancePaymentDO::getId, id).eq(ErpFinancePaymentDO::getStatus, status));
+    }
+
+    default ErpFinancePaymentDO selectByNo(String no) {
+        return selectOne(ErpFinancePaymentDO::getNo, no);
+    }
+
+}

+ 5 - 0
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java

@@ -64,6 +64,11 @@ public class ErpNoRedisDAO {
      */
     public static final String PURCHASE_RETURN_NO_PREFIX = "CGTH";
 
+    /**
+     * 付款单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO}
+     */
+    public static final String FINANCE_PAYMENT_NO_PREFIX = "FKD";
+
     @Resource
     private StringRedisTemplate stringRedisTemplate;
 

+ 2 - 2
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java

@@ -1,8 +1,8 @@
 package cn.iocoder.yudao.module.erp.service.finance;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountPageReqVO;
-import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountSaveReqVO;
+import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountPageReqVO;
+import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountSaveReqVO;
 import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO;
 import jakarta.validation.Valid;
 

+ 2 - 2
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java

@@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.erp.service.finance;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountPageReqVO;
-import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountSaveReqVO;
+import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountPageReqVO;
+import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountSaveReqVO;
 import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO;
 import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpAccountMapper;
 import jakarta.annotation.Resource;

+ 84 - 0
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentService.java

@@ -0,0 +1,84 @@
+package cn.iocoder.yudao.module.erp.service.finance;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+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;
+import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO;
+import jakarta.validation.Valid;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * ERP 付款单 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface ErpFinancePaymentService {
+
+    /**
+     * 创建付款单
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createFinancePayment(@Valid ErpFinancePaymentSaveReqVO createReqVO);
+
+    /**
+     * 更新付款单
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateFinancePayment(@Valid ErpFinancePaymentSaveReqVO updateReqVO);
+
+    /**
+     * 更新付款单的状态
+     *
+     * @param id 编号
+     * @param status 状态
+     */
+    void updateFinancePaymentStatus(Long id, Integer status);
+
+    /**
+     * 删除付款单
+     *
+     * @param ids 编号数组
+     */
+    void deleteFinancePayment(List<Long> ids);
+
+    /**
+     * 获得付款单
+     *
+     * @param id 编号
+     * @return 付款单
+     */
+    ErpFinancePaymentDO getFinancePayment(Long id);
+
+    /**
+     * 获得付款单分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 付款单分页
+     */
+    PageResult<ErpFinancePaymentDO> getFinancePaymentPage(ErpFinancePaymentPageReqVO pageReqVO);
+
+    // ==================== 付款单项 ====================
+
+    /**
+     * 获得付款单项列表
+     *
+     * @param paymentId 付款单编号
+     * @return 付款单项列表
+     */
+    List<ErpFinancePaymentItemDO> getFinancePaymentItemListByPaymentId(Long paymentId);
+
+    /**
+     * 获得付款单项 List
+     *
+     * @param paymentIds 付款单编号数组
+     * @return 付款单项 List
+     */
+    List<ErpFinancePaymentItemDO> getFinancePaymentItemListByPaymentIds(Collection<Long> paymentIds);
+
+}

+ 241 - 0
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java

@@ -0,0 +1,241 @@
+package cn.iocoder.yudao.module.erp.service.finance;
+
+import cn.hutool.core.collection.CollUtil;
+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.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;
+import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO;
+import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO;
+import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO;
+import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpFinancePaymentItemMapper;
+import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpFinancePaymentMapper;
+import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO;
+import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
+import cn.iocoder.yudao.module.erp.enums.common.ErpBizTypeEnum;
+import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseInService;
+import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseReturnService;
+import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import jakarta.annotation.Resource;
+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 static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
+import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
+
+// TODO 芋艿:记录操作日志
+
+/**
+ * ERP 付款单 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService {
+
+    @Resource
+    private ErpFinancePaymentMapper financePaymentMapper;
+    @Resource
+    private ErpFinancePaymentItemMapper financePaymentItemMapper;
+
+    @Resource
+    private ErpNoRedisDAO noRedisDAO;
+
+    @Resource
+    private ErpSupplierService supplierService;
+    @Resource
+    private ErpAccountService accountService;
+    @Resource
+    private ErpPurchaseInService purchaseInService;
+    @Resource
+    private ErpPurchaseReturnService purchaseReturnService;
+
+    @Resource
+    private AdminUserApi adminUserApi;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long createFinancePayment(ErpFinancePaymentSaveReqVO createReqVO) {
+        // 1.1 校验订单项的有效性
+        List<ErpFinancePaymentItemDO> paymentItems = validateFinancePaymentItems(createReqVO.getItems());
+        // 1.2 校验供应商
+        supplierService.validateSupplier(createReqVO.getSupplierId());
+        // 1.3 校验结算账户
+        if (createReqVO.getAccountId() != null) {
+            accountService.validateAccount(createReqVO.getAccountId());
+        }
+        // 1.4 校验财务人员
+        if (createReqVO.getFinanceUserId() != null) {
+            adminUserApi.validateUser(createReqVO.getFinanceUserId());
+        }
+        // 1.5 生成付款单号,并校验唯一性
+        String no = noRedisDAO.generate(ErpNoRedisDAO.FINANCE_PAYMENT_NO_PREFIX);
+        if (financePaymentMapper.selectByNo(no) != null) {
+            throw exception(FINANCE_PAYMENT_NO_EXISTS);
+        }
+
+        // 2.1 插入付款单
+        ErpFinancePaymentDO payment = BeanUtils.toBean(createReqVO, ErpFinancePaymentDO.class, in -> in
+                .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()));
+        calculateTotalPrice(payment, paymentItems);
+        financePaymentMapper.insert(payment);
+        // 2.2 插入付款单项
+        paymentItems.forEach(o -> o.setPaymentId(payment.getId()));
+        financePaymentItemMapper.insertBatch(paymentItems);
+        return payment.getId();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateFinancePayment(ErpFinancePaymentSaveReqVO updateReqVO) {
+        // 1.1 校验存在
+        ErpFinancePaymentDO payment = validateFinancePaymentExists(updateReqVO.getId());
+        if (ErpAuditStatus.APPROVE.getStatus().equals(payment.getStatus())) {
+            throw exception(SALE_ORDER_UPDATE_FAIL_APPROVE, payment.getNo());
+        }
+        // 1.2 校验供应商
+        supplierService.validateSupplier(updateReqVO.getSupplierId());
+        // 1.3 校验结算账户
+        if (updateReqVO.getAccountId() != null) {
+            accountService.validateAccount(updateReqVO.getAccountId());
+        }
+        // 1.4 校验财务人员
+        if (updateReqVO.getFinanceUserId() != null) {
+            adminUserApi.validateUser(updateReqVO.getFinanceUserId());
+        }
+        // 1.5 校验付款单项的有效性
+        List<ErpFinancePaymentItemDO> paymentItems = validateFinancePaymentItems(updateReqVO.getItems());
+
+        // 2.1 更新付款单
+        ErpFinancePaymentDO updateObj = BeanUtils.toBean(updateReqVO, ErpFinancePaymentDO.class);
+        calculateTotalPrice(updateObj, paymentItems);
+        financePaymentMapper.updateById(updateObj);
+        // 2.2 更新付款单项
+        updateFinancePaymentItemList(updateReqVO.getId(), paymentItems);
+    }
+
+    private void calculateTotalPrice(ErpFinancePaymentDO payment, List<ErpFinancePaymentItemDO> paymentItems) {
+        payment.setTotalPrice(getSumValue(paymentItems, ErpFinancePaymentItemDO::getPaymentPrice, BigDecimal::add, BigDecimal.ZERO));
+        payment.setPaymentPrice(payment.getTotalPrice().subtract(payment.getDiscountPrice()));
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateFinancePaymentStatus(Long id, Integer status) {
+        boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status);
+        // 1.1 校验存在
+        ErpFinancePaymentDO payment = validateFinancePaymentExists(id);
+        // 1.2 校验状态
+        if (payment.getStatus().equals(status)) {
+            throw exception(approve ? SALE_ORDER_APPROVE_FAIL : SALE_ORDER_PROCESS_FAIL);
+        }
+
+        // 2. 更新状态
+        int updateCount = financePaymentMapper.updateByIdAndStatus(id, payment.getStatus(),
+                new ErpFinancePaymentDO().setStatus(status));
+        if (updateCount == 0) {
+            throw exception(approve ? SALE_ORDER_APPROVE_FAIL : SALE_ORDER_PROCESS_FAIL);
+        }
+    }
+
+    private List<ErpFinancePaymentItemDO> validateFinancePaymentItems(List<ErpFinancePaymentSaveReqVO.Item> list) {
+        return convertList(list, o -> BeanUtils.toBean(o, ErpFinancePaymentItemDO.class, item -> {
+            if (ObjectUtil.equal(item.getBizType(), ErpBizTypeEnum.PURCHASE_IN.getType())) {
+                ErpPurchaseInDO purchaseIn = purchaseInService.validatePurchaseIn(item.getBizId());
+                item.setTotalPrice(purchaseIn.getTotalPrice()).setBizNo(purchaseIn.getNo());
+            } else if (ObjectUtil.equal(item.getBizType(), ErpBizTypeEnum.PURCHASE_RETURN.getType())) {
+                ErpPurchaseReturnDO purchaseReturn = purchaseReturnService.validatePurchaseReturn(item.getBizId());
+                item.setTotalPrice(purchaseReturn.getTotalPrice()).setBizNo(purchaseReturn.getNo());
+            } else {
+                throw new IllegalArgumentException("业务类型不正确:" + item.getBizType());
+            }
+        }));
+    }
+
+    private void updateFinancePaymentItemList(Long id, List<ErpFinancePaymentItemDO> newList) {
+        // 第一步,对比新老数据,获得添加、修改、删除的列表
+        List<ErpFinancePaymentItemDO> oldList = financePaymentItemMapper.selectListByPaymentId(id);
+        List<List<ErpFinancePaymentItemDO>> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录
+                (oldVal, newVal) -> oldVal.getId().equals(newVal.getId()));
+
+        // 第二步,批量添加、修改、删除
+        if (CollUtil.isNotEmpty(diffList.get(0))) {
+            diffList.get(0).forEach(o -> o.setPaymentId(id));
+            financePaymentItemMapper.insertBatch(diffList.get(0));
+        }
+        if (CollUtil.isNotEmpty(diffList.get(1))) {
+            financePaymentItemMapper.updateBatch(diffList.get(1));
+        }
+        if (CollUtil.isNotEmpty(diffList.get(2))) {
+            financePaymentItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpFinancePaymentItemDO::getId));
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteFinancePayment(List<Long> ids) {
+        // 1. 校验不处于已审批
+        List<ErpFinancePaymentDO> payments = financePaymentMapper.selectBatchIds(ids);
+        if (CollUtil.isEmpty(payments)) {
+            return;
+        }
+        payments.forEach(payment -> {
+            if (ErpAuditStatus.APPROVE.getStatus().equals(payment.getStatus())) {
+                throw exception(SALE_ORDER_DELETE_FAIL_APPROVE, payment.getNo());
+            }
+        });
+
+        // 2. 遍历删除,并记录操作日志
+        payments.forEach(payment -> {
+            // 2.1 删除付款单
+            financePaymentMapper.deleteById(payment.getId());
+            // 2.2 删除付款单项
+            financePaymentItemMapper.deleteByPaymentId(payment.getId());
+        });
+    }
+
+    private ErpFinancePaymentDO validateFinancePaymentExists(Long id) {
+        ErpFinancePaymentDO payment = financePaymentMapper.selectById(id);
+        if (payment == null) {
+            throw exception(SALE_ORDER_NOT_EXISTS);
+        }
+        return payment;
+    }
+
+    @Override
+    public ErpFinancePaymentDO getFinancePayment(Long id) {
+        return financePaymentMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<ErpFinancePaymentDO> getFinancePaymentPage(ErpFinancePaymentPageReqVO pageReqVO) {
+        return financePaymentMapper.selectPage(pageReqVO);
+    }
+
+    // ==================== 付款单项 ====================
+
+    @Override
+    public List<ErpFinancePaymentItemDO> getFinancePaymentItemListByPaymentId(Long paymentId) {
+        return financePaymentItemMapper.selectListByPaymentId(paymentId);
+    }
+
+    @Override
+    public List<ErpFinancePaymentItemDO> getFinancePaymentItemListByPaymentIds(Collection<Long> paymentIds) {
+        if (CollUtil.isEmpty(paymentIds)) {
+            return Collections.emptyList();
+        }
+        return financePaymentItemMapper.selectListByPaymentIds(paymentIds);
+    }
+
+}

+ 8 - 0
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java

@@ -55,6 +55,14 @@ public interface ErpPurchaseInService {
      */
     ErpPurchaseInDO getPurchaseIn(Long id);
 
+    /**
+     * 校验采购入库,已经审核通过
+     *
+     * @param id 编号
+     * @return 采购入库
+     */
+    ErpPurchaseInDO validatePurchaseIn(Long id);
+
     /**
      * 获得采购入库分页
      *

+ 11 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java

@@ -78,7 +78,7 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService {
         List<ErpPurchaseInItemDO> purchaseInItems = validatePurchaseInItems(createReqVO.getItems());
         // 1.3 校验结算账户
         accountService.validateAccount(createReqVO.getAccountId());
-        // 1.4 生成调拨单号,并校验唯一性
+        // 1.4 生成入库单号,并校验唯一性
         String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_IN_NO_PREFIX);
         if (purchaseInMapper.selectByNo(no) != null) {
             throw exception(PURCHASE_IN_NO_EXISTS);
@@ -163,6 +163,7 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService {
         if (purchaseIn.getStatus().equals(status)) {
             throw exception(approve ? PURCHASE_IN_APPROVE_FAIL : PURCHASE_IN_PROCESS_FAIL);
         }
+        // TODO 芋艿:稍后加下校验
 
         // 2. 更新状态
         int updateCount = purchaseInMapper.updateByIdAndStatus(id, purchaseIn.getStatus(),
@@ -260,6 +261,15 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService {
         return purchaseInMapper.selectById(id);
     }
 
+    @Override
+    public ErpPurchaseInDO validatePurchaseIn(Long id) {
+        ErpPurchaseInDO purchaseIn = validatePurchaseInExists(id);
+        if (ObjectUtil.notEqual(purchaseIn.getStatus(), ErpAuditStatus.APPROVE.getStatus())) {
+            throw exception(PURCHASE_IN_NOT_APPROVE);
+        }
+        return purchaseIn;
+    }
+
     @Override
     public PageResult<ErpPurchaseInDO> getPurchaseInPage(ErpPurchaseInPageReqVO pageReqVO) {
         return purchaseInMapper.selectPage(pageReqVO);

+ 1 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java

@@ -68,7 +68,7 @@ public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService {
         if (createReqVO.getAccountId() != null) {
             accountService.validateAccount(createReqVO.getAccountId());
         }
-        // 1.4 生成调拨单号,并校验唯一性
+        // 1.4 生成单号,并校验唯一性
         String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_ORDER_NO_PREFIX);
         if (purchaseOrderMapper.selectByNo(no) != null) {
             throw exception(PURCHASE_ORDER_NO_EXISTS);

+ 8 - 0
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java

@@ -55,6 +55,14 @@ public interface ErpPurchaseReturnService {
      */
     ErpPurchaseReturnDO getPurchaseReturn(Long id);
 
+    /**
+     * 校验采购退货,已经审核通过
+     *
+     * @param id 编号
+     * @return 采购退货
+     */
+    ErpPurchaseReturnDO validatePurchaseReturn(Long id);
+
     /**
      * 获得采购退货分页
      *

+ 11 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java

@@ -74,7 +74,7 @@ public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService {
         List<ErpPurchaseReturnItemDO> purchaseReturnItems = validatePurchaseReturnItems(createReqVO.getItems());
         // 1.3 校验结算账户
         accountService.validateAccount(createReqVO.getAccountId());
-        // 1.4 生成调拨单号,并校验唯一性
+        // 1.4 生成退货单号,并校验唯一性
         String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_RETURN_NO_PREFIX);
         if (purchaseReturnMapper.selectByNo(no) != null) {
             throw exception(PURCHASE_RETURN_NO_EXISTS);
@@ -159,6 +159,7 @@ public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService {
         if (purchaseReturn.getStatus().equals(status)) {
             throw exception(approve ? PURCHASE_RETURN_APPROVE_FAIL : PURCHASE_RETURN_PROCESS_FAIL);
         }
+        // TODO 芋艿:稍后加下校验
 
         // 2. 更新状态
         int updateCount = purchaseReturnMapper.updateByIdAndStatus(id, purchaseReturn.getStatus(),
@@ -256,6 +257,15 @@ public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService {
         return purchaseReturnMapper.selectById(id);
     }
 
+    @Override
+    public ErpPurchaseReturnDO validatePurchaseReturn(Long id) {
+        ErpPurchaseReturnDO purchaseReturn = getPurchaseReturn(id);
+        if (ObjectUtil.notEqual(purchaseReturn.getStatus(), ErpAuditStatus.APPROVE.getStatus())) {
+            throw exception(PURCHASE_RETURN_NOT_APPROVE);
+        }
+        return purchaseReturn;
+    }
+
     @Override
     public PageResult<ErpPurchaseReturnDO> getPurchaseReturnPage(ErpPurchaseReturnPageReqVO pageReqVO) {
         return purchaseReturnMapper.selectPage(pageReqVO);

+ 1 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java

@@ -76,7 +76,7 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService {
         if (createReqVO.getSaleUserId() != null) {
             adminUserApi.validateUser(createReqVO.getSaleUserId());
         }
-        // 1.5 生成调拨单号,并校验唯一性
+        // 1.5 生成单号,并校验唯一性
         String no = noRedisDAO.generate(ErpNoRedisDAO.SALE_ORDER_NO_PREFIX);
         if (saleOrderMapper.selectByNo(no) != null) {
             throw exception(SALE_ORDER_NO_EXISTS);

+ 1 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java

@@ -82,7 +82,7 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService {
         if (createReqVO.getSaleUserId() != null) {
             adminUserApi.validateUser(createReqVO.getSaleUserId());
         }
-        // 1.5 生成调拨单号,并校验唯一性
+        // 1.5 生成出库单号,并校验唯一性
         String no = noRedisDAO.generate(ErpNoRedisDAO.SALE_OUT_NO_PREFIX);
         if (saleOutMapper.selectByNo(no) != null) {
             throw exception(SALE_OUT_NO_EXISTS);

+ 1 - 1
yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java

@@ -82,7 +82,7 @@ public class ErpSaleReturnServiceImpl implements ErpSaleReturnService {
         if (createReqVO.getSaleUserId() != null) {
             adminUserApi.validateUser(createReqVO.getSaleUserId());
         }
-        // 1.5 生成调拨单号,并校验唯一性
+        // 1.5 生成退货单号,并校验唯一性
         String no = noRedisDAO.generate(ErpNoRedisDAO.SALE_RETURN_NO_PREFIX);
         if (saleReturnMapper.selectByNo(no) != null) {
             throw exception(SALE_RETURN_NO_EXISTS);

+ 0 - 142
yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImplTest.java

@@ -1,142 +0,0 @@
-package cn.iocoder.yudao.module.erp.service.finance;
-
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.mock.mockito.MockBean;
-
-import jakarta.annotation.Resource;
-
-import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-
-import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.*;
-import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO;
-import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpAccountMapper;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
-import jakarta.annotation.Resource;
-import org.springframework.context.annotation.Import;
-import java.util.*;
-import java.time.LocalDateTime;
-
-import static cn.hutool.core.util.RandomUtil.*;
-import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
-import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
-import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
-import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
-
-/**
- * {@link ErpAccountServiceImpl} 的单元测试类
- *
- * @author 芋道源码
- */
-@Import(ErpAccountServiceImpl.class)
-public class ErpAccountServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private ErpAccountServiceImpl accountService;
-
-    @Resource
-    private ErpAccountMapper accountMapper;
-
-    @Test
-    public void testCreateAccount_success() {
-        // 准备参数
-        ErpAccountSaveReqVO createReqVO = randomPojo(ErpAccountSaveReqVO.class).setId(null);
-
-        // 调用
-        Long accountId = accountService.createAccount(createReqVO);
-        // 断言
-        assertNotNull(accountId);
-        // 校验记录的属性是否正确
-        ErpAccountDO account = accountMapper.selectById(accountId);
-        assertPojoEquals(createReqVO, account, "id");
-    }
-
-    @Test
-    public void testUpdateAccount_success() {
-        // mock 数据
-        ErpAccountDO dbAccount = randomPojo(ErpAccountDO.class);
-        accountMapper.insert(dbAccount);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        ErpAccountSaveReqVO updateReqVO = randomPojo(ErpAccountSaveReqVO.class, o -> {
-            o.setId(dbAccount.getId()); // 设置更新的 ID
-        });
-
-        // 调用
-        accountService.updateAccount(updateReqVO);
-        // 校验是否更新正确
-        ErpAccountDO account = accountMapper.selectById(updateReqVO.getId()); // 获取最新的
-        assertPojoEquals(updateReqVO, account);
-    }
-
-    @Test
-    public void testUpdateAccount_notExists() {
-        // 准备参数
-        ErpAccountSaveReqVO updateReqVO = randomPojo(ErpAccountSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> accountService.updateAccount(updateReqVO), ACCOUNT_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteAccount_success() {
-        // mock 数据
-        ErpAccountDO dbAccount = randomPojo(ErpAccountDO.class);
-        accountMapper.insert(dbAccount);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbAccount.getId();
-
-        // 调用
-        accountService.deleteAccount(id);
-       // 校验数据不存在了
-       assertNull(accountMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteAccount_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> accountService.deleteAccount(id), ACCOUNT_NOT_EXISTS);
-    }
-
-    @Test
-    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
-    public void testGetAccountPage() {
-       // mock 数据
-       ErpAccountDO dbAccount = randomPojo(ErpAccountDO.class, o -> { // 等会查询到
-           o.setNo(null);
-           o.setRemark(null);
-           o.setStatus(null);
-           o.setName(null);
-       });
-       accountMapper.insert(dbAccount);
-       // 测试 no 不匹配
-       accountMapper.insert(cloneIgnoreId(dbAccount, o -> o.setNo(null)));
-       // 测试 remark 不匹配
-       accountMapper.insert(cloneIgnoreId(dbAccount, o -> o.setRemark(null)));
-       // 测试 status 不匹配
-       accountMapper.insert(cloneIgnoreId(dbAccount, o -> o.setStatus(null)));
-       // 测试 name 不匹配
-       accountMapper.insert(cloneIgnoreId(dbAccount, o -> o.setName(null)));
-       // 准备参数
-       ErpAccountPageReqVO reqVO = new ErpAccountPageReqVO();
-       reqVO.setNo(null);
-       reqVO.setRemark(null);
-       reqVO.setStatus(null);
-       reqVO.setName(null);
-
-       // 调用
-       PageResult<ErpAccountDO> pageResult = accountService.getAccountPage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbAccount, pageResult.getList().get(0));
-    }
-
-}

+ 0 - 131
yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java

@@ -1,131 +0,0 @@
-package cn.iocoder.yudao.module.erp.service.product;
-
-import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO;
-import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitSaveReqVO;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-import jakarta.annotation.Resource;
-
-import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-
-import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
-import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductUnitMapper;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
-import org.springframework.context.annotation.Import;
-
-import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
-import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
-import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link ErpProductUnitServiceImpl} 的单元测试类
- *
- * @author 芋道源码
- */
-@Import(ErpProductUnitServiceImpl.class)
-public class ErpProductUnitServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private ErpProductUnitServiceImpl productUnitService;
-
-    @Resource
-    private ErpProductUnitMapper productUnitMapper;
-
-    @Test
-    public void testCreateProductUnit_success() {
-        // 准备参数
-        ErpProductUnitSaveReqVO createReqVO = randomPojo(ErpProductUnitSaveReqVO.class).setId(null);
-
-        // 调用
-        Long productUnitId = productUnitService.createProductUnit(createReqVO);
-        // 断言
-        assertNotNull(productUnitId);
-        // 校验记录的属性是否正确
-        ErpProductUnitDO productUnit = productUnitMapper.selectById(productUnitId);
-        assertPojoEquals(createReqVO, productUnit, "id");
-    }
-
-    @Test
-    public void testUpdateProductUnit_success() {
-        // mock 数据
-        ErpProductUnitDO dbProductUnit = randomPojo(ErpProductUnitDO.class);
-        productUnitMapper.insert(dbProductUnit);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        ErpProductUnitSaveReqVO updateReqVO = randomPojo(ErpProductUnitSaveReqVO.class, o -> {
-            o.setId(dbProductUnit.getId()); // 设置更新的 ID
-        });
-
-        // 调用
-        productUnitService.updateProductUnit(updateReqVO);
-        // 校验是否更新正确
-        ErpProductUnitDO productUnit = productUnitMapper.selectById(updateReqVO.getId()); // 获取最新的
-        assertPojoEquals(updateReqVO, productUnit);
-    }
-
-    @Test
-    public void testUpdateProductUnit_notExists() {
-        // 准备参数
-        ErpProductUnitSaveReqVO updateReqVO = randomPojo(ErpProductUnitSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> productUnitService.updateProductUnit(updateReqVO), PRODUCT_UNIT_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteProductUnit_success() {
-        // mock 数据
-        ErpProductUnitDO dbProductUnit = randomPojo(ErpProductUnitDO.class);
-        productUnitMapper.insert(dbProductUnit);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbProductUnit.getId();
-
-        // 调用
-        productUnitService.deleteProductUnit(id);
-       // 校验数据不存在了
-       assertNull(productUnitMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteProductUnit_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> productUnitService.deleteProductUnit(id), PRODUCT_UNIT_NOT_EXISTS);
-    }
-
-    @Test
-    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
-    public void testGetProductUnitPage() {
-       // mock 数据
-       ErpProductUnitDO dbProductUnit = randomPojo(ErpProductUnitDO.class, o -> { // 等会查询到
-           o.setName(null);
-           o.setStatus(null);
-           o.setCreateTime(null);
-       });
-       productUnitMapper.insert(dbProductUnit);
-       // 测试 name 不匹配
-       productUnitMapper.insert(cloneIgnoreId(dbProductUnit, o -> o.setName(null)));
-       // 测试 status 不匹配
-       productUnitMapper.insert(cloneIgnoreId(dbProductUnit, o -> o.setStatus(null)));
-       // 测试 createTime 不匹配
-       productUnitMapper.insert(cloneIgnoreId(dbProductUnit, o -> o.setCreateTime(null)));
-       // 准备参数
-       ErpProductUnitPageReqVO reqVO = new ErpProductUnitPageReqVO();
-       reqVO.setName(null);
-       reqVO.setStatus(null);
-       reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
-
-       // 调用
-       PageResult<ErpProductUnitDO> pageResult = productUnitService.getProductUnitPage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbProductUnit, pageResult.getList().get(0));
-    }
-
-}

+ 0 - 131
yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java

@@ -1,131 +0,0 @@
-package cn.iocoder.yudao.module.erp.service.product;
-
-import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO;
-import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-import jakarta.annotation.Resource;
-
-import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-
-import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
-import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
-import org.springframework.context.annotation.Import;
-
-import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
-import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
-import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link ErpProductServiceImpl} 的单元测试类
- *
- * @author 芋道源码
- */
-@Import(ErpProductServiceImpl.class)
-public class ProductServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private ErpProductServiceImpl productService;
-
-    @Resource
-    private ErpProductMapper productMapper;
-
-    @Test
-    public void testCreateProduct_success() {
-        // 准备参数
-        ProductSaveReqVO createReqVO = randomPojo(ProductSaveReqVO.class).setId(null);
-
-        // 调用
-        Long productId = productService.createProduct(createReqVO);
-        // 断言
-        assertNotNull(productId);
-        // 校验记录的属性是否正确
-        ErpProductDO product = productMapper.selectById(productId);
-        assertPojoEquals(createReqVO, product, "id");
-    }
-
-    @Test
-    public void testUpdateProduct_success() {
-        // mock 数据
-        ErpProductDO dbProduct = randomPojo(ErpProductDO.class);
-        productMapper.insert(dbProduct);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        ProductSaveReqVO updateReqVO = randomPojo(ProductSaveReqVO.class, o -> {
-            o.setId(dbProduct.getId()); // 设置更新的 ID
-        });
-
-        // 调用
-        productService.updateProduct(updateReqVO);
-        // 校验是否更新正确
-        ErpProductDO product = productMapper.selectById(updateReqVO.getId()); // 获取最新的
-        assertPojoEquals(updateReqVO, product);
-    }
-
-    @Test
-    public void testUpdateProduct_notExists() {
-        // 准备参数
-        ProductSaveReqVO updateReqVO = randomPojo(ProductSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> productService.updateProduct(updateReqVO), PRODUCT_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteProduct_success() {
-        // mock 数据
-        ErpProductDO dbProduct = randomPojo(ErpProductDO.class);
-        productMapper.insert(dbProduct);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbProduct.getId();
-
-        // 调用
-        productService.deleteProduct(id);
-       // 校验数据不存在了
-       assertNull(productMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteProduct_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> productService.deleteProduct(id), PRODUCT_NOT_EXISTS);
-    }
-
-    @Test
-    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
-    public void testGetProductPage() {
-       // mock 数据
-       ErpProductDO dbProduct = randomPojo(ErpProductDO.class, o -> { // 等会查询到
-           o.setName(null);
-           o.setCategoryId(null);
-           o.setCreateTime(null);
-       });
-       productMapper.insert(dbProduct);
-       // 测试 name 不匹配
-       productMapper.insert(cloneIgnoreId(dbProduct, o -> o.setName(null)));
-       // 测试 categoryId 不匹配
-       productMapper.insert(cloneIgnoreId(dbProduct, o -> o.setCategoryId(null)));
-       // 测试 createTime 不匹配
-       productMapper.insert(cloneIgnoreId(dbProduct, o -> o.setCreateTime(null)));
-       // 准备参数
-       ErpProductPageReqVO reqVO = new ErpProductPageReqVO();
-       reqVO.setName(null);
-       reqVO.setCategoryId(null);
-       reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
-
-       // 调用
-       PageResult<ErpProductDO> pageResult = productService.getProductVOPage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbProduct, pageResult.getList().get(0));
-    }
-
-}

+ 0 - 131
yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImplTest.java

@@ -1,131 +0,0 @@
-package cn.iocoder.yudao.module.erp.service.sale;
-
-import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerPageReqVO;
-import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerSaveReqVO;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-import jakarta.annotation.Resource;
-
-import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-
-import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO;
-import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpCustomerMapper;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
-import org.springframework.context.annotation.Import;
-
-import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
-import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
-import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link ErpCustomerServiceImpl} 的单元测试类
- *
- * @author 芋道源码
- */
-@Import(ErpCustomerServiceImpl.class)
-public class ErpCustomerServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private ErpCustomerServiceImpl customerService;
-
-    @Resource
-    private ErpCustomerMapper customerMapper;
-
-    @Test
-    public void testCreateCustomer_success() {
-        // 准备参数
-        ErpCustomerSaveReqVO createReqVO = randomPojo(ErpCustomerSaveReqVO.class).setId(null);
-
-        // 调用
-        Long customerId = customerService.createCustomer(createReqVO);
-        // 断言
-        assertNotNull(customerId);
-        // 校验记录的属性是否正确
-        ErpCustomerDO customer = customerMapper.selectById(customerId);
-        assertPojoEquals(createReqVO, customer, "id");
-    }
-
-    @Test
-    public void testUpdateCustomer_success() {
-        // mock 数据
-        ErpCustomerDO dbCustomer = randomPojo(ErpCustomerDO.class);
-        customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        ErpCustomerSaveReqVO updateReqVO = randomPojo(ErpCustomerSaveReqVO.class, o -> {
-            o.setId(dbCustomer.getId()); // 设置更新的 ID
-        });
-
-        // 调用
-        customerService.updateCustomer(updateReqVO);
-        // 校验是否更新正确
-        ErpCustomerDO customer = customerMapper.selectById(updateReqVO.getId()); // 获取最新的
-        assertPojoEquals(updateReqVO, customer);
-    }
-
-    @Test
-    public void testUpdateCustomer_notExists() {
-        // 准备参数
-        ErpCustomerSaveReqVO updateReqVO = randomPojo(ErpCustomerSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> customerService.updateCustomer(updateReqVO), CUSTOMER_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteCustomer_success() {
-        // mock 数据
-        ErpCustomerDO dbCustomer = randomPojo(ErpCustomerDO.class);
-        customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbCustomer.getId();
-
-        // 调用
-        customerService.deleteCustomer(id);
-       // 校验数据不存在了
-       assertNull(customerMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteCustomer_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> customerService.deleteCustomer(id), CUSTOMER_NOT_EXISTS);
-    }
-
-    @Test
-    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
-    public void testGetCustomerPage() {
-       // mock 数据
-       ErpCustomerDO dbCustomer = randomPojo(ErpCustomerDO.class, o -> { // 等会查询到
-           o.setName(null);
-           o.setMobile(null);
-           o.setTelephone(null);
-       });
-       customerMapper.insert(dbCustomer);
-       // 测试 name 不匹配
-       customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setName(null)));
-       // 测试 mobile 不匹配
-       customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setMobile(null)));
-       // 测试 telephone 不匹配
-       customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setTelephone(null)));
-       // 准备参数
-       ErpCustomerPageReqVO reqVO = new ErpCustomerPageReqVO();
-       reqVO.setName(null);
-       reqVO.setMobile(null);
-       reqVO.setTelephone(null);
-
-       // 调用
-       PageResult<ErpCustomerDO> pageResult = customerService.getCustomerPage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbCustomer, pageResult.getList().get(0));
-    }
-
-}

+ 0 - 126
yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImplTest.java

@@ -1,126 +0,0 @@
-package cn.iocoder.yudao.module.erp.service.stock;
-
-import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO;
-import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSaveReqVO;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-import jakarta.annotation.Resource;
-
-import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-
-import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO;
-import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpWarehouseMapper;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-
-import org.springframework.context.annotation.Import;
-
-import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
-import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * {@link ErpWarehouseServiceImpl} 的单元测试类
- *
- * @author 芋道源码
- */
-@Import(ErpWarehouseServiceImpl.class)
-public class ErpWarehouseServiceImplTest extends BaseDbUnitTest {
-
-    @Resource
-    private ErpWarehouseServiceImpl warehouseService;
-
-    @Resource
-    private ErpWarehouseMapper warehouseMapper;
-
-    @Test
-    public void testCreateWarehouse_success() {
-        // 准备参数
-        ErpWarehouseSaveReqVO createReqVO = randomPojo(ErpWarehouseSaveReqVO.class).setId(null);
-
-        // 调用
-        Long warehouseId = warehouseService.createWarehouse(createReqVO);
-        // 断言
-        assertNotNull(warehouseId);
-        // 校验记录的属性是否正确
-        ErpWarehouseDO warehouse = warehouseMapper.selectById(warehouseId);
-        assertPojoEquals(createReqVO, warehouse, "id");
-    }
-
-    @Test
-    public void testUpdateWarehouse_success() {
-        // mock 数据
-        ErpWarehouseDO dbWarehouse = randomPojo(ErpWarehouseDO.class);
-        warehouseMapper.insert(dbWarehouse);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        ErpWarehouseSaveReqVO updateReqVO = randomPojo(ErpWarehouseSaveReqVO.class, o -> {
-            o.setId(dbWarehouse.getId()); // 设置更新的 ID
-        });
-
-        // 调用
-        warehouseService.updateWarehouse(updateReqVO);
-        // 校验是否更新正确
-        ErpWarehouseDO warehouse = warehouseMapper.selectById(updateReqVO.getId()); // 获取最新的
-        assertPojoEquals(updateReqVO, warehouse);
-    }
-
-    @Test
-    public void testUpdateWarehouse_notExists() {
-        // 准备参数
-        ErpWarehouseSaveReqVO updateReqVO = randomPojo(ErpWarehouseSaveReqVO.class);
-
-        // 调用, 并断言异常
-        assertServiceException(() -> warehouseService.updateWarehouse(updateReqVO), WAREHOUSE_NOT_EXISTS);
-    }
-
-    @Test
-    public void testDeleteWarehouse_success() {
-        // mock 数据
-        ErpWarehouseDO dbWarehouse = randomPojo(ErpWarehouseDO.class);
-        warehouseMapper.insert(dbWarehouse);// @Sql: 先插入出一条存在的数据
-        // 准备参数
-        Long id = dbWarehouse.getId();
-
-        // 调用
-        warehouseService.deleteWarehouse(id);
-       // 校验数据不存在了
-       assertNull(warehouseMapper.selectById(id));
-    }
-
-    @Test
-    public void testDeleteWarehouse_notExists() {
-        // 准备参数
-        Long id = randomLongId();
-
-        // 调用, 并断言异常
-        assertServiceException(() -> warehouseService.deleteWarehouse(id), WAREHOUSE_NOT_EXISTS);
-    }
-
-    @Test
-    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
-    public void testGetWarehousePage() {
-       // mock 数据
-       ErpWarehouseDO dbWarehouse = randomPojo(ErpWarehouseDO.class, o -> { // 等会查询到
-           o.setName(null);
-           o.setStatus(null);
-       });
-       warehouseMapper.insert(dbWarehouse);
-       // 测试 name 不匹配
-       warehouseMapper.insert(cloneIgnoreId(dbWarehouse, o -> o.setName(null)));
-       // 测试 status 不匹配
-       warehouseMapper.insert(cloneIgnoreId(dbWarehouse, o -> o.setStatus(null)));
-       // 准备参数
-       ErpWarehousePageReqVO reqVO = new ErpWarehousePageReqVO();
-       reqVO.setName(null);
-       reqVO.setStatus(null);
-
-       // 调用
-       PageResult<ErpWarehouseDO> pageResult = warehouseService.getWarehousePage(reqVO);
-       // 断言
-       assertEquals(1, pageResult.getTotal());
-       assertEquals(1, pageResult.getList().size());
-       assertPojoEquals(dbWarehouse, pageResult.getList().get(0));
-    }
-
-}