YunaiV/yudao-cloud · error · IllegalArgumentException

业务类型不正确:{}

Error message

业务类型不正确:{}

What it means

While building payment (付款单) item DOs, ErpFinancePaymentServiceImpl throws IllegalArgumentException when an item's bizType is neither PURCHASE_IN (采购入库) nor PURCHASE_RETURN (采购退货). A payment slip can only settle those two purchase-side document types; each valid item is enriched with the source document's totalPrice and no via validate + an Assert that the supplierId matches the header supplier.

Source

Thrown at yudao-module-erp/yudao-module-erp-server/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java:172

        if (updateCount == 0) {
            throw exception(approve ? FINANCE_PAYMENT_APPROVE_FAIL : FINANCE_PAYMENT_PROCESS_FAIL);
        }
    }

    private List<ErpFinancePaymentItemDO> validateFinancePaymentItems(
            Long supplierId,
            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());
                Assert.equals(purchaseIn.getSupplierId(), supplierId, "供应商必须相同");
                item.setTotalPrice(purchaseIn.getTotalPrice()).setBizNo(purchaseIn.getNo());
            } else if (ObjectUtil.equal(item.getBizType(), ErpBizTypeEnum.PURCHASE_RETURN.getType())) {
                ErpPurchaseReturnDO purchaseReturn = purchaseReturnService.validatePurchaseReturn(item.getBizId());
                Assert.equals(purchaseReturn.getSupplierId(), supplierId, "供应商必须相同");
                item.setTotalPrice(purchaseReturn.getTotalPrice().negate()).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));
        }

View on GitHub (pinned to 477be9dd49)

Solutions

  1. Use only ErpBizTypeEnum.PURCHASE_IN or PURCHASE_RETURN as bizType in payment items
  2. Use the finance receipt (收款单) API for sale-side documents (SALE_OUT / SALE_RETURN)
  3. Validate each item's bizType and bizId in the frontend before submit

Example fix

// before: sale doc in a payment
{"supplierId":1,"items":[{"bizType":3,"bizId":101}]} // SALE_OUT -> throws

// after
{"supplierId":1,"items":[{"bizType":1,"bizId":101}]} // PURCHASE_IN; sale docs go to /erp/finance-receipt
Defensive patterns

Strategy: validation

Validate before calling

for (var item : reqVO.getItems()) {
    Integer t = item.getBizType();
    if (!Objects.equals(t, ErpBizTypeEnum.PURCHASE_IN.getType())
     && !Objects.equals(t, ErpBizTypeEnum.PURCHASE_RETURN.getType())) {
        throw new IllegalArgumentException("付款单明细 bizType 必须为 采购入库/采购退货");
    }
}

Type guard

boolean isPaymentBizType(Integer bizType) {
    return Objects.equals(bizType, ErpBizTypeEnum.PURCHASE_IN.getType())
        || Objects.equals(bizType, ErpBizTypeEnum.PURCHASE_RETURN.getType());
}

Prevention

When it happens

Trigger: POST/PUT of a finance payment whose items[] contain bizType like SALE_OUT (3) or SALE_RETURN — sale documents belong to receipts, not payments; bizType null or 0 from a partially filled frontend form; API caller mixing up receipt and payment item payloads.

Common situations: Frontend form reusing one item-picker component for both payment and receipt screens; import scripts mapping ERP document kinds to the wrong finance type; client guessing bizType numbering instead of using ErpBizTypeEnum.

Related errors


AI-assisted analysis of YunaiV/yudao-cloud@477be9dd49 (2026-08-14). Data as JSON: /api/errors/6c2e425415eb9255. Report an issue: GitHub.