invoice_validation_update.md 8.05 KB

发票验证功能更新

修改概述

InvoiceMainServiceImpl 中的 addInvoiceupdateInvoice 方法中添加了全面的验证逻辑,确保发票中的经销商与关联订单和出库单中的经销商保持一致。

修改内容

1. 新增自定义异常类

创建了 InvoiceValidationException 异常类,用于处理发票验证失败的情况:

public class InvoiceValidationException extends RuntimeException {
    public InvoiceValidationException(String message) {
        super(message);
    }

    public InvoiceValidationException(String message, Throwable cause) {
        super(message, cause);
    }
}

2. 扩展DeliveryMainMapper接口

DeliveryMainMapper 接口中添加了 selectByDeliveryNo 方法:

@Select("SELECT * FROM t_delivery_main WHERE delivery_no = #{deliveryNo} AND del_flag = '0'")
DeliveryMain selectByDeliveryNo(@Param("deliveryNo") String deliveryNo);

3. 新增验证方法

InvoiceMainServiceImpl 中添加了两个验证方法:

validateOrderConsistency方法

private void validateOrderConsistency(String orderNo, String invoiceDealerCode) {
    // 根据订单编号查询订单信息
    OrderMain order = orderMainMapper.selectByOrderNo(orderNo);
    if (order == null) {
        throw new IllegalArgumentException("关联的订单不存在");
    }

    // 比较经销商编码
    if (!invoiceDealerCode.equals(order.getDealerCode())) {
        String errorMessage = String.format(
            "发票中的经销商编码[%s]与关联订单[%s]中的经销商编码[%s]不一致",
            invoiceDealerCode, orderNo, order.getDealerCode()
        );
        throw new InvoiceValidationException(errorMessage);
    }
}

validateDeliveryConsistency方法

private void validateDeliveryConsistency(String deliveryNo, String invoiceDealerCode) {
    // 根据出库单编号查询出库单信息
    DeliveryMain delivery = deliveryMainMapper.selectByDeliveryNo(deliveryNo);
    if (delivery == null) {
        throw new IllegalArgumentException("关联的出库单不存在");
    }

    // 比较经销商编码
    if (!invoiceDealerCode.equals(delivery.getDealerCode())) {
        String errorMessage = String.format(
            "发票中的经销商编码[%s]与关联出库单[%s]中的经销商编码[%s]不一致",
            invoiceDealerCode, deliveryNo, delivery.getDealerCode()
        );
        throw new InvoiceValidationException(errorMessage);
    }
}

4. 修改addInvoice方法

addInvoice 方法中添加了验证逻辑:

// 验证关联的订单是否存在且经销商一致
validateOrderConsistency(addReq.getOrderNo(), addReq.getDealerCode());

// 验证关联的出库单是否存在且经销商一致(如果提供了出库单号)
if (StringUtils.hasText(addReq.getDeliveryNo())) {
    validateDeliveryConsistency(addReq.getDeliveryNo(), addReq.getDealerCode());
}

5. 修改updateInvoice方法

updateInvoice 方法中添加了验证逻辑:

// 验证关联的订单是否存在且经销商一致
validateOrderConsistency(updateReq.getOrderNo(), updateReq.getDealerCode());

// 验证关联的出库单是否存在且经销商一致(如果提供了出库单号)
if (StringUtils.hasText(updateReq.getDeliveryNo())) {
    validateDeliveryConsistency(updateReq.getDeliveryNo(), updateReq.getDealerCode());
}

验证逻辑说明

验证流程

  1. 订单存在性验证:验证关联的订单编号是否在订单管理中存在
  2. 订单经销商一致性验证:验证发票中的经销商编码与关联订单中的经销商编码是否一致
  3. 出库单存在性验证:如果提供了出库单号,验证关联的出库单编号是否在出库管理中存在
  4. 出库单经销商一致性验证:如果提供了出库单号,验证发票中的经销商编码与关联出库单中的经销商编码是否一致
  5. 异常处理:如果任何验证失败,抛出相应的异常

验证时机

  • 新增发票时:在 addInvoice 方法中,在发票编号存在性验证之后立即进行验证
  • 修改发票时:在 updateInvoice 方法中,在发票编号存在性验证之后立即进行验证

