# 客户对账单 Bug 修复计划

本文档列出 antd-demo 后端对账单同步与计算中已确认的所有问题，按优先级排序。

---

## 问题总览

| # | 问题 | 影响金额（腾飞案例） | 影响金额（张晓鹏案例） | 优先级 |
|---|------|---:|---:|:---:|
| 1 | 退货单金额放错列 | 7,378 | 17,224 | P0 |
| 2 | 退货单被冗余写入收款桶 | 7,378 | 17,224 | P0 |
| 3 | SfJinE 未按 BianHaoID 去重 | 0 | 197,280 | P0 |
| 4 | 销售折扣（F_Skd XS% 行 ZkJinE）无法获取 | 2 | 583 | P1 |

---

## Bug 1：退货单金额放错列

### 现象

"外部销售退货单"行的金额被放到了"已收金额"列，应该放到"本单应收"列（负数）。

| | antd-demo 当前 | ERP 正确值 |
|---|---|---|
| 本单应收 | 0 | -7,378（负数） |
| 已收金额 | 7,378 | 0 |

### 影响

退货对欠款的减少效果被抵消，导致累欠偏高。

### 修复

同步 `sale_return` 类型的 `ExternalCustomerStatementOrder` 时：
- `positive_amount` = 0
- `negative_amount` = |JinE|（取绝对值，如 7,378）

对账单视图中"本单应收"显示为负数（= positive_amount - negative_amount = -7,378）。

---

## Bug 2：退货单被冗余写入收款桶

### 现象

同一笔 XT 退货单同时出现在"外部销售退货单"和"收款单"两种类型里。

腾飞纺织：收款单 101 行（应为 92），多出的 9 行 = 退货单。

### 影响

收款行数虚增，但金额被退货冲减，导致退货效果完全抵消。

### 修复

同步逻辑中，XT 退货单只写入退货桶（`external_sales_return_order`），不写入收款桶（`receipt_order`）。

检查点：`finance/by-customer?record_types=refund` 返回的 XT 记录不应该再创建 `ReceiptOrder`。

---

## Bug 3：SfJinE 未按 BianHaoID 去重

### 现象

`I_Sale.SfJinE` 是单据头级别字段，被冗余写到同一 BianHaoID 的每一行明细上。直接对所有明细行求和会重复计入。

张晓鹏案例：
- 7 笔现场收款订单，共 22 行明细
- 去重后 SfJinE = 77,132（正确）
- 直接 SUM = 274,412（错误，多算 197,280）

### 影响

欠款被严重低估（张晓鹏少算了 197,280 元）。

### 修复

同步时按 BianHaoID 分组，每组只取一次 SfJinE：

```python
seen = set()
total_sf = 0.0
for record in sales_records:
    if record.BianHaoID not in seen:
        seen.add(record.BianHaoID)
        total_sf += record.SfJinE
```

---

## Bug 4：销售折扣数据缺失

### 现象

`/api/v1/i-sale/by-customer` 返回的 `ZkJinE` 全部为 0。真实的销售折扣存在于 `F_Skd` 表的 XS% 行中，但当前只从 F_Skd 拉 SK%（收款）记录。

张晓鹏案例：
- receipt.ZkJinE = 233（已正确获取）✅
- sales.ZkJinE = 583（存在于 F_Skd XS% 行，无法获取）❌
- 总差额 = 816 元

### 影响

欠款偏高 583 元（销售折扣未扣减）。影响较小，大部分客户折扣为 0 或极小。

### 解决方案（需 haobuye API 配合）

**方案 A（推荐）**：让 haobuye API 的 `finance/by-customer` 接口支持 `record_types=sale`

```http
GET /api/v1/finance/by-customer?customer_name_b64=xxx&record_types=sale
```

返回 F_Skd 中 `sType=1 AND BianHaoID LIKE 'XS%'` 的记录，包含 ZkJinE 字段。

**方案 B**：用 `db/select` 补查非零折扣

```http
GET /api/v1/db/select?table=dbo.F_Skd
  &columns=BianHaoID,ZkJinE
  &where=KhID='KH00308' AND BianHaoID LIKE 'XS%' AND ZkJinE<>0
  &limit=1000
```

非零折扣行通常很少，不会触及 1000 行上限。

**方案 C**：让 haobuye API 修改 `i-sale/by-customer` 接口，按 BianHaoID join F_Skd 把真实 ZkJinE 填入返回值。

---

## 修复优先级建议

```text
第一步：修 Bug 1 + Bug 2（退货相关，影响最大，纯后端改动）
第二步：修 Bug 3（SfJinE 去重，纯后端改动）
第三步：修 Bug 4（需要 haobuye API 配合，影响最小）
```

---

## 修复后预期结果

以腾飞纺织为例：

| 项目 | 修复前 | 修复后 | ERP 正确值 |
|------|---:|---:|---:|
| 累欠金额 | 60,899 | 53,521 | 53,521 |

以张晓鹏为例（截至 5-18）：

| 项目 | 修复前 | 修复后（不含 Bug4） | 修复后（含 Bug4） | ERP |
|------|---:|---:|---:|---:|
| 累欠金额 | 748,563 | 748,330 | 747,747 | 747,747 |

---

## 验证方法

修复后用以下客户验证：

1. **木棉（KH01078）**— SfJinE=0，无折扣，预期 10,718
2. **腾飞纺织（KH00311）**— SfJinE=0，折扣=2，预期 53,521
3. **金庸（KH00290）**— SfJinE=23,394（1笔1行，不涉及去重），折扣=13,009，预期 82,670
4. **张晓鹏（KH00308）**— SfJinE=77,132（7笔22行，必须去重），折扣=816，预期与 ERP 实时值一致
