From d39e4f7d839167c16425086dfa2f8747bccfdff9 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 05 十一月 2026 17:39:01 +0800
Subject: [PATCH] feat: 打通销售采购财务闭环并完成累计业务优化

---
 yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInvoiceServiceImpl.java |  238 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 193 insertions(+), 45 deletions(-)

diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInvoiceServiceImpl.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInvoiceServiceImpl.java
index 19c6e7e..8df0874 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInvoiceServiceImpl.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInvoiceServiceImpl.java
@@ -3,15 +3,22 @@
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.exception.ServiceException;
 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.purchase.vo.invoice.ErpPurchaseInvoiceItemReceiptRespVO;
 import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.invoice.ErpPurchaseInvoicePageReqVO;
 import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.invoice.ErpPurchaseInvoiceSaveReqVO;
 import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInvoiceDO;
 import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO;
+import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO;
+import cn.iocoder.yudao.module.mes.api.itemreceipt.MesWmItemReceiptApi;
+import cn.iocoder.yudao.module.mes.api.itemreceipt.dto.MesWmItemReceiptLineRespDTO;
+import cn.iocoder.yudao.module.mes.api.itemreceipt.dto.MesWmItemReceiptRespDTO;
+import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpFinancePaymentMapper;
 import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseInvoiceMapper;
 import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO;
-import cn.iocoder.yudao.module.erp.enums.ErpPurchaseInvoiceAuditStatusEnum;
 import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi;
 import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
@@ -20,7 +27,11 @@
 
 import java.math.BigDecimal;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue;
@@ -44,13 +55,29 @@
     private ErpPurchaseInvoiceMapper invoiceMapper;
 
     @Resource
+    private ErpFinancePaymentMapper financePaymentMapper;
+
+    @Resource
     private ErpNoRedisDAO noRedisDAO;
 
     @Resource
     private ErpPurchaseOrderService purchaseOrderService;
 
     @Resource
+    private MesWmItemReceiptApi mesWmItemReceiptApi;
+
+    @Resource
     private StorageAttachmentApi storageAttachmentApi;
+
+    /**
+     * MES 鍏ュ簱鍗曞凡瀹屾垚鐘舵�侊紝瑙� MesWmItemReceiptStatusEnum.FINISHED
+     */
+    private static final Integer ITEM_RECEIPT_STATUS_FINISHED = 4;
+
+    /**
+     * MES 鍏ュ簱鍗曞凡鍙栨秷鐘舵�侊紝瑙� MesWmItemReceiptStatusEnum.CANCELED
+     */
+    private static final Integer ITEM_RECEIPT_STATUS_CANCELED = 5;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -65,9 +92,9 @@
             throw exception(PURCHASE_INVOICE_NO_EXISTS);
         }
 
-        // 2.1 鎻掑叆鏉ョエ锛堝垱寤哄悗鍗充负鏈鏍哥姸鎬侊級
-        ErpPurchaseInvoiceDO invoice = BeanUtils.toBean(createReqVO, ErpPurchaseInvoiceDO.class)
-                .setNo(no).setAuditStatus(ErpPurchaseInvoiceAuditStatusEnum.PROCESS.getStatus());
+        // 2.1 鎻掑叆鏉ョエ锛堝垱寤哄悗鍗充负鏈夋晥鐘舵�侊紝鏃犻渶瀹℃牳锛�
+        ErpPurchaseInvoiceDO invoice = BeanUtils.toBean(createReqVO, ErpPurchaseInvoiceDO.class).setNo(no);
+        applyItemReceiptCode(invoice);
         invoiceMapper.insert(invoice);
 
         // 2.2 缁戝畾鍙戠エ闄勪欢
@@ -85,24 +112,137 @@
             throw exception(PURCHASE_INVOICE_CREATE_FAIL_SUPPLIER_MISMATCH);
         }
         reqVO.setSupplierId(purchaseOrder.getSupplierId()); // 渚涘簲鍟嗕互閲囪喘璁㈠崟涓哄噯
