一、供应链财务管理概述

1.1 什么是供应链财务管理

供应链财务管理是指对供应链运营过程中产生的财务活动进行计划、核算、分析和控制,以实现供应链成本最优和企业价值最大化。

核心内容

  • 应付管理:供应商款项支付、账期管理
  • 应收管理:客户款项回收、信用管理
  • 成本核算:采购成本、仓储成本、运输成本
  • 对账结算:供应商对账、客户对账、内部结算
  • 财务报表:成本分析、利润分析、现金流分析
  • 成本优化:降本增效、精益管理

1.2 供应链成本构成

供应链总成本
├── 采购成本(40-50%)
│   ├── 采购价款
│   ├── 运输费用
│   └── 关税税费
├── 仓储成本(20-25%)
│   ├── 仓库租金
│   ├── 人工成本
│   └── 设备折旧
├── 运输成本(15-20%)
│   ├── 干线运输
│   ├── 末端配送
│   └── 包装材料
└── 库存成本(10-15%)
    ├── 资金占用
    ├── 损耗报废
    └── 保险费用

行业数据(以零售电商为例):

  • 供应链成本占销售额的60-80%
  • 降低1%供应链成本,利润提升5-10%
  • 库存周转天数:30-45天
  • 应付账款周期:60-90天

二、应付账款管理

2.1 应付账款核心流程

采购订单 → 收货验收 → 发票验证 → 应付入账 → 付款审批 → 付款执行

2.2 应付账款数据模型

-- 应付账款主表
CREATE TABLE accounts_payable (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  ap_no VARCHAR(64) UNIQUE NOT NULL COMMENT '应付单号',
  supplier_id BIGINT NOT NULL COMMENT '供应商ID',
  purchase_order_no VARCHAR(64) COMMENT '采购订单号',
  invoice_no VARCHAR(64) COMMENT '发票号',
  
  -- 金额信息
  total_amount DECIMAL(15,2) NOT NULL COMMENT '应付总金额',
  paid_amount DECIMAL(15,2) DEFAULT 0 COMMENT '已付金额',
  unpaid_amount DECIMAL(15,2) NOT NULL COMMENT '未付金额',
  currency VARCHAR(10) DEFAULT 'CNY' COMMENT '币种',
  
  -- 账期信息
  invoice_date DATE COMMENT '发票日期',
  payment_term INT COMMENT '账期(天)',
  due_date DATE COMMENT '到期日期',
  
  -- 状态信息
  status VARCHAR(20) DEFAULT 'PENDING' COMMENT '状态:PENDING/PARTIAL_PAID/PAID/OVERDUE',
  payment_status VARCHAR(20) COMMENT '付款状态',
  
  -- 审计字段
  created_time DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  
  INDEX idx_supplier (supplier_id),
  INDEX idx_due_date (due_date),
  INDEX idx_status (status)
) ENGINE=InnoDB COMMENT='应付账款主表';

-- 应付明细表
CREATE TABLE accounts_payable_detail (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  ap_no VARCHAR(64) NOT NULL COMMENT '应付单号',
  sku VARCHAR(64) NOT NULL COMMENT 'SKU编码',
  quantity INT NOT NULL COMMENT '数量',
  unit_price DECIMAL(10,2) NOT NULL COMMENT '单价',
  amount DECIMAL(15,2) NOT NULL COMMENT '金额',
  
  INDEX idx_ap_no (ap_no)
) ENGINE=InnoDB COMMENT='应付明细表';

2.3 账期优化策略

public class PaymentTermOptimizer {
    
    // 计算最优付款计划
    public List<PaymentPlan> optimizePaymentPlan(List<AccountsPayable> apList) {
        List<PaymentPlan> plans = new ArrayList<>();
        
        // 1. 按到期日期排序
        apList.sort(Comparator.comparing(AccountsPayable::getDueDate));
        
        // 2. 考虑现金流约束
        BigDecimal availableCash = getAvailableCash();
        
        // 3. 优先支付折扣款项
        for (AccountsPayable ap : apList) {
            // 如果有早付折扣,优先支付
            if (hasEarlyPaymentDiscount(ap)) {
                BigDecimal discountAmount = calculateDiscount(ap);
                if (discountAmount.compareTo(ap.getUnpaidAmount()) > 0) {
                    plans.add(new PaymentPlan(ap, LocalDate.now()));
                    availableCash = availableCash.subtract(ap.getUnpaidAmount());
                }
            }
        }
        
        // 4. 正常付款
        for (AccountsPayable ap : apList) {
            if (ap.getDueDate().isBefore(LocalDate.now().plusDays(7))) {
                plans.add(new PaymentPlan(ap, ap.getDueDate()));
            }
        }
        
        return plans;
    }
    
