# 财务ERP - 进销存模块（采购与台账）详细开发文档

## <span class="">版本历史</span>

<div class="ds-scroll-area ds-scroll-area--show-on-focus-within ds-scroll-area--enabled _1210dd7 c03cafe9" id="bkmrk-%E7%89%88%E6%9C%AC-%E6%97%A5%E6%9C%9F-%E4%BF%AE%E6%94%B9%E5%86%85%E5%AE%B9-%E4%BD%9C%E8%80%85-v1.0-2"><div class="ds-scroll-area__gutters"><div class="ds-scroll-area__horizontal-gutter">  
</div><div class="ds-scroll-area__vertical-gutter">  
</div></div><table><thead><tr><th><span class="">版本</span></th><th><span class="">日期</span></th><th><span class="">修改内容</span></th><th><span class="">作者</span></th></tr></thead><tbody><tr><td><span class="">v1.0</span></td><td><span class="">2026-06-25</span></td><td><span class="">基于20260618需求梳理，定义采购模块与台账功能</span></td><td><span class="">架构组</span></td></tr></tbody></table>

</div>---

## <span class="">1. 模块定位与范围</span>

### <span class="">1.1 模块目标</span>

<span class="">实现采购业务全流程的财务核算与台账管理，打通</span>**<span class="">采购订单 → 付款 → 入库 → 发票</span>**<span class="">的业务闭环，并提供多维度的台账查询与对账功能。本模块作为现有 </span>`wimoor-finance`<span class=""> 微服务的扩展，复用已有凭证、科目、辅助核算等基础能力。</span>

### <span class="">1.2 涉及功能清单</span>

- **<span class="">进销存配置</span>**<span class="">：采购账户、供应商收款账户、库存核算方法、凭证科目映射</span>
- **<span class="">采购单（会计版）</span>**<span class="">：创建、付款、退款、入库、退货，状态追踪</span>
- **<span class="">采购账户台账</span>**<span class="">：多维度查询、台账付款（账期结算）、批量上传对账单、退款处理</span>
- **<span class="">供应商台账</span>**<span class="">：按供应商汇总应付/已付/待付、库存价值、发票状态，支持发票入账</span>
- **<span class="">发票台账</span>**<span class="">：数电发票同步、入账、查询、统计分析</span>
- **<span class="">本地仓库台账</span>**<span class="">：移动加权平均核算，汇总账与明细账，与总账勾稽</span>
- **<span class="">FBA仓库台账</span>**<span class="">：与亚马逊库存报告对接，按月汇总核算（后续迭代）</span>

### <span class="">1.3 依赖关系</span>

- <span class="">复用 </span>`wimoor-finance`<span class=""> 现有表：</span>`fin_accounting_subjects`<span class="">、</span>`fin_vouchers`<span class="">、</span>`fin_voucher_entries`<span class="">、</span>`fin_auxiliary_*`<span class="">、</span>`fin_currency`
- <span class="">调用 </span>`wimoor-erp`<span class=""> 模块：供应商基础信息、SKU信息、仓库信息</span>
- <span class="">调用 </span>`wimoor-amazon`<span class=""> 模块：FBA库存报告数据（后续）</span>
- <span class="">调用 </span>`wimoor-admin`<span class=""> 模块：飞书多维表格连接配置（用于发票同步等）</span>

---

## <span class="">2. 数据库设计（新增表）</span>

### <span class="">2.1 采购账户表 </span>`fin_purchase_account`

<span class="">已在原文档中定义，此处补充字段说明：</span>

<div class="ds-scroll-area ds-scroll-area--show-on-focus-within ds-scroll-area--enabled _1210dd7 c03cafe9" id="bkmrk-%E5%AD%97%E6%AE%B5-%E7%B1%BB%E5%9E%8B-%E8%AF%B4%E6%98%8E-id-bigint-u"><div class="ds-scroll-area__gutters"><div class="ds-scroll-area__horizontal-gutter">  
</div><div class="ds-scroll-area__vertical-gutter">  
</div></div><table><thead><tr><th><span class="">字段</span></th><th><span class="">类型</span></th><th><span class="">说明</span></th></tr></thead><tbody><tr><td>`id`</td><td><span class="">bigint unsigned</span></td><td><span class="">主键</span></td></tr><tr><td>`groupid`</td><td><span class="">bigint unsigned</span></td><td><span class="">租户ID（账套）</span></td></tr><tr><td>`account_name`</td><td><span class="">varchar(100)</span></td><td><span class="">账户名称，如“公户现金”“跨境直采”</span></td></tr><tr><td>`account_type`</td><td><span class="">tinyint</span></td><td><span class="">1-现金，2-账期</span></td></tr><tr><td>`related_subject_id`</td><td><span class="">bigint unsigned</span></td><td><span class="">对应会计科目ID（如“银行存款-浦发”）</span></td></tr><tr><td>`config_json`</td><td><span class="">json</span></td><td><span class="">完整配置：费用类型列表、归属标记、借贷科目映射、退款设置、支持的付款账户等</span></td></tr><tr><td>`is_enabled`</td><td><span class="">tinyint</span></td><td><span class="">是否启用</span></td></tr><tr><td>`created_time`</td><td><span class="">datetime</span></td><td> </td></tr><tr><td>`updated_time`</td><td><span class="">datetime</span></td><td> </td></tr></tbody></table>