+        // 鏍¢獙鍏ュ簱鍗曪紝骞跺洖濉叆搴撳崟鍙峰揩鐓�
+        validateItemReceipt(reqVO, purchaseOrder);
+    }
+
+    /**
+     * 鏍¢獙鏉ョエ缁戝畾鐨勫叆搴撳崟锛氬繀椤诲瓨鍦ㄣ�佸凡瀹屾垚鍏ュ簱銆佸睘浜庡綋鍓嶉噰璐鍗曞拰渚涘簲鍟�
+     */
+    private void validateItemReceipt(ErpPurchaseInvoiceSaveReqVO reqVO, ErpPurchaseOrderDO purchaseOrder) {
+        if (reqVO.getItemReceiptId() == null) {
+            return; // 瀛橀噺/鏈粦瀹氭椂鍏佽涓虹┖
+        }
+        MesWmItemReceiptRespDTO receipt = mesWmItemReceiptApi.getItemReceipt(reqVO.getItemReceiptId());
+        if (receipt == null) {
+            throw new ServiceException(PURCHASE_INVOICE_CREATE_FAIL_RECEIPT_NOT_EXISTS.getCode(),
+                    "鏉ョエ鍏宠仈鐨勫叆搴撳崟涓嶅瓨鍦細鍏ュ簱鍗� ID=" + reqVO.getItemReceiptId()
+                            + "銆傝閲嶆柊閫夋嫨璇ラ噰璐鍗曚笅鐨勫叆搴撳崟锛涜嫢鍒楄〃涓病鏈夊彲閫夐」锛岃鍏堝湪 MES 瀹屾垚鍏ュ簱銆�");
+        }
+        if (!ITEM_RECEIPT_STATUS_FINISHED.equals(receipt.getStatus())) {
+            throw new ServiceException(PURCHASE_INVOICE_CREATE_FAIL_RECEIPT_NOT_FINISHED.getCode(),
+                    "鏉ョエ鍏宠仈鐨勫叆搴撳崟[" + receipt.getCode() + "]褰撳墠鐘舵�佷负銆�" + itemReceiptStatusName(receipt.getStatus())
+                            + "銆嶏紝鍙湁銆屽凡瀹屾垚銆嶇殑鍏ュ簱鍗曟墠鑳芥潵绁ㄣ�傝鍏堝湪 MES 瀹屾垚鍏ュ簱鍚庡啀閫夋嫨璇ュ叆搴撳崟銆�");
+        }
+        if (ObjectUtil.notEqual(receipt.getPurchaseOrderId(), reqVO.getPurchaseOrderId())) {
+            throw new ServiceException(PURCHASE_INVOICE_CREATE_FAIL_RECEIPT_ORDER_MISMATCH.getCode(),
+                    "鎵�閫夊叆搴撳崟[" + receipt.getCode() + "]灞炰簬閲囪喘璁㈠崟[" + StrUtil.blankToDefault(receipt.getPurchaseOrderCode(), "ID=" + receipt.getPurchaseOrderId())
+                            + "]锛屼笌褰撳墠閫夋嫨鐨勯噰璐鍗昜" + purchaseOrder.getNo() + "]涓嶄竴鑷淬�傝閲嶆柊閫夋嫨璇ラ噰璐鍗曚笅鐨勫叆搴撳崟锛屾垨鍏堟牳瀵归噰璐鍗曞彿銆�");
+        }
+        if (ObjectUtil.notEqual(receipt.getVendorId(), purchaseOrder.getSupplierId())) {
+            throw new ServiceException(PURCHASE_INVOICE_CREATE_FAIL_RECEIPT_SUPPLIER_MISMATCH.getCode(),
+                    "鎵�閫夊叆搴撳崟[" + receipt.getCode() + "]鐨勪緵搴斿晢(ID=" + receipt.getVendorId()
+                            + ")涓庨噰璐鍗昜" + purchaseOrder.getNo() + "]鐨勪緵搴斿晢(ID=" + purchaseOrder.getSupplierId()
+                            + ")涓嶄竴鑷淬�傝鏍稿鍏ュ簱鍗曟潵婧愶紝鎴栨敼閫夎閲囪喘璁㈠崟涓嬬殑鍏ュ簱鍗曘��");
+        }
+    }
+
+    /**
+     * 淇濆瓨鍏ュ簱鍗曞彿蹇収锛屽垪琛ㄤ笌瀵煎嚭鐩存帴灞曠ず锛岄伩鍏嶈仈琛�
+     */
+    private void applyItemReceiptCode(ErpPurchaseInvoiceDO invoice) {
+        if (invoice.getItemReceiptId() == null) {
+            invoice.setItemReceiptCode(null);
+            return;
+        }
+        MesWmItemReceiptRespDTO receipt = mesWmItemReceiptApi.getItemReceipt(invoice.getItemReceiptId());
+        invoice.setItemReceiptCode(receipt != null ? receipt.getCode() : null);
+    }
+
+    private String itemReceiptStatusName(Integer status) {
+        if (status == null) {
+            return "鏈煡";
+        }
+        return switch (status) {
+            case 0 -> "鑽夌";
+            case 2 -> "寰呬笂鏋�";
+            case 3 -> "寰呮墽琛屽叆搴�";
+            case 4 -> "宸插畬鎴�";
+            case 5 -> "宸插彇娑�";
+            default -> "鐘舵��" + status;
+        };
     }
 
     private void validatePurchaseInvoicePriceExceedsLimit(ErpPurchaseInvoiceSaveReqVO reqVO) {
-        // 1. 璁$畻鍓╀綑鍙紑绁ㄩ噾棰濓紝涓嶅寘鎷� reqVO 鑷韩锛堝鎵逛腑涔熷崰鐢ㄩ搴︼紝闃叉绱鏉ョエ瓒呰繃閲囪喘璁㈠崟閲戦锛�
+        // 1. 璁$畻鍓╀綑鍙紑绁ㄩ噾棰濓紝涓嶅寘鎷� reqVO 鑷韩锛堟墍鏈夋湁鏁堟潵绁ㄩ兘鍗犵敤棰濆害锛岄槻姝㈢疮璁℃潵绁ㄨ秴杩囬噰璐鍗曢噾棰濓級
         ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.getPurchaseOrder(reqVO.getPurchaseOrderId());
-        List<ErpPurchaseInvoiceDO> invoices = invoiceMapper.selectListByOrderIdAndStatus(reqVO.getPurchaseOrderId(),
-                List.of(ErpPurchaseInvoiceAuditStatusEnum.DRAFT.getStatus(),
-                        ErpPurchaseInvoiceAuditStatusEnum.PROCESS.getStatus(),
-                        ErpPurchaseInvoiceAuditStatusEnum.APPROVE.getStatus()));
+        List<ErpPurchaseInvoiceDO> invoices = invoiceMapper.selectListByOrderId(reqVO.getPurchaseOrderId());
         if (reqVO.getId() != null) {
             invoices.removeIf(invoice -> ObjectUtil.equal(invoice.getId(), reqVO.getId()));
         }
         BigDecimal remainPrice = purchaseOrder.getTotalPrice().subtract(
                 getSumValue(invoices, ErpPurchaseInvoiceDO::getPrice, BigDecimal::add, BigDecimal.ZERO));
-        // 2. 鏍¢獙閲戦鏄惁瓒呰繃
+        // 2. 鏍¢獙閲戦鏄惁瓒呰繃閲囪喘璁㈠崟鍙紑绁ㄩ噾棰�
         if (reqVO.getPrice().compareTo(remainPrice) > 0) {
             throw exception(PURCHASE_INVOICE_CREATE_FAIL_PRICE_EXCEEDS_LIMIT, remainPrice);
         }
+        // 3. 缁戝畾浜嗗叆搴撳崟鏃讹紝杩樿鏍¢獙涓嶈秴杩囧叆搴撳崟鍙紑绁ㄩ噾棰濓紙鍏ュ簱閲戦 - 璇ュ叆搴撳崟宸叉潵绁ㄩ噾棰濓級
+        if (reqVO.getItemReceiptId() != null) {
+            MesWmItemReceiptRespDTO receipt = mesWmItemReceiptApi.getItemReceipt(reqVO.getItemReceiptId());
+            BigDecimal receiptTotalPrice = calcItemReceiptTotalPrice(receipt);
+            BigDecimal invoicedPrice = getItemReceiptInvoicedPrice(reqVO.getItemReceiptId(), reqVO.getId());
+            BigDecimal receiptRemainPrice = receiptTotalPrice.subtract(invoicedPrice);
+            if (reqVO.getPrice().compareTo(receiptRemainPrice) > 0) {
+                throw new ServiceException(PURCHASE_INVOICE_CREATE_FAIL_RECEIPT_PRICE_EXCEEDS_LIMIT.getCode(),
+                        "鏈鏉ョエ閲戦 " + reqVO.getPrice().stripTrailingZeros().toPlainString() + " 鍏冿紝瓒呰繃鎵�閫夊叆搴撳崟["
+                                + (receipt != null ? receipt.getCode() : "ID=" + reqVO.getItemReceiptId()) + "]鐨勫彲寮�绁ㄩ噾棰� "
+                                + receiptRemainPrice.stripTrailingZeros().toPlainString() + " 鍏冿紙鍏ュ簱閲戦 "
+                                + receiptTotalPrice.stripTrailingZeros().toPlainString() + " 鍏冿紝宸叉潵绁� "
+                                + invoicedPrice.stripTrailingZeros().toPlainString()
+                                + " 鍏冿級銆傝璋冩暣鏉ョエ閲戦锛屾垨鏀归�夊叾浠栧叆搴撳崟锛涘闇�鎸夋暣鍗曞紑绁紝璇峰厛鏍稿鍏ュ簱閲戦銆�");
+            }
+        }
+    }
+
+    /**
+     * 璁$畻鍏ュ簱鍗曢噾棰濓細浼樺厛鍙栧叆搴撹閲戦蹇収锛屽叾娆℃寜琛屽崟浠� 脳 鍏ュ簱鏁伴噺锛屾渶鍚庢寜閲囪喘璁㈠崟琛屽崟浠峰厹搴�
+     */
+    private BigDecimal calcItemReceiptTotalPrice(MesWmItemReceiptRespDTO receipt) {
+        if (receipt == null || CollUtil.isEmpty(receipt.getLines())) {
+            return BigDecimal.ZERO;
+        }
+        Map<Long, BigDecimal> orderItemPriceMap = purchaseOrderService
+                .getPurchaseOrderItemListByOrderId(receipt.getPurchaseOrderId()).stream()
+                .filter(item -> item.getProductPrice() != null)
+                .collect(Collectors.toMap(ErpPurchaseOrderItemDO::getId, ErpPurchaseOrderItemDO::getProductPrice, (a, b) -> a));
+        BigDecimal total = BigDecimal.ZERO;
+        for (MesWmItemReceiptLineRespDTO line : receipt.getLines()) {
+            BigDecimal amount = line.getTotalPrice();
+            if (amount == null && line.getPrice() != null && line.getReceivedQuantity() != null) {
+                amount = line.getPrice().multiply(line.getReceivedQuantity());
+            }
+            if (amount == null && line.getPurchaseOrderItemId() != null && line.getReceivedQuantity() != null) {
+                BigDecimal orderItemPrice = orderItemPriceMap.get(line.getPurchaseOrderItemId());
+                if (orderItemPrice != null) {
+                    amount = orderItemPrice.multiply(line.getReceivedQuantity());
+                }
+            }
+            if (amount != null) {
+                total = total.add(amount);
+            }
+        }
+        return total;
+    }
+
+    /**
+     * 璁$畻鏌愬叆搴撳崟宸叉潵绁ㄩ噾棰濓紙鍙寜鏉ョエ缂栧彿鎺掗櫎鑷韩锛�
+     */
+    private BigDecimal getItemReceiptInvoicedPrice(Long itemReceiptId, Long excludeInvoiceId) {
+        List<ErpPurchaseInvoiceDO> invoices = invoiceMapper.selectListByItemReceiptId(itemReceiptId);
+        if (excludeInvoiceId != null) {
+            invoices.removeIf(invoice -> Objects.equals(invoice.getId(), excludeInvoiceId));
+        }
+        return getSumValue(invoices, ErpPurchaseInvoiceDO::getPrice, BigDecimal::add, BigDecimal.ZERO);
     }
 
     @Override