    // 计算早付折扣
    private BigDecimal calculateDiscount(AccountsPayable ap) {
        // 假设10天内付款有2%折扣
        if (ChronoUnit.DAYS.between(LocalDate.now(), ap.getDueDate()) > 10) {
            return ap.getUnpaidAmount().multiply(new BigDecimal("0.02"));
        }
        return BigDecimal.ZERO;
    }
}

三、应收账款管理

3.1 应收账款数据模型

-- 应收账款主表
CREATE TABLE accounts_receivable (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  ar_no VARCHAR(64) UNIQUE NOT NULL COMMENT '应收单号',
  customer_id BIGINT NOT NULL COMMENT '客户ID',
  order_no VARCHAR(64) COMMENT '订单号',
  invoice_no VARCHAR(64) COMMENT '发票号',
  
  -- 金额信息
  total_amount DECIMAL(15,2) NOT NULL COMMENT '应收总金额',
  received_amount DECIMAL(15,2) DEFAULT 0 COMMENT '已收金额',
  unreceived_amount DECIMAL(15,2) NOT NULL COMMENT '未收金额',
  
  -- 账期信息
  invoice_date DATE COMMENT '发票日期',
  payment_term INT COMMENT '账期(天)',
  due_date DATE COMMENT '到期日期',
  overdue_days INT DEFAULT 0 COMMENT '逾期天数',
  
  -- 信用管理
  credit_level VARCHAR(10) COMMENT '客户信用等级',
  risk_level VARCHAR(20) COMMENT '风险等级:LOW/MEDIUM/HIGH',
  
  -- 状态信息
  status VARCHAR(20) DEFAULT 'PENDING',
  
  INDEX idx_customer (customer_id),
  INDEX idx_due_date (due_date),
  INDEX idx_overdue (overdue_days)
) ENGINE=InnoDB COMMENT='应收账款主表';

3.2 信用风险管控

public class CreditRiskManager {
    
    // 信用评估
    public CreditRating evaluateCredit(Customer customer) {
        CreditRating rating = new CreditRating();
        
        // 1. 历史付款记录(40%权重)
        double paymentScore = calculatePaymentScore(customer);
        
        // 2. 财务状况(30%权重)
        double financialScore = calculateFinancialScore(customer);
        
        // 3. 业务合作时长(20%权重)
        double cooperationScore = calculateCooperationScore(customer);
        
        // 4. 行业风险(10%权重)
        double industryScore = calculateIndustryScore(customer);
        
        // 综合评分
        double totalScore = paymentScore * 0.4 + financialScore * 0.3 
                          + cooperationScore * 0.2 + industryScore * 0.1;
        
        // 评级
        if (totalScore >= 90) {
            rating.setLevel("AAA");
            rating.setCreditLimit(new BigDecimal("5000000"));
        } else if (totalScore >= 80) {
            rating.setLevel("AA");
            rating.setCreditLimit(new BigDecimal("3000000"));
        } else if (totalScore >= 70) {
            rating.setLevel("A");
            rating.setCreditLimit(new BigDecimal("1000000"));
        } else {
            rating.setLevel("B");
            rating.setCreditLimit(new BigDecimal("500000"));
        }
        
        return rating;
    }
    
    // 信用额度检查
    public boolean checkCreditLimit(Customer customer, BigDecimal orderAmount) {
        // 1. 获取信用额度
        BigDecimal creditLimit = customer.getCreditLimit();
        
        // 2. 计算已占用额度
        BigDecimal usedCredit = arMapper.sumUnreceivedByCustomer(customer.getId());
        
        // 3. 可用额度
        BigDecimal availableCredit = creditLimit.subtract(usedCredit);
        
        // 4. 检查是否超额
        return availableCredit.compareTo(orderAmount) >= 0;
    }
}

3.3 催收策略

public class CollectionService {
    
    @Scheduled(cron = "0 9 * * * ?") // 每天9点执行
    public void autoCollection() {
        // 1. 查询逾期应收
        List<AccountsReceivable> overdueList = arMapper.selectOverdue();
        
        for (AccountsReceivable ar : overdueList) {
            int overdueDays = ar.getOverdueDays();
            
            // 2. 分级催收
            if (overdueDays <= 7) {
                // 一级催收:系统自动发送短信提醒
                sendSMS(ar.getCustomer(), "温馨提醒:您有应收款项即将到期");
            } else if (overdueDays <= 30) {
                // 二级催收:客户经理电话催收
                assignToSales(ar);
            } else {
                // 三级催收:法务介入
                assignToLegal(ar);
            }
        }
    }
}

