From 70ea74cfb981f812bfa4e3ef91843c5ad93f7b27 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期三, 04 十一月 2026 17:32:49 +0800
Subject: [PATCH] feat(erp): 采购台账改造与采购退货增强

---
 yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java |   89 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 86 insertions(+), 3 deletions(-)

diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java
index 53da8de..36efd8a 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java
@@ -29,7 +29,9 @@
 import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseRequestMapper;
 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.ErpPaymentMethodEnum;
 import cn.iocoder.yudao.module.erp.enums.ErpPurchaseOrderInStatusEnum;
+import cn.iocoder.yudao.module.erp.enums.ErpPurchaseTypeEnum;
 import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService;
 import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
 import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO;
@@ -125,6 +127,8 @@
     public Long createPurchaseOrder(ErpPurchaseOrderSaveReqVO createReqVO, boolean submit) {
         // 1.1 鏍¢獙璁㈠崟椤圭殑鏈夋晥鎬�
         List<ErpPurchaseOrderItemDO> purchaseOrderItems = validatePurchaseOrderItems(createReqVO.getItems());
+        // 1.1.1 鏍¢獙閲囪喘鍙拌处瀛楁
+        validateLedgerFields(createReqVO);
         // 1.2 鏍¢獙渚涘簲鍟�
         supplierService.validateSupplier(createReqVO.getSupplierId());
         // 1.3 鏍¢獙缁撶畻璐︽埛
@@ -175,6 +179,8 @@
         }
         // 1.4 鏍¢獙璁㈠崟椤圭殑鏈夋晥鎬�
         List<ErpPurchaseOrderItemDO> purchaseOrderItems = validatePurchaseOrderItems(updateReqVO.getItems());
+        // 1.5 鏍¢獙閲囪喘鍙拌处瀛楁
+        validateLedgerFields(updateReqVO);
 
         // 2.1 鏇存柊璁㈠崟
         ErpPurchaseOrderDO updateObj = BeanUtils.toBean(updateReqVO, ErpPurchaseOrderDO.class);
@@ -284,6 +290,7 @@
             }
             ErpPurchaseOrderSaveReqVO.Item itemVO = new ErpPurchaseOrderSaveReqVO.Item();
             itemVO.setProductId(item.getId());
+            itemVO.setProductCode(item.getCode());
             itemVO.setProductUnitId(item.getUnitMeasureId());
             itemVO.setProductPrice(row.getProductPrice() == null ? BigDecimal.ZERO : row.getProductPrice());
             itemVO.setCount(row.getCount());
@@ -305,6 +312,11 @@
         purchaseOrder.setNo(no);
         purchaseOrder.setSupplierId(supplierId);
         purchaseOrder.setOrderTime(parseImportOrderTime(head.getOrderTime()));
+        purchaseOrder.setPurchaseType(parsePurchaseType(head.getPurchaseType()));
+        purchaseOrder.setContractNo(StrUtil.trimToNull(head.getContractNo()));
+        purchaseOrder.setProjectName(StrUtil.trimToNull(head.getProjectName()));
+        purchaseOrder.setPaymentDate(parseImportDateTime(head.getPaymentDate(), "浠樻鏃ユ湡"));
+        purchaseOrder.setPaymentMethod(parsePaymentMethod(head.getPaymentMethod()));
         purchaseOrder.setRemark(head.getRemark());
         purchaseOrder.setStatus(Boolean.TRUE.equals(directApprove)
                 ? ErpAuditStatus.APPROVE.getStatus() : ErpAuditStatus.PROCESS.getStatus());
@@ -324,8 +336,16 @@
      * 瑙f瀽瀵煎叆鐨勯噰璐椂闂达紝鍏煎澶氱甯歌鏍煎紡锛涗负绌哄彇褰撳墠鏃堕棿
      */
     private LocalDateTime parseImportOrderTime(String text) {
+        LocalDateTime value = parseImportDateTime(text, "閲囪喘鏃堕棿");
+        return value != null ? value : LocalDateTime.now();
+    }
+
+    /**
+     * 瑙f瀽瀵煎叆鐨勬棩鏈熸椂闂达紝鍏煎澶氱甯歌鏍煎紡锛涗负绌鸿繑鍥� null
+     */
+    private LocalDateTime parseImportDateTime(String text, String fieldName) {
         if (StrUtil.isBlank(text)) {
-            return LocalDateTime.now();
+            return null;
         }
         String value = text.trim();
         for (String pattern : new String[]{"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy/MM/dd HH:mm:ss"}) {
@@ -342,7 +362,33 @@
                 // 缁х画灏濊瘯涓嬩竴涓牸寮�
             }
         }