@@ -110,17 +250,14 @@
     public void updatePurchaseInvoice(ErpPurchaseInvoiceSaveReqVO updateReqVO) {
         Assert.notNull(updateReqVO.getId(), "鏉ョエ缂栧彿涓嶈兘涓虹┖");
         // 1.1 鏍¢獙瀛樺湪
-        ErpPurchaseInvoiceDO oldInvoice = validatePurchaseInvoiceExists(updateReqVO.getId());
-        // 1.2 鍙湁鏈鏍稿彲浠ョ紪杈�
-        if (ObjectUtil.notEqual(oldInvoice.getAuditStatus(), ErpPurchaseInvoiceAuditStatusEnum.PROCESS.getStatus())) {
-            throw exception(PURCHASE_INVOICE_UPDATE_FAIL_EDITING_PROHIBITED, oldInvoice.getNo());
-        }
-        // 1.3 鏍¢獙鍏宠仈鏁版嵁 + 鍙紑绁ㄩ噾棰�
+        validatePurchaseInvoiceExists(updateReqVO.getId());
+        // 1.2 鏍¢獙鍏宠仈鏁版嵁 + 鍙紑绁ㄩ噾棰�
         validateRelationDataExists(updateReqVO);
         validatePurchaseInvoicePriceExceedsLimit(updateReqVO);
 
         // 2. 鏇存柊鏉ョエ
         ErpPurchaseInvoiceDO updateObj = BeanUtils.toBean(updateReqVO, ErpPurchaseInvoiceDO.class);
+        applyItemReceiptCode(updateObj);
         invoiceMapper.updateById(updateObj);
 
         // 3. 澧為噺鏇存柊鍙戠エ闄勪欢
@@ -131,35 +268,17 @@
     @Transactional(rollbackFor = Exception.class)
     public void deletePurchaseInvoice(Long id) {
         // 1.1 鏍¢獙瀛樺湪
-        ErpPurchaseInvoiceDO invoice = validatePurchaseInvoiceExists(id);
-        // 1.2 瀹℃壒閫氳繃鏃讹紝涓嶅厑璁稿垹闄�
-        if (ObjectUtil.equal(invoice.getAuditStatus(), ErpPurchaseInvoiceAuditStatusEnum.APPROVE.getStatus())) {
-            throw exception(PURCHASE_INVOICE_DELETE_FAIL_IS_APPROVE);
+        validatePurchaseInvoiceExists(id);
+        // 1.2 宸叉湁鏈夋晥浠樻鍗曞叧鑱旂殑鏉ョエ锛屼笉鍏佽鍒犻櫎锛堜繚鎸佹潵绁ㄤ笌浠樻鐨勫叧鑱斿畬鏁存�э級
+        Map<Long, BigDecimal> paidMap = financePaymentMapper.selectPaymentPriceMapByInvoiceId(List.of(id));
+        if (paidMap.getOrDefault(id, BigDecimal.ZERO).compareTo(BigDecimal.ZERO) > 0) {
+            throw exception(PURCHASE_INVOICE_DELETE_FAIL_HAS_PAYMENT);
         }
 
         // 2.1 鍒犻櫎鍙戠エ闄勪欢
         storageAttachmentApi.deleteAttachmentsByRecord(PURCHASE_INVOICE_RECORD_TYPE, id);
         // 2.2 鍒犻櫎鏉ョエ
         invoiceMapper.deleteById(id);
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void updatePurchaseInvoiceStatus(Long id, Integer status) {
-        boolean approve = ErpPurchaseInvoiceAuditStatusEnum.APPROVE.getStatus().equals(status);
-        // 1.1 鏍¢獙瀛樺湪
-        ErpPurchaseInvoiceDO invoice = validatePurchaseInvoiceExists(id);
-        // 1.2 鏍¢獙鐘舵��
-        if (invoice.getAuditStatus().equals(status)) {
-            throw exception(approve ? PURCHASE_INVOICE_APPROVE_FAIL : PURCHASE_INVOICE_PROCESS_FAIL);
-        }
-
-        // 2. 鏇存柊鐘舵��
-        int updateCount = invoiceMapper.updateByIdAndStatus(id, invoice.getAuditStatus(),
-                new ErpPurchaseInvoiceDO().setAuditStatus(status));
-        if (updateCount == 0) {
-            throw exception(approve ? PURCHASE_INVOICE_APPROVE_FAIL : PURCHASE_INVOICE_PROCESS_FAIL);
-        }
     }
 
     private ErpPurchaseInvoiceDO validatePurchaseInvoiceExists(Long id) {
@@ -189,18 +308,47 @@
     }
 
     @Override
-    public List<ErpPurchaseInvoiceDO> getPurchaseInvoiceListByOrderIdAndStatus(Long orderId, Collection<Integer> auditStatuses) {
-        return invoiceMapper.selectListByOrderIdAndStatus(orderId, auditStatuses);
+    public List<ErpPurchaseInvoiceDO> getPurchaseInvoiceListByOrderId(Long orderId) {
+        return invoiceMapper.selectListByOrderId(orderId);
     }
 
     @Override
-    public List<ErpPurchaseInvoiceDO> getPurchaseInvoiceListBySupplierIdAndStatus(Long supplierId, Collection<Integer> auditStatuses) {
-        return invoiceMapper.selectListBySupplierIdAndStatus(supplierId, auditStatuses);
+    public List<ErpPurchaseInvoiceDO> getPurchaseInvoiceListBySupplierId(Long supplierId) {
+        return invoiceMapper.selectListBySupplierId(supplierId);
     }
 
     @Override
-    public Long getAuditInvoiceCount() {
-        return invoiceMapper.selectCountByAudit();
+    public Map<Long, BigDecimal> getPurchaseInvoicePriceSumMapByOrderIds(Collection<Long> orderIds) {
+        if (CollUtil.isEmpty(orderIds)) {
+            return Collections.emptyMap();
+        }
+        List<ErpPurchaseInvoiceDO> invoices = invoiceMapper.selectListByOrderIds(orderIds);
+        return invoices.stream().collect(Collectors.groupingBy(ErpPurchaseInvoiceDO::getPurchaseOrderId,
+                Collectors.mapping(ErpPurchaseInvoiceDO::getPrice, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
+    }
+
+    @Override
+    public List<ErpPurchaseInvoiceItemReceiptRespVO> getItemReceiptListForInvoice(Long purchaseOrderId, Long excludeInvoiceId) {
+        if (purchaseOrderId == null) {
+            return List.of();
+        }
+        List<MesWmItemReceiptRespDTO> receipts = mesWmItemReceiptApi.getItemReceiptListByPurchaseOrderId(purchaseOrderId);
+        return receipts.stream()
+                .filter(receipt -> !ITEM_RECEIPT_STATUS_CANCELED.equals(receipt.getStatus()))
+                .map(receipt -> {
+                    BigDecimal totalPrice = calcItemReceiptTotalPrice(receipt);
+                    BigDecimal invoicedPrice = getItemReceiptInvoicedPrice(receipt.getId(), excludeInvoiceId);
+                    return new ErpPurchaseInvoiceItemReceiptRespVO()
+                            .setId(receipt.getId())
+                            .setCode(receipt.getCode())
+                            .setName(receipt.getName())
+                            .setReceiptDate(receipt.getReceiptDate())
+                            .setStatus(receipt.getStatus())
+                            .setTotalPrice(totalPrice)
+                            .setInvoicedPrice(invoicedPrice)
+                            .setRemainInvoicePrice(totalPrice.subtract(invoicedPrice));
+                })
+                .toList();
     }
 
 }

--
Gitblit v1.9.3