异常信息

订单经销商不一致

发票中的经销商编码[DEALER002]与关联订单[ORDER001]中的经销商编码[DEALER001]不一致

出库单经销商不一致

发票中的经销商编码[DEALER002]与关联出库单[DELIVERY001]中的经销商编码[DEALER001]不一致

订单不存在

关联的订单不存在

出库单不存在

关联的出库单不存在

测试

单元测试

创建了 InvoiceMainServiceImplValidationTest 测试类,包含以下测试用例:

  1. 成功场景测试

    • 经销商一致时的正常流程
    • 不提供出库单号时的验证逻辑
    • 验证方法调用正确性
  2. 异常场景测试

    • 订单经销商不一致时抛出 InvoiceValidationException
    • 出库单经销商不一致时抛出 InvoiceValidationException
    • 订单不存在时抛出 IllegalArgumentException
    • 出库单不存在时抛出 IllegalArgumentException
  3. 异常消息测试

    • 验证异常消息格式的正确性

测试覆盖

  • ✅ 新增发票时的订单验证
  • ✅ 新增发票时的出库单验证
  • ✅ 修改发票时的订单验证
  • ✅ 修改发票时的出库单验证
  • ✅ 经销商不一致的异常处理
  • ✅ 关联记录不存在的异常处理
  • ✅ 异常消息格式验证

影响范围

修改的文件

  1. backend/src/main/java/com/apple/erp/exception/InvoiceValidationException.java - 新增异常类
  2. backend/src/main/java/com/apple/erp/mapper/DeliveryMainMapper.java - 扩展Mapper接口
  3. backend/src/main/java/com/apple/erp/service/impl/InvoiceMainServiceImpl.java - 修改服务实现
  4. backend/src/test/java/com/apple/erp/service/impl/InvoiceMainServiceImplValidationTest.java - 新增测试类

影响的方法

  • InvoiceMainServiceImpl.addInvoice() - 新增验证逻辑
  • InvoiceMainServiceImpl.updateInvoice() - 新增验证逻辑
  • 新增 validateOrderConsistency() 私有方法
  • 新增 validateDeliveryConsistency() 私有方法
  • DeliveryMainMapper.selectByDeliveryNo() - 新增查询方法

业务价值

数据一致性保障

  • 确保发票与关联订单的经销商信息保持一致
  • 确保发票与关联出库单的经销商信息保持一致
  • 防止因经销商信息不匹配导致的数据错误
  • 提高系统的数据完整性和可靠性

错误预防

  • 在数据录入阶段就发现并阻止经销商不匹配的问题
  • 提供清晰的错误信息,便于用户快速定位和修正问题
  • 减少后续业务流程中的数据异常

系统健壮性

  • 增强系统的数据验证能力
  • 提供更好的错误处理和用户反馈
  • 提高系统的整体稳定性和可维护性

向后兼容性

  • 新增的验证逻辑不会影响现有的正常业务流程
  • 只有在经销商不匹配或关联记录不存在时才会抛出异常
  • 保持了原有的方法签名和返回值类型
  • 不影响现有的API接口
  • 出库单号验证是可选的,只有在提供出库单号时才会进行验证

使用示例

成功场景

// 发票中的经销商与订单和出库单中的经销商一致
InvoiceAddReq addReq = new InvoiceAddReq();
addReq.setOrderNo("ORDER001");
addReq.setDeliveryNo("DELIVERY001");
addReq.setDealerCode("DEALER001"); // 与订单和出库单中的经销商一致

invoiceMainService.addInvoice(addReq); // 验证通过

失败场景

// 发票中的经销商与订单中的经销商不一致
InvoiceAddReq addReq = new InvoiceAddReq();
addReq.setOrderNo("ORDER001");
addReq.setDealerCode("DEALER002"); // 与订单中的经销商不一致

try {
    invoiceMainService.addInvoice(addReq);
} catch (InvoiceValidationException e) {
    System.out.println("验证失败:" + e.getMessage());
    // 输出:验证失败:发票中的经销商编码[DEALER002]与关联订单[ORDER001]中的经销商编码[DEALER001]不一致
}