docs/erp_purchase_invoice_multi_order_integration.md
@@ -37,7 +37,7 @@ | orderAllocations[].price | BigDecimal | 是 | 本张来票分摊到该订单的金额,不能小于 0 | | purchaseOrderId | Long | 否 | **不再由前端传**,后端取分摊明细第一行回填 | | supplierId | Long | 否 | **不再由前端传**,后端取第一张订单的供应商回填 | | price | BigDecimal | 是 | 来票金额,必须等于各行分摊金额之和 | | price | BigDecimal | 是 | 来票金额,必须大于等于各行分摊金额之和(未分摊部分可后续编辑补充订单) | **page 请求参数新增:** @@ -80,7 +80,7 @@ | 字段 | 展示位置 | 说明 | |------|----------|------| | 采购订单 | 来票新增/编辑弹窗 | 多选弹窗(已审核 + 未开票金额大于 0),表格列:订单号、供应商、订单金额、未开票金额、本次分摊金额(可编辑)、移除 | | 分摊合计 / 待分摊差额 | 分摊表格下方 | 实时显示,差额不为 0 时保存被拦截 | | 分摊合计 / 待分摊差额 | 分摊表格下方 | 实时显示;差额为正(未分摊)允许保存,为负(超出)时保存被拦截 | | 供应商 | 来票表单 | 由所选订单供应商带出(同一供应商),只读 | | 采购订单编号 | 来票列表 | 展示 orderNos;历史数据回退到主订单号 | | 未开票金额 | 采购订单列表 / 选择弹窗 | 按分摊明细实时计算 | @@ -89,7 +89,7 @@ | 场景 | 规则 | |------|------| | 分摊合计 | 必须等于来票金额,否则报错并列出来票金额、分摊合计和差额 | | 分摊合计 | 不能大于来票金额(超出时报错并列出来票金额、分摊合计和超出金额);允许小于来票金额,未分摊部分可保存后编辑来票再补充采购订单 | | 单订单上限 | 每行分摊金额不得超过该订单「未开票金额」(订单金额 − 其他来票已占用) | | 订单重复 | 同一张来票内同一订单只能出现一次 | | 订单状态 | 只有已审核通过(status=20)的采购订单才能登记来票 | yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java
@@ -65,7 +65,7 @@ ErrorCode PURCHASE_INVOICE_ALLOCATION_EMPTY = new ErrorCode(1_030_105_009, "请至少选择一张采购订单,并把来票金额分摊到订单上"); ErrorCode PURCHASE_INVOICE_ALLOCATION_ORDER_DUPLICATE = new ErrorCode(1_030_105_010, "同一张来票内的采购订单不能重复选择"); ErrorCode PURCHASE_INVOICE_ALLOCATION_PRICE_INVALID = new ErrorCode(1_030_105_011, "分摊金额必须填写且不能小于 0"); ErrorCode PURCHASE_INVOICE_ALLOCATION_SUM_MISMATCH = new ErrorCode(1_030_105_012, "各采购订单的分摊金额合计必须等于来票金额"); ErrorCode PURCHASE_INVOICE_ALLOCATION_SUM_MISMATCH = new ErrorCode(1_030_105_012, "各采购订单的分摊金额合计不能大于来票金额"); ErrorCode PURCHASE_INVOICE_ALLOCATION_SUPPLIER_MISMATCH = new ErrorCode(1_030_105_013, "同一张来票只能关联同一供应商的采购订单"); // ========== ERP 采购退货(1-030-103-000) ========== yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInvoiceServiceImpl.java
@@ -132,18 +132,16 @@ } // 1.2 校验所有采购订单必须是同一供应商(来票对应一个供应商) validateSameSupplier(orders); // 2. 校验分摊合计 = 来票金额 // 2. 校验分摊合计不能大于来票金额(允许小于:未分摊部分可后续编辑来票时再补充采购订单) BigDecimal allocationTotal = allocations.stream().map(ErpPurchaseInvoiceOrderReqVO::getPrice) .reduce(BigDecimal.ZERO, BigDecimal::add); if (allocationTotal.compareTo(reqVO.getPrice()) != 0) { BigDecimal diff = reqVO.getPrice().subtract(allocationTotal); String detail = diff.compareTo(BigDecimal.ZERO) > 0 ? StrUtil.format("还有 {} 元未分摊到订单,请为订单填写分摊金额或改选订单", diff.stripTrailingZeros().toPlainString()) : StrUtil.format("分摊合计比来票金额多 {} 元,请减少分摊金额", diff.negate().stripTrailingZeros().toPlainString()); if (allocationTotal.compareTo(reqVO.getPrice()) > 0) { throw new ServiceException(PURCHASE_INVOICE_ALLOCATION_SUM_MISMATCH.getCode(), StrUtil.format("来票金额 {} 元,各订单分摊合计 {} 元,两者必须相等(差额:{})。", StrUtil.format("来票金额 {} 元,各订单分摊合计 {} 元,分摊合计不能大于来票金额(超出 {} 元)。" + "请减少订单的分摊金额,或提高来票金额后重试;未分摊的部分可以留待以后再编辑来票补充采购订单。", reqVO.getPrice().stripTrailingZeros().toPlainString(), allocationTotal.stripTrailingZeros().toPlainString(), detail)); allocationTotal.stripTrailingZeros().toPlainString(), allocationTotal.subtract(reqVO.getPrice()).stripTrailingZeros().toPlainString())); } // 3. 主订单、供应商取分摊明细第一张(一张来票涉及多个供应商时,列表/付款沿用第一家) reqVO.setPurchaseOrderId(allocations.get(0).getPurchaseOrderId());