四、成本核算

4.1 成本核算模型

-- 成本核算主表
CREATE TABLE cost_accounting (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  cost_no VARCHAR(64) UNIQUE NOT NULL,
  cost_type VARCHAR(20) NOT NULL COMMENT '成本类型:PURCHASE/WAREHOUSE/TRANSPORT/INVENTORY',
  reference_no VARCHAR(64) COMMENT '关联单号',
  
  -- 成本明细
  total_cost DECIMAL(15,2) NOT NULL COMMENT '总成本',
  unit_cost DECIMAL(10,2) COMMENT '单位成本',
  quantity INT COMMENT '数量',
  
  -- 成本分摊
  allocated_cost JSON COMMENT '成本分摊明细',
  
  -- 时间维度
  cost_period VARCHAR(20) COMMENT '成本期间:2025-11',
  cost_date DATE COMMENT '成本日期',
  
  INDEX idx_type_period (cost_type, cost_period)
) ENGINE=InnoDB COMMENT='成本核算表';

4.2 采购成本核算

public class PurchaseCostCalculator {
    
    public PurchaseCost calculate(PurchaseOrder order) {
        PurchaseCost cost = new PurchaseCost();
        
        // 1. 采购价款
        BigDecimal goodsAmount = order.getItems().stream()
            .map(item -> item.getQuantity().multiply(item.getUnitPrice()))
            .reduce(BigDecimal.ZERO, BigDecimal::add);
        cost.setGoodsAmount(goodsAmount);
        
        // 2. 运输费用
        BigDecimal freightCost = calculateFreight(order);
        cost.setFreightCost(freightCost);
        
        // 3. 关税税费
        BigDecimal taxCost = calculateTax(order);
        cost.setTaxCost(taxCost);
        
        // 4. 其他费用(报关、商检等)
        BigDecimal otherCost = calculateOtherCost(order);
        cost.setOtherCost(otherCost);
        
        // 5. 总成本
        BigDecimal totalCost = goodsAmount.add(freightCost)
                                         .add(taxCost)
                                         .add(otherCost);
        cost.setTotalCost(totalCost);
        
        // 6. 单位成本
        int totalQty = order.getItems().stream()
            .mapToInt(PurchaseOrderItem::getQuantity)
            .sum();
        BigDecimal unitCost = totalCost.divide(
            new BigDecimal(totalQty), 
            2, 
            RoundingMode.HALF_UP
        );
        cost.setUnitCost(unitCost);
        
        return cost;
    }
}

4.3 库存成本核算

public class InventoryCostCalculator {
    
    // 加权平均成本法
    public BigDecimal calculateWeightedAverageCost(String sku) {
        // 1. 查询当前库存
        List<InventoryTransaction> transactions = inventoryMapper.selectBySku(sku);
        
        BigDecimal totalCost = BigDecimal.ZERO;
        int totalQty = 0;
        
        // 2. 计算加权平均
        for (InventoryTransaction txn : transactions) {
            if (txn.getType() == TransactionType.IN) {
                totalCost = totalCost.add(
                    txn.getUnitCost().multiply(new BigDecimal(txn.getQuantity()))
                );
                totalQty += txn.getQuantity();
            }
        }
        
        // 3. 加权平均成本
        if (totalQty == 0) {
            return BigDecimal.ZERO;
        }
        
        return totalCost.divide(
            new BigDecimal(totalQty), 
            2, 
            RoundingMode.HALF_UP
        );
    }
    
    // 先进先出法(FIFO)
    public BigDecimal calculateFIFOCost(String sku, int outQty) {
        // 按入库时间排序
        List<InventoryTransaction> inTransactions = 
            inventoryMapper.selectInTransactions(sku);
        
        BigDecimal totalCost = BigDecimal.ZERO;
        int remainQty = outQty;
        
        for (InventoryTransaction txn : inTransactions) {
            if (remainQty <= 0) break;
            
            int qty = Math.min(remainQty, txn.getAvailableQty());
            totalCost = totalCost.add(
                txn.getUnitCost().multiply(new BigDecimal(qty))
            );
            remainQty -= qty;
        }
        
        return totalCost;
    }
}

五、财务对账与结算

5.1 自动对账系统

public class AutoReconciliationService {
    
