# 货品台账系统最小闭环后端与写入层交付说明

更新时间：2026-06-12 02:48

## 1. 云端部署状态

云服务器：`wwyl-cloud`

数据库：`goods_ledger`

后端服务：`goods-ledger-api`

监听地址：

```text
http://127.0.0.1:8791
```

运行方式：PM2 常驻进程，进程名：

```text
goods-ledger-api
```

后端代码：

```text
/srv/goods-ledger/backend
```

配置文件：

```text
/srv/goods-ledger/.env
```

说明：`.env` 内含数据库密码和写入 API Key，只报告路径，不展示内容。

## 2. Schema v2 已补充的结构化字段

本次按“宁愿为空，也要有结构化列承接”的原则，已在云端执行：

```text
/srv/goods-ledger/schema/postgres_ledger_schema_v2_structured_fields.sql
```

重点补充：

### 合同/单据

- `business_documents.contract_no`
- `business_documents.document_no_alt`
- `business_documents.external_document_no`
- `business_documents.signature_date`
- `business_documents.effective_start_date`
- `business_documents.effective_end_date`
- `business_documents.total_amount`
- `business_documents.payment_terms`
- `business_documents.delivery_terms`
- `business_documents.raw_own_party_name`
- `business_documents.raw_counterparty_name`

### 采购订单

- `purchase_orders.external_contract_no`
- `purchase_orders.supplier_contract_no_on_order`
- `purchase_orders.customer_contract_no_on_order`
- `purchase_orders.expected_arrival_start`
- `purchase_orders.expected_arrival_end`
- `purchase_orders.expected_arrival_text`
- `purchase_orders.delivery_address`
- `purchase_orders.receiver_name`
- `purchase_orders.receiver_phone_masked`
- `purchase_orders.logistics_company`
- `purchase_orders.tracking_no`
- `purchase_orders.payment_status`
- `purchase_orders.fulfillment_status`

### 订单明细

- `order_lines.line_external_no`
- `order_lines.product_code_raw`
- `order_lines.barcode_69_raw`
- `order_lines.spec_raw`
- `order_lines.color_style`
- `order_lines.package_spec`
- `order_lines.tax_rate`
- `order_lines.tax_amount`
- `order_lines.delivery_quantity`
- `order_lines.received_quantity`
- `order_lines.returned_quantity`
- `order_lines.arrival_status`
- `order_lines.expected_arrival_start`
- `order_lines.expected_arrival_end`

### 渠道分配

- `channel_allocations.allocation_type`
- `channel_allocations.planned_quantity`
- `channel_allocations.confirmed_quantity`
- `channel_allocations.shipped_quantity`
- `channel_allocations.signed_quantity`

### 库存/出入库

- `stock_items.batch_no`
- `stock_items.production_date`
- `stock_items.expiry_date`
- `stock_items.storage_location`
- `stock_items.safety_stock_qty`
- `stock_items.locked_quantity`
- `stock_movements.movement_no`
- `stock_movements.source_order_line_id`
- `stock_movements.related_movement_id`
- `stock_movements.expected_return_date`
- `stock_movements.actual_return_date`
- `stock_movements.signoff_status`
- `stock_movements.logistics_company`
- `stock_movements.tracking_no`
- `stock_movements.delivery_address`
- `stock_movements.receiver_name`

### 发货签收

- `shipment_signoffs.logistics_company`
- `shipment_signoffs.tracking_no`
- `shipment_signoffs.delivery_address`
- `shipment_signoffs.receiver_name`
- `shipment_signoffs.expected_arrival_start`
- `shipment_signoffs.expected_arrival_end`
- `shipment_signoffs.signed_at`
- `shipment_signoffs.signer_name`
- `shipment_signoff_lines.shipped_quantity`
- `shipment_signoff_lines.signed_quantity`
- `shipment_signoff_lines.rejected_quantity`
- `shipment_signoff_lines.rejection_reason`

### 文件接收与补货计划

新增：

- `file_receipts`
- `replenishment_plans`
- `replenishment_plan_lines`
- `api_write_requests`

## 3. 后端 API 已完成

基础健康：

```text
GET /health
```

只读查询：

```text
GET /api/summary
GET /api/source-files
GET /api/products
GET /api/orders
GET /api/orders/{order_id}/lines
GET /api/channel-allocations
GET /api/stock/current
GET /api/stock/movements
GET /api/shipments
GET /api/reconciliation/issues
GET /api/raw-fields
```

已验证：

```text
/health -> 200
/api/products -> 200
/api/orders -> 200
/api/stock/current -> 200
/api/shipments -> 200
/api/reconciliation/issues -> 200
```

## 4. 受控写入层已完成

写入接口需要请求头：

```text
X-Ledger-API-Key: <server-side configured key>
X-Ledger-Actor: <profile or robot name>
Idempotency-Key: <optional idempotency key>
```

接口：

```text
POST /api/write/parties
POST /api/write/products
POST /api/write/source-files
POST /api/write/purchase-orders
POST /api/write/stock-movements
POST /api/write/shipment-signoffs
POST /api/write/validation-issues
```

特性：

- 不开放裸 SQL。
- 写入按业务对象进行。
- 支持幂等键。
- 写入 `api_write_requests`。
- 写入 `agent_write_audit`。
- 出库接口会校验当前库存，不足则拒绝并写 `validation_issues`。
- 无 API Key 请求返回 401。

烟测结果：

```text
write validation issue -> success
same idempotency key -> idempotent success
api_write_requests=1
agent_audit=1 for smoke actor
no API key -> 401
```

烟测产生的测试 validation issue 已标记为 `ignored`，不污染待处理问题列表。

## 5. MCP 写入层已完成

MCP 入口：

```text
/srv/goods-ledger/backend/app/mcp_server.py
```

工具：

```text
ledger_create_party
ledger_create_product
ledger_register_source_file
ledger_create_purchase_order
ledger_add_stock_movement
ledger_create_shipment_signoff
ledger_create_validation_issue
```

已验证：

```text
mcp_server_import_ok
```

如要让 Hermes 直接发现这些 MCP 工具，下一步需要把该 MCP server 加到对应 profile 的 `mcp_servers` 配置里，并重启相应 Hermes profile/gateway；本轮没有擅自重启 profile。

## 6. 最终云端验证

现场验证结果：

```text
tables=24
business_documents.contract_no=1
purchase_orders.expected_arrival_range=3
stock_movements.logistics_fields=4
file_receipts=1
replenishment_tables=2
api_write_requests=1
agent_audit_total=2
health_ok=True database=goods_ledger
```

## 7. 下一步建议

1. 前端先做只读页面：总览、订单、渠道分配、库存流水、签收、问题中心。
2. 把写入层先给机器人试用，不直接给人工批量编辑入口。
3. 下一轮把 `mcp_server.py` 注册到需要使用的 profile；注册需要重启对应 Hermes 进程，应单独确认。
4. 继续把国博编码、69码、新品信息表、价格单等导入到产品主数据。