</div>**<span class="">config\_json 结构示例：</span>**

<div class="md-code-block md-code-block-light" id="bkmrk-json"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">json</span></div></div></div></div></div>```
{
  "feeTypes": [
    { "code": "GOODS", "name": "货款", "isSupplierRelated": true },
    { "code": "FREIGHT", "name": "运费", "isSupplierRelated": true },
    { "code": "SERVICE", "name": "跨境直采手续费", "isSupplierRelated": false }
  ],
  "paySubjectMapping": {
    "GOODS": { "debitSubjectId": 101, "creditSubjectId": 201 },
    "FREIGHT": { "debitSubjectId": 102, "creditSubjectId": 201 },
    "SERVICE": { "debitSubjectId": 501, "creditSubjectId": 201 }
  },
  "refundMapping": {
    "GOODS": { "debitSubjectId": 201, "creditSubjectId": 101 },
    "FREIGHT": { "debitSubjectId": 201, "creditSubjectId": 102 }
  },
  "creditPayAccounts": [  // 仅账期类型有效，可选的现金账户列表
    { "cashAccountId": 1, "subjectMapping": { "debit": 301, "credit": 201 } }
  ]
}
```

<div class="md-code-block md-code-block-light" id="bkmrk--2"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>### <span class="">2.2 采购订单表 </span>`fin_purchase_order`

<span class="">已在原文档中定义，补充以下索引和约束：</span>

<div class="md-code-block md-code-block-light" id="bkmrk-sql"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">sql</span></div></div></div></div></div>```
ALTER TABLE `fin_purchase_order` 
ADD INDEX `idx_status_pay` (`status_pay`),
ADD INDEX `idx_status_inv` (`status_inv`),
ADD INDEX `idx_status_stock` (`status_stock`);
```

<div class="md-code-block md-code-block-light" id="bkmrk--3"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>### <span class="">2.3 采购付款明细表 </span>`fin_purchase_payment`

<span class="">已在原文档定义，确保与 </span>`purchase_order_id`<span class=""> 和 </span>`voucher_id`<span class=""> 关联。</span>

### <span class="">2.4 供应商收款账户表 </span>`fin_supplier_bank`

<span class="">（新增）用于维护供应商的多个收款账户信息：</span>

<div class="md-code-block md-code-block-light" id="bkmrk-sql-1"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">sql</span></div></div></div></div></div>```
CREATE TABLE `fin_supplier_bank` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `groupid` bigint unsigned NOT NULL,
  `supplier_id` bigint unsigned NOT NULL,
  `bank_name` varchar(100) COLLATE utf8mb4_bin DEFAULT NULL,
  `account_name` varchar(100) COLLATE utf8mb4_bin NOT NULL,
  `account_no` varchar(50) COLLATE utf8mb4_bin NOT NULL,
  `is_default` tinyint DEFAULT '0',
  `is_enabled` tinyint DEFAULT '1',
  `created_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_supplier` (`supplier_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='供应商收款账户';
```

<div class="md-code-block md-code-block-light" id="bkmrk--4"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>### <span class="">2.5 库存余额表 </span>`fin_warehouse_stock`

<span class="">已在原文档定义，新增 </span>`warehouse_type`<span class=""> 字段区分本地/FBA：</span>

<div class="md-code-block md-code-block-light" id="bkmrk-sql-2"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">sql</span></div></div></div></div></div>```
ALTER TABLE `fin_warehouse_stock` ADD COLUMN `warehouse_type` tinyint DEFAULT '1' COMMENT '1-本地，2-FBA';
```

<div class="md-code-block md-code-block-light" id="bkmrk--5"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>### <span class="">2.6 库存变动明细表 </span>`fin_inventory_transaction`

<span class="">已在原文档定义。</span>

### <span class="">2.7 采购发票关联表（可选）</span>

<span class="">为支持“一张发票对应多笔采购订单”，可新增中间表，但当前简化设计，发票直接关联凭证，通过凭证分录的辅助核算追踪订单，暂不建中间表。</span>

---

## <span class="">3. 核心业务逻辑</span>

### <span class="">3.1 采购付款凭证生成规则（完整版）</span>

<span class="">根据需求，采购付款涉及三个环节：</span>**<span class="">付款</span>**<span class="">、</span>**<span class="">在途库存确认</span>**<span class="">、</span>**<span class="">发票入账</span>**<span class="">。系统按以下规则自动生成凭证。</span>

#### <span class="">3.1.1 现金类账户付款（公户、跨境直采等）</span>

- **<span class="">付款时（采购单点击“付款”）</span>**<span class="">：</span>
    
    
    - <span class="">凭证1（付款）：</span>
        
        <div class="md-code-block md-code-block-light"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">text</span></div></div></div></div></div>```
        借：预付账款-ERP采购供应商   (供应商辅助核算)
        贷：银行存款-浦发银行(2384) / 其他货币资金-连连跨境直采
        ```
        
        <div class="md-code-block md-code-block-light"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>
    - <span class="">凭证2（在途库存）：</span>
        
        <div class="md-code-block md-code-block-light"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">text</span></div></div></div></div></div>```
        借：在途库存_XX本地仓库   (存货辅助核算)
        贷：预付账款-ERP在途发票
        ```
        
        <div class="md-code-block md-code-block-light"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>
- **<span class="">收到发票时（发票入账操作）</span>**<span class="">：</span>
    
    <div class="md-code-block md-code-block-light"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">text</span></div></div></div></div></div>```
    借：预付账款-ERP在途发票
    贷：预付账款-ERP采购供应商
    ```
    
    <div class="md-code-block md-code-block-light"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>
- **<span class="">入库时（采购单收货）</span>**<span class="">：</span>
    
    <div class="md-code-block md-code-block-light"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">text</span></div></div></div></div></div>```
    借：库存商品_XX本地仓库   (存货辅助核算)
    贷：在途库存_XX本地仓库
    ```
    
    <div class="md-code-block md-code-block-light"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>

#### <span class="">3.1.2 账期类账户付款（先采后付、公户请款等）</span>

- **<span class="">采购单点击“付款”（即发起请款）</span>**<span class="">：</span>
    
    <div class="md-code-block md-code-block-light"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">text</span></div></div></div></div></div>```
    借：预付账款-ERP采购供应商
    贷：应付账款_1688先采后付  （或应付账款_公户请款即付等）
    ```
    
    <div class="md-code-block md-code-block-light"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>
- **<span class="">在途库存确认</span>**<span class="">（同3.1.1）：</span>
    
    <div class="md-code-block md-code-block-light"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">text</span></div></div></div></div></div>```
    借：在途库存_XX本地仓库
    贷：预付账款-ERP在途发票
    ```
    
    <div class="md-code-block md-code-block-light"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>
- **<span class="">台账付款（实际还款）</span>**<span class="">：</span>
    
    
    - <span class="">借：应付账款\_1688先采后付</span>
    - <span class="">贷：银行存款-浦发 / 其他货币资金-连连跨境直采</span>
    - <span class="">若有跨境直采手续费，另加一笔：</span>
        
        <div class="md-code-block md-code-block-light"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">text</span></div></div></div></div></div>```
        借：财务费用_跨境直采
        贷：其他货币资金-连连跨境直采
        ```
        
        <div class="md-code-block md-code-block-light"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>

#### <span class="">3.1.3 退款处理</span>

<span class="">退款时，根据已付款、已入库、已开票的不同状态，系统自动生成红字冲销凭证（方向相反），并更新台账。具体规则已在需求中列出，此处不再赘述。</span>

#### <span class="">3.1.4 辅助核算要求</span>

<span class="">所有涉及供应商的科目必须启用“供应商”辅助核算；涉及存货的科目启用“存货”辅助核算（即SKU）。系统在生成凭证时自动填充 </span>`fin_voucher_entries_auxiliary`<span class=""> 表。</span>

---

### <span class="">3.2 移动加权平均成本计算</span>

<span class="">在每次采购入库、盘盈入库时，重新计算库存单价。出库时，出库成本 = 出库数量 × 当前移动单价。</span>

**<span class="">Java 核心实现：</span>**

<div class="md-code-block md-code-block-light" id="bkmrk-java"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">java</span></div></div></div></div></div>```
@Component
public class MovingAverageCostCalculator {

    /**
     * 计算新移动平均单价
     * @param currentQty 当前数量
     * @param currentAmount 当前金额
     * @param inQty 入库数量（正数）
     * @param inAmount 入库金额（正数）
     * @return 新单价，保留4位小数
     */
    public BigDecimal calculateNewUnitCost(BigDecimal currentQty, BigDecimal currentAmount,
                                           BigDecimal inQty, BigDecimal inAmount) {
        if (inQty.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        BigDecimal newQty = currentQty.add(inQty);
        if (newQty.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        BigDecimal newAmount = currentAmount.add(inAmount);
        return newAmount.divide(newQty, 4, RoundingMode.HALF_UP);
    }

    /**
     * 计算出库成本（金额）
     */
    public BigDecimal calculateOutCost(BigDecimal qty, BigDecimal unitCost) {
        return qty.multiply(unitCost).setScale(2, RoundingMode.HALF_UP);
    }
}
```

<div class="md-code-block md-code-block-light" id="bkmrk--8"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>**<span class="">库存余额更新（确保不反算）：</span>**

<div class="md-code-block md-code-block-light" id="bkmrk-java-1"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">java</span></div></div></div></div></div>```
@Transactional
public void updateStockForTransaction(InventoryTransactionDTO dto) {
    // 1. 获取当前期间库存
    WarehouseStock stock = stockMapper.selectBySkuPeriod(...);
    BigDecimal oldQty = stock.getCurrentQty();
    BigDecimal oldAmount = stock.getCurrentAmount();
    BigDecimal oldUnitCost = stock.getUnitCost();

    if (dto.getTransType() == PURCHASE_IN) {
        // 入库：重新计算单价
        BigDecimal newUnitCost = calculateNewUnitCost(oldQty, oldAmount, dto.getQty(), dto.getAmount());
        stock.setUnitCost(newUnitCost);
        stock.setCurrentQty(oldQty.add(dto.getQty()));
        stock.setCurrentAmount(oldAmount.add(dto.getAmount()));
    } else if (dto.getTransType() == SALE_OUT) {
        // 出库：使用当前单价计算成本
        BigDecimal cost = calculateOutCost(dto.getQty().abs(), oldUnitCost);
        dto.setAmountChange(cost.negate()); // 记录变动金额
        stock.setCurrentQty(oldQty.subtract(dto.getQty().abs()));
        stock.setCurrentAmount(oldAmount.subtract(cost));
        // 单价不变
    }
    // 其他类型（调拨、盘点等）类似...
    stockMapper.updateById(stock);
    // 插入变动明细
    inventoryTransactionMapper.insert(buildTransaction(dto, oldUnitCost));
}
```

<div class="md-code-block md-code-block-light" id="bkmrk--9"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>---

### <span class="">3.3 采购账户台账查询与批量付款</span>

#### <span class="">3.3.1 台账列表查询</span>

<span class="">支持多维度筛选（采购账户、账套、时间、状态），返回以下核心字段：</span>

- <span class="">账簿、采购账户、采购订单号、SKU、供应商、收款账号</span>
- <span class="">付款状态、库存状态、发票状态</span>
- <span class="">金额字段：订单金额、请款金额（归属供应商）、已付金额、待付金额</span>
- <span class="">库存字段：库存价值、已入库价值、待入库价值</span>
- <span class="">发票字段：应开票金额、已开票金额、待开票金额</span>

**<span class="">SQL 查询核心（MyBatis XML）：</span>**

<div class="md-code-block md-code-block-light" id="bkmrk-xml"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">xml</span></div></div></div></div></div>```
<select id="queryLedgerList" resultType="com.wimoor.finance.vo.PurchaseLedgerVO">
    SELECT 
        po.groupid,
        po.id as orderId,
        po.sku,
        s.name as supplierName,
        sb.account_no as bankAccount,
        po.total_amount,
        po.paid_amount,
        po.inventory_value,
        po.invoiced_amount,
        -- 计算待付、待入库、待开票
        (po.total_amount - po.paid_amount) as pending_pay,
        (po.inventory_value - IFNULL(SUM(ir.received_value),0)) as pending_stock,
        (po.total_amount - po.invoiced_amount) as pending_invoice,
        po.status_pay,
        po.status_stock,
        po.status_inv
    FROM fin_purchase_order po
    LEFT JOIN t_erp_supplier s ON po.supplier_id = s.id
    LEFT JOIN fin_supplier_bank sb ON s.id = sb.supplier_id AND sb.is_default=1
    LEFT JOIN fin_inventory_transaction ir ON po.id = ir.source_doc_id AND ir.trans_type='RECEIVE'
    WHERE po.groupid = #{groupid}
    <if test="accountIds != null and accountIds.size()>0">
        AND po.purchase_account_id IN 
    </if>
    <if test="startDate != null"> AND po.created_time >= #{startDate} </if>
    <if test="endDate != null"> AND po.created_time < #{endDate} </if>
    <if test="payStatus != null"> AND po.status_pay IN ... </if>
    GROUP BY po.id
    ORDER BY po.created_time DESC
</select>
```

<div class="md-code-block md-code-block-light" id="bkmrk--11"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>#### <span class="">3.3.2 台账付款操作</span>

- <span class="">前端勾选多条记录 → 调用 </span>`/api/finance/ledger/purchase-account/ledger-pay`
- <span class="">后端校验：所有记录必须属于同一个账期采购账户；必须选择现金类付款账户</span>
- <span class="">生成凭证（借贷科目按配置）并插入 </span>`fin_purchase_payment`<span class="">，更新 </span>`paid_amount`<span class=""> 和状态</span>
- <span class="">支持分摊：若付款金额与应付总额不一致，按比例分摊到尾差处理</span>

**<span class="">批量上传对账单（Excel）流程：</span>**

1. <span class="">下载模板（含列：采购订单号、SKU、应付金额、本次付款金额、费用类型）</span>
2. <span class="">用户填写后上传</span>
3. <span class="">后端解析，校验订单号有效、未超额付款</span>
4. <span class="">预览确认，用户提交</span>
5. <span class="">批量生成付款记录和凭证</span>

---

### <span class="">3.4 供应商台账与发票入账</span>

#### <span class="">3.4.1 供应商台账查询</span>

<span class="">与采购账户台账类似，但按</span>**<span class="">供应商</span>**<span class="">维度汇总，展示：</span>

- <span class="">供应商、账簿、采购订单明细</span>
- <span class="">应付/已付/待付（归属供应商）</span>
- <span class="">库存价值、已入库、待入库</span>
- <span class="">应开票、已开票、待开票</span>

#### <span class="">3.4.2 发票入账操作</span>

- <span class="">前端勾选多条未开票记录 → 选择数电发票（从发票台账中选）</span>
- <span class="">调用 </span>`/api/finance/ledger/invoice/post`
- <span class="">后端：生成凭证：</span>
    
    <div class="md-code-block md-code-block-light"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">text</span></div></div></div></div></div>```
    借：预付账款-ERP在途发票
    贷：预付账款-ERP采购供应商
    ```
    
    <div class="md-code-block md-code-block-light"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>
- <span class="">同时更新采购订单的 </span>`invoiced_amount`<span class=""> 和 </span>`status_inv`<span class="">，更新发票的 </span>`posting_status=1`<span class="">、</span>`voucher_id`
- <span class="">支持发票分摊到多条订单（按订单待开票金额比例）</span>

---

### <span class="">3.5 发票台账同步与入账</span>

#### <span class="">3.5.1 发票数据同步</span>

- <span class="">定时任务调用税局电子发票API（或从金蝶拉取），将数电发票信息写入 </span>`fin_invoice`
- <span class="">同步时，根据发票销方税号匹配内部供应商（</span>`supplier_id`<span class="">），若无法匹配则记录为“待匹配”</span>
- <span class="">同步后，发票状态默认为“正常”</span>

#### <span class="">3.5.2 发票台账查询</span>

<span class="">提供多维度筛选（账簿、销方、日期、入账状态、发票状态），展示发票号码、开票日期、价税合计、税额、入账状态等。</span>

#### <span class="">3.5.3 手工入账（未匹配自动入账）</span>

<span class="">用户可在发票台账页面勾选发票，选择“入账”，系统生成凭证（借：预付账款-ERP在途发票 贷：预付账款-ERP采购供应商），并关联供应商（若之前未匹配）。</span>

---

### <span class="">3.6 本地仓库台账（移动加权平均核算）</span>

#### <span class="">3.6.1 汇总账</span>

<span class="">按“期间 + 账簿 + SKU + 仓库”展示期初、入库、出库、期末的数量和金额。</span>

- <span class="">期初 = 上一期间期末</span>
- <span class="">入库 = 所有 </span>`PURCHASE_IN`<span class=""> 类型变动汇总</span>
- <span class="">出库 = 所有 </span>`SALE_OUT`<span class=""> 类型变动汇总</span>
- <span class="">期末 = 期初 + 入库 - 出库</span>

**<span class="">勾稽校验</span>**<span class="">：期末金额应与对应会计科目（库存商品）余额一致，若不一致，系统提示差异。</span>

#### <span class="">3.6.2 明细账</span>

<span class="">展示每笔库存变动明细：操作时间、类型、数量、单价、金额变动、关联单据号、凭证号。支持按SKU、仓库、时间筛选。</span>

---

## <span class="">4. API 接口详细设计</span>

### <span class="">4.1 采购账户管理</span>

<div class="ds-scroll-area ds-scroll-area--show-on-focus-within ds-scroll-area--enabled _1210dd7 c03cafe9" id="bkmrk-%E6%96%B9%E6%B3%95-%E8%B7%AF%E5%BE%84-%E8%AF%B4%E6%98%8E-%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0-post-%2F"><div class="ds-scroll-area__gutters"><div class="ds-scroll-area__horizontal-gutter">  
</div><div class="ds-scroll-area__vertical-gutter">  
</div></div><table><thead><tr><th><span class="">方法</span></th><th><span class="">路径</span></th><th><span class="">说明</span></th><th><span class="">请求参数</span></th></tr></thead><tbody><tr><td><span class="">POST</span></td><td>`/api/finance/purchase/account/create`</td><td><span class="">创建采购账户</span></td><td>`PurchaseAccountSaveDTO`</td></tr><tr><td><span class="">PUT</span></td><td>`/api/finance/purchase/account/update`</td><td><span class="">更新配置</span></td><td>`PurchaseAccountUpdateDTO`</td></tr><tr><td><span class="">GET</span></td><td>`/api/finance/purchase/account/list`</td><td><span class="">查询可用账户</span></td><td>`groupid`</td></tr><tr><td><span class="">GET</span></td><td>`/api/finance/purchase/account/detail/{id}`</td><td><span class="">获取详情</span></td><td>`id`</td></tr></tbody></table>

</div>### <span class="">4.2 采购订单（会计版）</span>

<div class="ds-scroll-area ds-scroll-area--show-on-focus-within ds-scroll-area--enabled _1210dd7 c03cafe9" id="bkmrk-%E6%96%B9%E6%B3%95-%E8%B7%AF%E5%BE%84-%E8%AF%B4%E6%98%8E-%E8%AF%B7%E6%B1%82%E5%8F%82%E6%95%B0-post-%2F-1"><div class="ds-scroll-area__gutters"><div class="ds-scroll-area__horizontal-gutter">  
</div><div class="ds-scroll-area__vertical-gutter">  
</div></div><table><thead><tr><th><span class="">方法</span></th><th><span class="">路径</span></th><th><span class="">说明</span></th><th><span class="">请求参数</span></th></tr></thead><tbody><tr><td><span class="">POST</span></td><td>`/api/finance/purchase/order/create`</td><td><span class="">创建采购订单（从ERP业务单转换）</span></td><td>`PurchaseOrderSaveDTO`</td></tr><tr><td><span class="">POST</span></td><td>`/api/finance/purchase/order/pay`</td><td><span class="">付款（生成凭证）</span></td><td>`PurchasePayDTO`<span class="">（含付款账户、费用明细）</span></td></tr><tr><td><span class="">POST</span></td><td>`/api/finance/purchase/order/refund`</td><td><span class="">退款</span></td><td>`RefundDTO`</td></tr><tr><td><span class="">POST</span></td><td>`/api/finance/purchase/order/receive`</td><td><span class="">入库</span></td><td>`ReceiveDTO`<span class="">（收货数量/金额）</span></td></tr><tr><td><span class="">GET</span></td><td>`/api/finance/purchase/order/page`</td><td><span class="">订单列表</span></td><td>`PageQuery`<span class=""> + 筛选条件</span></td></tr></tbody></table>

</div>### <span class="">4.3 采购账户台账</span>

<div class="ds-scroll-area ds-scroll-area--show-on-focus-within ds-scroll-area--enabled _1210dd7 c03cafe9" id="bkmrk-%E6%96%B9%E6%B3%95-%E8%B7%AF%E5%BE%84-%E8%AF%B4%E6%98%8E-get-%2Fapi%2Ffi"><div class="ds-scroll-area__gutters"><div class="ds-scroll-area__horizontal-gutter">  
</div><div class="ds-scroll-area__vertical-gutter">  
</div></div><table><thead><tr><th><span class="">方法</span></th><th><span class="">路径</span></th><th><span class="">说明</span></th></tr></thead><tbody><tr><td><span class="">GET</span></td><td>`/api/finance/ledger/purchase/page`</td><td><span class="">台账列表（分页）</span></td></tr><tr><td><span class="">POST</span></td><td>`/api/finance/ledger/purchase/ledger-pay`</td><td><span class="">台账付款（批量）</span></td></tr><tr><td><span class="">POST</span></td><td>`/api/finance/ledger/purchase/upload-pay`</td><td><span class="">上传对账单批量付款</span></td></tr><tr><td><span class="">GET</span></td><td>`/api/finance/ledger/purchase/statistics`</td><td><span class="">统计图表数据</span></td></tr></tbody></table>

</div>### <span class="">4.4 供应商台账</span>

<div class="ds-scroll-area ds-scroll-area--show-on-focus-within ds-scroll-area--enabled _1210dd7 c03cafe9" id="bkmrk-%E6%96%B9%E6%B3%95-%E8%B7%AF%E5%BE%84-%E8%AF%B4%E6%98%8E-get-%2Fapi%2Ffi-1"><div class="ds-scroll-area__gutters"><div class="ds-scroll-area__horizontal-gutter">  
</div><div class="ds-scroll-area__vertical-gutter">  
</div></div><table><thead><tr><th><span class="">方法</span></th><th><span class="">路径</span></th><th><span class="">说明</span></th></tr></thead><tbody><tr><td><span class="">GET</span></td><td>`/api/finance/ledger/supplier/page`</td><td><span class="">供应商台账列表</span></td></tr><tr><td><span class="">POST</span></td><td>`/api/finance/ledger/supplier/invoice-post`</td><td><span class="">发票入账</span></td></tr><tr><td><span class="">GET</span></td><td>`/api/finance/ledger/supplier/export-uninvoiced`</td><td><span class="">导出未开票明细</span></td></tr></tbody></table>

</div>### <span class="">4.5 发票台账</span>

<div class="ds-scroll-area ds-scroll-area--show-on-focus-within ds-scroll-area--enabled _1210dd7 c03cafe9" id="bkmrk-%E6%96%B9%E6%B3%95-%E8%B7%AF%E5%BE%84-%E8%AF%B4%E6%98%8E-get-%2Fapi%2Ffi-2"><div class="ds-scroll-area__gutters"><div class="ds-scroll-area__horizontal-gutter">  
</div><div class="ds-scroll-area__vertical-gutter">  
</div></div><table><thead><tr><th><span class="">方法</span></th><th><span class="">路径</span></th><th><span class="">说明</span></th></tr></thead><tbody><tr><td><span class="">GET</span></td><td>`/api/finance/ledger/invoice/page`</td><td><span class="">发票台账列表</span></td></tr><tr><td><span class="">POST</span></td><td>`/api/finance/ledger/invoice/sync`</td><td><span class="">手动触发同步（定时任务自动）</span></td></tr><tr><td><span class="">POST</span></td><td>`/api/finance/ledger/invoice/post`</td><td><span class="">发票入账（勾选后）</span></td></tr><tr><td><span class="">GET</span></td><td>`/api/finance/ledger/invoice/statistics`</td><td><span class="">发票统计</span></td></tr></tbody></table>

</div>### <span class="">4.6 库存台账</span>

<div class="ds-scroll-area ds-scroll-area--show-on-focus-within ds-scroll-area--enabled _1210dd7 c03cafe9" id="bkmrk-%E6%96%B9%E6%B3%95-%E8%B7%AF%E5%BE%84-%E8%AF%B4%E6%98%8E-get-%2Fapi%2Ffi-3"><div class="ds-scroll-area__gutters"><div class="ds-scroll-area__horizontal-gutter">  
</div><div class="ds-scroll-area__vertical-gutter">  
</div></div><table><thead><tr><th><span class="">方法</span></th><th><span class="">路径</span></th><th><span class="">说明</span></th></tr></thead><tbody><tr><td><span class="">GET</span></td><td>`/api/finance/ledger/stock/summary`</td><td><span class="">汇总账（按期间）</span></td></tr><tr><td><span class="">GET</span></td><td>`/api/finance/ledger/stock/detail`</td><td><span class="">明细账（按SKU）</span></td></tr><tr><td><span class="">GET</span></td><td>`/api/finance/ledger/stock/check`</td><td><span class="">勾稽校验（与总账对比）</span></td></tr></tbody></table>

</div>---

## <span class="">5. 服务层实现要点</span>

### <span class="">5.1 采购付款服务（</span>`PurchasePaymentService`<span class="">）</span>

- <span class="">职责：处理采购单付款、退款、台账付款</span>
- <span class="">主要方法：</span>
    
    
    - `payOrder(PurchasePayDTO)`<span class="">：校验账户余额（现金类）、生成凭证、更新订单状态、更新台账</span>
    - `ledgerPay(LedgerPayDTO)`<span class="">：批量处理账期还款，支持分摊</span>
    - `refund(RefundDTO)`<span class="">：退款，生成红字凭证，更新订单状态</span>

### <span class="">5.2 库存服务（</span>`InventoryService`<span class="">）</span>

- <span class="">职责：管理库存余额、变动明细、成本计算</span>
- <span class="">主要方法：</span>
    
    
    - `onPurchaseReceive(PurchaseOrder order, ReceiveDTO)`<span class="">：入库，调用成本计算器更新库存</span>
    - `onSaleOut(SaleOutDTO)`<span class="">：销售出库，计算成本并更新库存</span>
    - `getStockSummary(String period)`<span class="">：汇总账查询</span>
    - `getStockDetail(String sku)`<span class="">：明细账查询</span>

### <span class="">5.3 发票服务（</span>`InvoiceService`<span class="">）</span>

- <span class="">职责：同步税局发票、匹配供应商、入账</span>
- <span class="">主要方法：</span>
    
    
    - `syncFromTaxAPI()`<span class="">：调用外部API拉取发票</span>
    - `matchSupplier()`<span class="">：根据税号匹配供应商</span>
    - `postInvoice(InvoicePostingDTO)`<span class="">：生成入账凭证，关联采购订单</span>

### <span class="">5.4 台账查询服务（</span>`LedgerQueryService`<span class="">）</span>

- <span class="">职责：提供采购账户、供应商、发票、库存的统一查询视图</span>
- <span class="">使用 MyBatis-Plus 分页 + 复杂SQL关联查询</span>

---

## <span class="">6. 前端页面交互设计</span>

### <span class="">6.1 采购单（会计版）页面</span>

- **<span class="">列表页</span>**<span class="">：展示订单号、SKU、供应商、金额、付款/库存/发票状态；支持筛选、排序</span>
- **<span class="">详情/操作页</span>**<span class="">：显示完整信息，提供“付款”“退款”“收货”“退货”按钮，点击弹出对应表单</span>
- **<span class="">付款表单</span>**<span class="">：选择采购账户（带出对应费用类型）、填写金额、选择供应商收款账户</span>

### <span class="">6.2 采购账户台账页面</span>

- **<span class="">筛选区</span>**<span class="">：采购账户下拉、账套、时间、状态</span>
- **<span class="">表格</span>**<span class="">：展示上述金额字段，底部汇总行</span>
- **<span class="">操作区</span>**<span class="">：“台账付款”按钮（勾选后弹出付款对话框），“导出对账单”按钮</span>
- **<span class="">图表页签</span>**<span class="">：按日期展示付款趋势图</span>

### <span class="">6.3 供应商台账页面</span>

- **<span class="">筛选区</span>**<span class="">：供应商下拉、账套、时间</span>
- **<span class="">表格</span>**<span class="">：展示应付/已付/待付、库存价值、应开票/已开票/待开票</span>
- **<span class="">操作</span>**<span class="">：“发票入账”按钮（勾选后弹出选择发票对话框）</span>

### <span class="">6.4 发票台账页面</span>

- **<span class="">筛选区</span>**<span class="">：账簿、销方、日期、入账状态</span>
- **<span class="">表格</span>**<span class="">：发票号码、金额、税额、状态</span>
- **<span class="">操作</span>**<span class="">：“同步”按钮（手动触发），“入账”按钮</span>

### <span class="">6.5 本地仓库台账</span>

- **<span class="">汇总账</span>**<span class="">：期间选择、SKU搜索，展示期初/入库/出库/期末数量和金额，提供校验标识</span>
- **<span class="">明细账</span>**<span class="">：点击SKU跳转明细，展示每笔变动，联查凭证</span>

---

## <span class="">7. 定时任务与消息队列</span>

### <span class="">7.1 定时任务（XXL-JOB）</span>

<div class="ds-scroll-area ds-scroll-area--show-on-focus-within ds-scroll-area--enabled _1210dd7 c03cafe9" id="bkmrk-%E4%BB%BB%E5%8A%A1%E5%90%8D%E7%A7%B0-cron-%E8%AF%B4%E6%98%8E-invoice"><div class="ds-scroll-area__gutters"><div class="ds-scroll-area__horizontal-gutter">  
</div><div class="ds-scroll-area__vertical-gutter">  
</div></div><table><thead><tr><th><span class="">任务名称</span></th><th><span class="">Cron</span></th><th><span class="">说明</span></th></tr></thead><tbody><tr><td>`InvoiceSyncJob`</td><td>`0 0 2 * * ?`</td><td><span class="">同步税局发票数据</span></td></tr><tr><td>`StockCheckJob`</td><td>`0 0 3 1 * ?`</td><td><span class="">每月1号执行库存与总账勾稽校验</span></td></tr><tr><td>`AutoPostInvoiceJob`</td><td>`0 0/30 9-18 * * ?`</td><td><span class="">工作时间内自动匹配未入账发票（可选）</span></td></tr></tbody></table>

</div>### <span class="">7.2 消息队列（RabbitMQ）</span>

- <span class="">采购订单状态变更时，发送事件（如 </span>`ORDER_PAID`<span class="">、</span>`ORDER_RECEIVED`<span class="">）到 exchange，库存服务、台账服务监听更新。</span>
- <span class="">避免同步调用，提高响应速度。</span>

---

## <span class="">8. 异常处理与日志</span>

### <span class="">8.1 异常场景</span>

- <span class="">付款金额超过订单未付金额 → 提示“超额付款”</span>
- <span class="">发票金额与订单待开票金额不一致 → 提示“金额不符，请确认分摊”</span>
- <span class="">供应商未维护收款账户 → 提示“请先维护供应商收款信息”</span>
- <span class="">科目配置缺失 → 提示“采购账户科目映射不完整，请联系管理员”</span>

### <span class="">8.2 日志规范</span>

- <span class="">关键操作（付款、退款、入库、发票入账）记录 INFO 日志，包含操作人、订单号、金额</span>
- <span class="">异常堆栈记录 ERROR 日志，并发送飞书告警（通过 </span>`wimoor-common`<span class=""> 的告警组件）</span>

---

## <span class="">9. 测试策略</span>

### <span class="">9.1 单元测试（JUnit + Mockito）</span>

- <span class="">移动加权平均计算器</span>
- <span class="">凭证生成逻辑（各场景）</span>
- <span class="">分摊算法</span>

### <span class="">9.2 集成测试（@SpringBootTest + Testcontainers）</span>

- <span class="">完整流程：创建订单 → 现金付款 → 入库 → 发票入账 → 查询台账</span>
- <span class="">账期流程：创建订单 → 账期付款 → 台账付款 → 查询供应商待付</span>
- <span class="">退款流程：部分退款、全额退款（不同状态组合）</span>

### <span class="">9.3 前端测试（Vue Test Utils）</span>

- <span class="">页面渲染、表单交互、数据校验</span>

---

## <span class="">10. 部署与配置</span>

### <span class="">10.1 依赖环境</span>

- <span class="">MySQL 8.0（已有）</span>
- <span class="">Redis（用于缓存科目、辅助核算项）</span>
- <span class="">RabbitMQ（事件驱动）</span>
- <span class="">XXL-JOB（调度中心）</span>

### <span class="">10.2 配置示例（application.yml）</span>

<div class="md-code-block md-code-block-light" id="bkmrk-yaml"><div class="md-code-block-banner-wrap"><div class="md-code-block-banner md-code-block-banner-lite"><div class="_121d384"><div class="d2a24f03"><span class="d813de27">yaml</span></div></div></div></div></div>```
wimoor:
  finance:
    inventory:
      cost-method: moving_average   # 仅支持移动加权
    invoice:
      sync-api: https://api.tax.gov/invoice
      sync-cron: 0 0 2 * * ?
    ledger:
      batch-size: 1000   # 批量导入单次最大行数
```

<div class="md-code-block md-code-block-light" id="bkmrk--22"><svg class="_9bc997d _33882ae" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg><svg class="_9bc997d _28d7e84" fill="none" height="12" viewbox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M-5.24537e-07 0C-2.34843e-07 6.62742 5.37258 12 12 12L0 12L-5.24537e-07 0Z" fill="currentColor"></path></svg></div>---

## <span class="">11. 后续扩展规划</span>

- **<span class="">FBA仓库台账</span>**<span class="">：对接亚马逊库存报告，按月汇总，与本地仓库成本联动</span>
- **<span class="">关务台账</span>**<span class="">：报关单与FBA货件关联，统计出口数据</span>
- **<span class="">无票成本统计</span>**<span class="">：在利润表中增加无票成本明细</span>
- **<span class="">银行API对接</span>**<span class="">：自动获取对公账户流水，与采购账户对账</span>

---

> **<span class="">开发周期估计</span>**<span class="">：</span>
> 
> - <span class="">数据库设计与基础服务：3天</span>
> - <span class="">核心业务逻辑（凭证生成、成本计算、台账查询）：5天</span>
> - <span class="">接口开发与联调：4天</span>
> - <span class="">前端页面开发：5天</span>
> - <span class="">测试与修复：3天</span>  
>     **<span class="">总计约20人天</span>**