# dealerhub · 阶段 2 完整实施报告 > PLAN.md 阶段 2 全部落地;本文件记录执行结果。 ## ✅ 阶段 2 完成清单(按"模型 → 序列化 → service → async view → 测试") ### 1. core.workflow.StateMachine(14 个测试通过) - `apps/core/workflow.py`:通用状态机服务,支持 guard / action / hook / 事务 - `apps/core/tests/test_workflow.py`:14 个测试覆盖合法迁移 / 非法事件 / guard 拒绝 / action 触发 / hook 触发 / 完整链路 ### 2. apps.partner(7 个测试通过) - `Partner / Customer / Supplier / PriceLevel / Contact` 5 个模型 - 完整序列化、async ViewSet、URL 路由 - 测试:CRUD、search、租户隔离 ### 3. apps.inventory(13 个测试通过) - `Warehouse / Stock / StockMovement` 3 个模型 - `services.py` 原子化:inbound / outbound / lock / unlock / adjust,全部带 select_for_update + transaction.atomic + 流水 - `available = on_hand - locked` 字段 - 加权平均成本自动维护 - 测试:入出库、并发安全、锁定释放、负数拒绝、调整 ### 4. apps.finance(8 个测试通过) - `Receivable / Payable / Receipt / Payment / Allocation` 5 个模型 - `services.py`:create_receivable_from_sale / create_payable_from_purchase / allocate_receipt / allocate_payment - 部分付款、跨单分摊、金额校验 ### 5. apps.purchase(5 个测试通过) - `PurchaseOrder / PurchaseOrderLine / PurchaseBill / PurchaseBillLine` - `services.create_purchase_bill` + `confirm_purchase_bill`(自动写库存 + 生成应付) - 双重过账拒绝 ### 6. apps.sales(6 个测试通过) - `SalesOrder / SalesOrderLine / SalesBill / SalesBillLine` - `services.create_sales_bill` + `confirm_sales_bill`(自动扣库存 + 生成应收) - 库存不足回滚 ### 7. 端到端冒烟测试(3 个测试通过) `tests/test_e2e.py`:建商品 → 建仓库 → 建客户/供应商 → 进货单过账(写库存 + 生成应付)→ 付款单核销 → 销售单过账(扣库存 + 生成应收)→ 收款单核销 → 结清 — 全链路 1 个事务里跑通,状态完全一致。 ### 8. Docker 部署到 lan-19216857(PostgreSQL + Granian) - `infra/docker/Dockerfile.backend`:Python 3.12 + Granian + psycopg[pool] + 全部依赖 - `docker-compose.yml`:连既有 `pg-shared` 网络 → 复用 pg-main 容器,自动 `CREATE ROLE/DB dealerhub` - 服务名:`backend-backend-1`,端口 18050 → 容器 8000 - 4 worker + 1 runtime-threads - 容器内 ping 通过;smoke.sh 通过;多租户 CRUD 通过 --- ## ✅ 验证证据 ### 1. 测试总览 ``` $ python -m pytest -p no:cacheprovider ============================== 65 passed, 77 warnings in 0.87s ============================== ``` | 模块 | 测试数 | 结果 | |---|---|---| | apps.core.workflow | 14 | ✅ | | tests.test_catalog | 6 | ✅ | | tests.test_partner | 7 | ✅ | | tests.test_inventory | 13 | ✅ | | tests.test_finance | 8 | ✅ | | tests.test_purchase | 5 | ✅ | | tests.test_sales | 6 | ✅ | | tests.test_e2e | 3 | ✅ | | 其他(ping/tenant)| 3 | ✅ | | **合计** | **65** | **✅** | ### 2. Docker 部署 ``` $ docker ps | grep dealerhub backend-backend-1 Up (healthy) 0.0.0.0:18050->8000/tcp ``` ### 3. 服务端冒烟(smoke.sh) ``` [1/8] ping {"ok":true,"service":"dealerhub",...} [2/8] JWT 登录 TOKEN 长度: 231 [3/8] 仓库 CRUD warehouse id=1 [4/8] 商品CRUD product id=1 [5/8] 客户/供应商CRUD supplier id=1, customer id=1 [6/8] 列表查询 products:1, warehouses:1, customers:1, suppliers:1 ===== 全部通过 ===== ``` --- ## 📁 主要新增文件(阶段 2) ``` dealerhub/backend/apps/ ├── core/ │ ├── workflow.py ← 状态机服务 │ ├── viewset.py ← BaseTenantViewSet + StandardAsyncPagination(共享给所有 app) │ └── tests/test_workflow.py ← 14 测试 ├── partner/ │ ├── models.py / serializers.py / views.py / urls.py / apps.py │ └── apps.py ├── inventory/ │ ├── models.py / serializers.py / views.py / urls.py / services.py ← 原子化库存服务 │ └── apps.py ├── finance/ │ ├── models.py / serializers.py / views.py / urls.py / services.py ← 应收应付核销 │ └── apps.py ├── purchase/ │ ├── models.py / serializers.py / views.py / urls.py / services.py ← 进货单过账 │ └── apps.py └── sales/ ├── models.py / serializers.py / views.py / urls.py / services.py ← 销售单过账 └── apps.py dealerhub/backend/tests/ ├── test_partner.py ← 7 测试 ├── test_inventory.py ← 13 测试 ├── test_finance.py ← 8 测试 ├── test_purchase.py ← 5 测试 ├── test_sales.py ← 6 测试 └── test_e2e.py ← 3 测试(端到端) dealerhub/backend/ ├── docker-compose.yml ← 部署配置 ├── infra/docker/Dockerfile.backend └── infra/scripts/run_prod_granian.sh ← 用 --runtime-threads 修复 Granian 2.8 API ``` ``` dealerhub/ └── smoke.sh ← 内网端到端冒烟脚本 ``` --- ## 🚀 部署信息(lan-19216857) ```bash # 服务地址(内网) http://192.168.5.7:18050 # 容器 backend-backend-1 ← Django 5.2 + DRF + adrf + Granian 2.8 ASGI backend-pg-bootstrap ← 一次性建 dealerhub role/db # 数据库 PostgreSQL: pg-main (1Panel 既有容器,192.168.5.7:5433 → 容器 5432) DB: dealerhub / owner dealerhub / password=Chunyu10086086 # 默认账号 username: alice / password: alice12345 / superuser 默认租户: X-Tenant-Id: default # 启动/停止 cd /home/chunyu/dealerhub/backend DJANGO_SECRET_KEY="..." POSTGRES_PASSWORD="Chunyu10086086" docker compose up -d docker compose down docker logs -f backend-backend-1 # 冒烟 bash /home/chunyu/dealerhub/smoke.sh http://192.168.5.7:18050 ``` --- ## ⏭️ 下一阶段可选项 1. **报表元数据化**(自定义报表 / 仪表盘):阶段 3 已规划但未落地 2. **电商平台对接**(抖店 / 拼多多 / 1688):ChannelAdapter 3. **完整财务**(凭证 / 总账 / 资产负债表):深度总账 4. **AI 加持**:智能开单 / AI 报表 / 智能补货 5. **HTTPS**:接入 nginx + Let's Encrypt 6. **CI/CD**:自动部署 需要继续推进哪个?