    // 供应商对账
    public ReconciliationResult reconcile(Long supplierId, String period) {
        ReconciliationResult result = new ReconciliationResult();
        
        // 1. 获取应付数据(我方系统)
        List<AccountsPayable> apList = apMapper.selectBySupplierAndPeriod(
            supplierId, period
        );
        BigDecimal ourTotal = apList.stream()
            .map(AccountsPayable::getTotalAmount)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        // 2. 获取供应商账单数据
        List<SupplierInvoice> invoices = supplierApiClient.getInvoices(
            supplierId, period
        );
        BigDecimal supplierTotal = invoices.stream()
            .map(SupplierInvoice::getAmount)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        // 3. 对账比对
        if (ourTotal.compareTo(supplierTotal) == 0) {
            result.setStatus("MATCHED");
            result.setDifference(BigDecimal.ZERO);
        } else {
            result.setStatus("UNMATCHED");
            result.setDifference(ourTotal.subtract(supplierTotal));
            
            // 4. 差异明细分析
            List<DifferenceDetail> differences = analyzeDifferences(
                apList, invoices
            );
            result.setDifferences(differences);
        }
        
        return result;
    }
    
    // 差异分析
    private List<DifferenceDetail> analyzeDifferences(
        List<AccountsPayable> apList,
        List<SupplierInvoice> invoices
    ) {
        List<DifferenceDetail> differences = new ArrayList<>();
        
        // 将发票转为Map,便于比对
        Map<String, SupplierInvoice> invoiceMap = invoices.stream()
            .collect(Collectors.toMap(
                SupplierInvoice::getInvoiceNo,
                inv -> inv
            ));
        
        // 比对每笔应付
        for (AccountsPayable ap : apList) {
            SupplierInvoice invoice = invoiceMap.get(ap.getInvoiceNo());
            
            if (invoice == null) {
                // 我方有,供应商无
                differences.add(new DifferenceDetail(
                    DifferenceType.MISSING_IN_SUPPLIER,
                    ap.getApNo(),
                    ap.getTotalAmount()
                ));
            } else if (!ap.getTotalAmount().equals(invoice.getAmount())) {
                // 金额不一致
                differences.add(new DifferenceDetail(
                    DifferenceType.AMOUNT_MISMATCH,
                    ap.getApNo(),
                    ap.getTotalAmount().subtract(invoice.getAmount())
                ));
            }
        }
        
        return differences;
    }
}

六、财务报表分析

6.1 成本分析报表

public class CostAnalysisService {
    
    // 生成成本分析报表
    public CostAnalysisReport generateReport(String period) {
        CostAnalysisReport report = new CostAnalysisReport();
        report.setPeriod(period);
        
        // 1. 采购成本分析
        BigDecimal purchaseCost = costMapper.sumByTypeAndPeriod(
            CostType.PURCHASE, period
        );
        report.setPurchaseCost(purchaseCost);
        
        // 2. 仓储成本分析
        BigDecimal warehouseCost = costMapper.sumByTypeAndPeriod(
            CostType.WAREHOUSE, period
        );
        report.setWarehouseCost(warehouseCost);
        
        // 3. 运输成本分析
        BigDecimal transportCost = costMapper.sumByTypeAndPeriod(
            CostType.TRANSPORT, period
        );
        report.setTransportCost(transportCost);
        
        // 4. 库存成本分析
        BigDecimal inventoryCost = costMapper.sumByTypeAndPeriod(
            CostType.INVENTORY, period
        );
        report.setInventoryCost(inventoryCost);
        
        // 5. 总成本
        BigDecimal totalCost = purchaseCost.add(warehouseCost)
                                          .add(transportCost)
                                          .add(inventoryCost);
        report.setTotalCost(totalCost);
        
        // 6. 成本占比分析
        report.setPurchaseCostRatio(
            purchaseCost.divide(totalCost, 4, RoundingMode.HALF_UP)
        );
        
        return report;
    }
}

七、降本增效实践

7.1 降本策略

采购降本

  1. 集中采购,提高议价能力
  2. 供应商比价,选择最优方案
  3. 长期合同,锁定优惠价格
  4. 联合采购,共享供应商资源

仓储降本

  1. 优化库位,提高空间利用率
  2. 共享仓库,降低固定成本
  3. 自动化设备,提升作业效率

运输降本

  1. 路线优化,减少运输里程
  2. 整车运输,降低单位成本
  3. 共享配送,提高满载率

库存降本

  1. 精准预测,降低安全库存
  2. 快速周转,减少资金占用
  3. 呆滞清理,避免积压损失

下一篇预告:《应付账款管理:供应商账款、付款计划与账期优化》

参考资料

  1. 《供应链财务管理实务》
  2. 《成本会计:传统与创新》
  3. SAP ERP财务模块官方文档