-        throw new IllegalArgumentException("閲囪喘鏃堕棿鏍煎紡涓嶆纭細" + text + "锛岀ず渚� 2026-01-01 10:00:00");
+        throw new IllegalArgumentException(fieldName + "鏍煎紡涓嶆纭細" + text + "锛岀ず渚� 2026-01-01 10:00:00");
+    }
+
+    /**
+     * 瑙f瀽瀵煎叆鐨勯噰璐被鍨嬪悕绉帮紱涓虹┖鎴栨棤娉曡瘑鍒繑鍥� null
+     */
+    private Integer parsePurchaseType(String text) {
+        if (StrUtil.isBlank(text)) {
+            return null;
+        }
+        String value = text.trim();
+        return Arrays.stream(ErpPurchaseTypeEnum.values())
+                .filter(item -> item.getName().equals(value))
+                .map(ErpPurchaseTypeEnum::getType).findFirst().orElse(null);
+    }
+
+    /**
+     * 瑙f瀽瀵煎叆鐨勪粯娆炬柟寮忓悕绉帮紱涓虹┖鎴栨棤娉曡瘑鍒繑鍥� null
+     */
+    private Integer parsePaymentMethod(String text) {
+        if (StrUtil.isBlank(text)) {
+            return null;
+        }
+        String value = text.trim();
+        return Arrays.stream(ErpPaymentMethodEnum.values())
+                .filter(item -> item.getName().equals(value))
+                .map(ErpPaymentMethodEnum::getType).findFirst().orElse(null);
     }
 
     /**
@@ -515,7 +561,7 @@
 
     private List<ErpPurchaseOrderItemDO> validatePurchaseOrderItems(List<ErpPurchaseOrderSaveReqVO.Item> list) {
         // 杞寲涓� ErpPurchaseOrderItemDO 鍒楄〃锛堜骇鍝侀獙璇佸凡绉婚櫎锛�
-        return convertList(list, o -> BeanUtils.toBean(o, ErpPurchaseOrderItemDO.class, item -> {
+        List<ErpPurchaseOrderItemDO> items = convertList(list, o -> BeanUtils.toBean(o, ErpPurchaseOrderItemDO.class, item -> {
             item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount()));
             if (item.getTotalPrice() == null) {
                 return;
@@ -525,6 +571,43 @@
                 item.setTaxPrice(MoneyUtils.taxPriceIncluded(item.getTotalPrice(), item.getTaxPercent()));
             }
         }));
+        // 閲囪喘鍙拌处锛氫骇鍝佺紪鍙峰彇 MDM 鐗╂枡缂栫爜蹇収锛屼繚璇佸垪琛�/瀵煎嚭鍙洿鎺ュ睍绀�
+        fillProductCode(items);
+        return items;
+    }
+
+    /**
+     * 鍥炲~鏄庣粏琛岀殑浜у搧缂栧彿锛圡DM 鐗╂枡缂栫爜锛�
+     */
+    private void fillProductCode(List<ErpPurchaseOrderItemDO> items) {
+        if (CollUtil.isEmpty(items)) {
+            return;
+        }
+        Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemMap(
+                convertSet(items, ErpPurchaseOrderItemDO::getProductId));
+        items.forEach(item -> {
+            MdmItemRespDTO mdmItem = itemMap.get(item.getProductId());
+            if (mdmItem == null) {
+                return;
+            }
+            if (StrUtil.isBlank(mdmItem.getCode())) {
+                throw exception(PURCHASE_ORDER_ITEM_PRODUCT_CODE_MISSING,
+                        StrUtil.blankToDefault(mdmItem.getName(), "ID=" + mdmItem.getId()));
+            }
+            item.setProductCode(mdmItem.getCode());
+        });
+    }
+
+    /**
+     * 鏍¢獙閲囪喘鍙拌处瀛楁锛堥噰璐被鍨嬨�佷粯娆炬柟寮忥級
+     */
+    private void validateLedgerFields(ErpPurchaseOrderSaveReqVO reqVO) {
+        if (!ErpPurchaseTypeEnum.isValid(reqVO.getPurchaseType())) {
+            throw exception(PURCHASE_ORDER_PURCHASE_TYPE_INVALID, reqVO.getPurchaseType());
+        }
+        if (!ErpPaymentMethodEnum.isValid(reqVO.getPaymentMethod())) {
+            throw exception(PURCHASE_ORDER_PAYMENT_METHOD_INVALID, reqVO.getPaymentMethod());
+        }
     }
 
     private void updatePurchaseOrderItemList(Long id, List<ErpPurchaseOrderItemDO> newList) {

--
Gitblit v1.9.3