init
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
---
|
||||
description: REST API 路由与统一 JSON 返回格式
|
||||
globs: backend/routes/**/*.php,backend/app/Http/**/*.php
|
||||
alwaysApply: false
|
||||
---
|
||||
# API 规范
|
||||
|
||||
详见 `docs/07-api.md`。
|
||||
|
||||
## 路由
|
||||
- 统一前缀 `/api/v1/`,资源名复数,路由参数优先业务编码。
|
||||
- 状态动作:`POST /api/v1/{resource}/{code}/{action}`
|
||||
|
||||
```
|
||||
POST /api/v1/inbounds/{inbound_no}/receive
|
||||
POST /api/v1/outbounds/{outbound_no}/allocate
|
||||
```
|
||||
|
||||
- 认证 Sanctum;每个接口都要经过 Policy / Gate 授权,权限码形如 `outbound:allocate`。
|
||||
- 列表接口必须分页并使用统一分页格式。
|
||||
|
||||
## 统一返回
|
||||
所有接口通过统一响应工具(如 `App\Support\ApiResponse`)返回,禁止 Controller 自定义结构。
|
||||
|
||||
```json
|
||||
{ "success": true, "message": "OK", "data": {} }
|
||||
{ "success": false, "message": "操作失败", "errors": {} }
|
||||
```
|
||||
|
||||
- 输出数据统一经 API Resource 转换,不直接返回 Model。
|
||||
- 验证错误、业务异常、授权失败在异常处理器中统一转换为失败格式。
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
description: MySQL 表设计、迁移与索引规范
|
||||
globs: backend/database/**/*.php,backend/app/Models/**/*.php,docs/database/**
|
||||
alwaysApply: false
|
||||
---
|
||||
# 数据库规范
|
||||
|
||||
详见 `docs/09-database.md`。表结构设计存放在 `docs/database/`(索引 `docs/database/README.md`)。
|
||||
|
||||
- **设计先行**:先在 `docs/database/` 中设计并确认表结构,再写迁移;迁移与设计文档必须保持一致,改表时同步更新文档。
|
||||
|
||||
- InnoDB + utf8mb4;所有表有 `created_at`、`updated_at`。
|
||||
- 核心业务表必须有 `tenant_code`;业务编码唯一约束包含租户:`UNIQUE (tenant_code, sku_code)`。
|
||||
- 重要业务表按需加 `status`、`version`(乐观锁)、`deleted_at`;**不要无脑给所有表加软删除**,流水类事实表禁止软删除与更新。
|
||||
- 数量字段使用整数或 `DECIMAL`,禁止 `FLOAT/DOUBLE`;金额使用 `DECIMAL`。
|
||||
- 索引围绕实际查询设计,复合索引通常以 `tenant_code` 为最左列;关注 `warehouse_code`、`customer_code`、`sku_code`、`order_no`、`inbound_no`、`outbound_no`、`location_code`、`status`、`created_at`。
|
||||
- 迁移必须可回滚(实现 `down()`),已上线的迁移不修改,新增迁移变更。
|
||||
- 表名是单数加 `wms_` 前缀(如 `wms_sku`、`wms_stock_log`)。每张表一个 SQL 文件,放在 `docs/database/` 对应领域目录,约定见 `docs/database/00-conventions.md`。
|
||||
|
||||
```php
|
||||
// ✅
|
||||
$table->string('tenant_code', 32);
|
||||
$table->string('sku_code', 64);
|
||||
$table->unique(['tenant_code', 'sku_code']);
|
||||
$table->index(['tenant_code', 'status', 'created_at']);
|
||||
```
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
description: 分阶段开发流程、修改前后检查清单与禁止事项
|
||||
alwaysApply: true
|
||||
---
|
||||
# 开发工作方式
|
||||
|
||||
像资深项目开发人员一样工作,而不是代码生成器。详见 `docs/15-development-workflow.md`、`docs/16-roadmap.md`。
|
||||
|
||||
## 分阶段
|
||||
- 严格按 Phase 1~17 顺序推进(`docs/16-roadmap.md`),不要一次生成整个项目或几百个文件。
|
||||
- 每个 Phase 开始前先说明:目标、涉及模块、数据库变化、API 变化、前端变化、测试方案、风险;确认后再实施。
|
||||
- 阶段完成后:检查代码 → 数据库 → 运行测试 → API → 前端 → 修复问题,再进入下一阶段。
|
||||
|
||||
## 修改前
|
||||
理解目录 → 搜索已有实现(不重复造)→ 检查数据库结构、相关 API、前端调用 → 再修改。
|
||||
|
||||
## 修改后
|
||||
检查类型、语法、引用、迁移、API、权限、**租户隔离**,并运行相关测试。
|
||||
|
||||
## 禁止
|
||||
- 跳过架构设计;Controller 堆业务;一个 Model 承担所有业务
|
||||
- 忽略 `tenant_code`;直接改库存不留流水;不考虑并发库存
|
||||
- Python 直接修改核心 WMS 数据;平台逻辑写死进核心订单模型
|
||||
- 过早微服务化;没有测试就继续堆功能;随意增加第三方依赖
|
||||
- 重复实现 Element Plus / Admin 框架已提供的能力
|
||||
- 魔法字符串、硬编码、重复 SQL、跨模块强耦合
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
description: Docker 开发环境规范
|
||||
globs: docker-compose*.yml,docker/**,**/Dockerfile
|
||||
alwaysApply: false
|
||||
---
|
||||
# Docker 开发环境
|
||||
|
||||
详见 `docs/13-docker.md`。
|
||||
|
||||
- 根目录**一个** `docker-compose.yml`,不为小模块建立独立 Compose。
|
||||
- 服务:php-fpm(PHP 8.4)、nginx、mysql(8)、redis(7)、node(前端开发)、py-service(FastAPI,构建上下文 `py-service/`)。
|
||||
- Queue Worker、Scheduler 为独立服务,复用 PHP 镜像。
|
||||
- 镜像定义放 `docker/{service}/`;敏感配置经 `.env` 注入,不写入镜像与 Git。
|
||||
- 数据卷持久化 MySQL / Redis;端口、密码可通过 `.env` 配置。
|
||||
- 第一阶段不引入 Kubernetes,生产方案在 Phase 17 设计。
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
description: Vue 3 + TypeScript + Element Plus 前端规范(pure-admin-thin)
|
||||
globs: frontend/**/*.vue,frontend/**/*.ts,frontend/**/*.tsx
|
||||
alwaysApply: false
|
||||
---
|
||||
# 前端规范
|
||||
|
||||
详见 `docs/10-frontend.md`。
|
||||
|
||||
## 框架
|
||||
- Admin 基于 pure-admin-thin(i18n 分支),复用其 Layout / Router / 权限 / 标签页 / i18n,不重复实现。
|
||||
- UI 只用 Element Plus,不引入 Naive UI 等第二套组件库;不重复实现 Element Plus 已有组件。
|
||||
- 新增依赖前先确认框架与现有依赖无法满足。
|
||||
|
||||
## 结构
|
||||
- 页面按业务领域放 `src/views/{domain}/`(warehouse、inventory、inbound、outbound 等)。
|
||||
- 接口调用统一放 `src/api/{domain}.ts`,通过框架封装的 HTTP 实例,页面内不直接写 axios。
|
||||
- 类型放 `src/types/`,状态 / 枚举常量放 `src/constants/`,禁止魔法字符串。
|
||||
|
||||
## 编码
|
||||
- `<script setup lang="ts">` + Composition API;Props、Emits、接口响应都要声明类型,避免 `any`。
|
||||
- 列表页统一:查询区 → Toolbar → ElTable → ElPagination;表单用 ElForm + rules,弹窗用 ElDialog / ElDrawer。
|
||||
- 文案走 i18n,不硬编码中文。
|
||||
|
||||
## 权限
|
||||
- 按钮 / 菜单权限使用权限码 `模块:动作`(如 `inventory:adjust`、`outbound:ship`),通过框架的权限指令 / 组件控制。
|
||||
- 前端权限只控制展示,最终以后端授权为准。
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
description: 库存模型、库存流水与并发安全规则(任何涉及库存数量变化的代码)
|
||||
globs: backend/app/**/Inventory/**,backend/app/**/Inbound/**,backend/app/**/Outbound/**,backend/app/**/Picking/**,backend/app/**/Return/**
|
||||
alwaysApply: false
|
||||
---
|
||||
# 库存规则
|
||||
|
||||
详见 `docs/05-inventory.md`。库存是整个 WMS 的核心。
|
||||
|
||||
## 模型
|
||||
- 维度:仓库 → 库区 → 库位 → SKU → 批次 → 库存状态,不要简化为 `sku + warehouse + quantity`。
|
||||
- 数量:`available_qty`、`reserved_qty`、`picked_qty`、`hold_qty`、`damaged_qty`、`in_transit_qty`。
|
||||
|
||||
## 流水
|
||||
- 任何库存数量变化,必须在**同一事务**内写入 `wms_stock_log`(变化量、变化前后、业务单据类型与单号、操作人)。
|
||||
- 库存变更只能通过库存领域服务 / Action 完成,业务模块不得直接 update 库存表。
|
||||
- 流水只追加,不修改、不删除。
|
||||
|
||||
## 并发
|
||||
禁止 "先 SELECT → PHP 计算 → UPDATE"。使用事务 + 原子条件更新 / 行锁 / 乐观锁,必要时 Redis 锁。
|
||||
|
||||
```php
|
||||
// ❌ 并发下会超卖
|
||||
$inv = Inventory::find($id);
|
||||
if ($inv->available_qty >= $qty) { $inv->available_qty -= $qty; $inv->save(); }
|
||||
|
||||
// ✅ 原子条件更新,受影响行数为 0 即库存不足
|
||||
$affected = Inventory::whereKey($id)
|
||||
->where('available_qty', '>=', $qty)
|
||||
->update([
|
||||
'available_qty' => DB::raw('available_qty - '.(int) $qty),
|
||||
'reserved_qty' => DB::raw('reserved_qty + '.(int) $qty),
|
||||
]);
|
||||
if ($affected === 0) { throw new InsufficientStockException(); }
|
||||
```
|
||||
|
||||
- 多行扣减按固定顺序(如库存主键升序)加锁,避免死锁。
|
||||
- 必须有并发测试:库存 10,两个请求同时扣 8,只能成功一个,且不会出现负库存。
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
description: Laravel 后端分层、目录结构与编码规范
|
||||
globs: backend/**/*.php
|
||||
alwaysApply: false
|
||||
---
|
||||
# Laravel 后端规范
|
||||
|
||||
详见 `docs/06-backend-laravel.md`。
|
||||
|
||||
## 分层
|
||||
Controller → FormRequest → Application Action/Service → Domain → Model → DB
|
||||
|
||||
- Controller 只做:接收请求、调用 FormRequest 验证、调用 Action/Service、返回 API Resource。
|
||||
- 复杂业务放 `app/Application/{Module}/Actions`,一个 Action 一个用例(如 `AllocateOutboundAction`)。
|
||||
- 业务规则、状态机、Enum、值对象放 `app/Domain/{Module}`,不依赖 Http 与第三方平台。
|
||||
- 第三方平台 / 物流商实现放 `app/Infrastructure/`;租户上下文、统一响应等放 `app/Support/`。
|
||||
- 事务边界在 Application 层;跨模块协作走 Application Service 或 Events。
|
||||
|
||||
```php
|
||||
// ❌ Controller 中直接写业务与查询
|
||||
public function ship(string $outboundNo) {
|
||||
$o = Outbound::where('outbound_no', $outboundNo)->first();
|
||||
if ($o->status == 'packed') { $o->status = 'shipped'; $o->save(); }
|
||||
}
|
||||
|
||||
// ✅
|
||||
public function ship(ShipOutboundRequest $request, string $outboundNo, ShipOrderAction $action) {
|
||||
return ApiResponse::success(new OutboundResource($action->execute($outboundNo, $request->toDto())));
|
||||
}
|
||||
```
|
||||
|
||||
## 编码
|
||||
- `declare(strict_types=1);`,参数与返回值写明类型;DTO 在层间传递,不传裸数组。
|
||||
- 状态、类型一律用 PHP Enum,非法状态转换抛业务异常。
|
||||
- 授权用 Policies / Gates;认证用 Sanctum。
|
||||
- 避免超大 Controller / Service;不重复 SQL,查询复用 Scope。
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
description: WMS SaaS 项目核心架构约束与文档索引
|
||||
alwaysApply: true
|
||||
---
|
||||
# 项目核心约束
|
||||
|
||||
完整规范见 `docs/`(索引 `docs/README.md`)。涉及某领域的改动前,先阅读对应文档。
|
||||
|
||||
## 仓库结构(monorepo)
|
||||
- `backend/`:Laravel 13 + PHP 8.4,唯一的核心业务系统
|
||||
- `frontend/`:基于 pure-admin-thin(i18n 分支),Vue 3 + TS + Vite + Element Plus
|
||||
- `py-service/`:Python FastAPI,独立 AI / 数据分析服务
|
||||
- `docs/`:设计文档;`docs/database/` 存放数据库表结构设计
|
||||
- 根目录一个 `docker-compose.yml`
|
||||
|
||||
## 不可违背的架构红线
|
||||
1. **多租户**:单库 + `tenant_code`,通过 TenantContext 自动隔离;严禁跨租户读写。→ `docs/03-multi-tenancy.md`
|
||||
2. **库存**:余额是结果,流水(`wms_stock_log`)是事实;任何库存变化必须同事务写流水,且并发安全。→ `docs/05-inventory.md`
|
||||
3. **Laravel 是唯一核心业务系统**:Python 只做分析,只通过 `/internal/v1/` API 交互,不直接写核心库。→ `docs/11-py-service.md`
|
||||
4. **平台解耦**:订单为统一模型,第三方平台走 Connector/Adapter,核心表不写死平台逻辑。→ `docs/04-domain-model.md`
|
||||
5. **状态机**:状态用 Enum + 集中定义的合法转换,禁止散落的 `if ($status == ...)`。
|
||||
6. **业务编码优先**:业务关联优先使用 `sku_code`、`outbound_no` 等,自增 ID 仅作内部主键。
|
||||
7. **MySQL 是事实数据源**,Redis 只做 Cache / Queue / Lock / Rate Limit。
|
||||
8. **不过度设计**:第一阶段不引入 K8s、Kafka、ES、MongoDB、ClickHouse、微服务。
|
||||
|
||||
## 架构问题处理
|
||||
需求存在架构问题时不要直接照做,先说明:问题 → 原因 → 推荐方案 → 替代方案 → 最终建议。
|
||||
存在多个影响全局的合理方案时,先说明区别,由用户决定。
|
||||
|
||||
整个项目遵循:**简单、清晰、可维护、可扩展、业务优先。**
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
description: Python FastAPI AI / 数据分析服务边界与规范
|
||||
globs: py-service/**
|
||||
alwaysApply: false
|
||||
---
|
||||
# Python Service(py-service)
|
||||
|
||||
详见 `docs/11-py-service.md`。
|
||||
|
||||
## 边界(红线)
|
||||
- 只负责:AI 分析、库存分析、销量 / 缺货预测、补货建议、异常检测、AI 助手、机器学习。
|
||||
- **不实现**用户、租户、SKU、仓库、库存、入库、出库等核心业务逻辑。
|
||||
- **不直接连接或写入** Laravel 核心业务数据库;数据由 Laravel 推送,或通过 Laravel 只读接口获取。
|
||||
- 分析结果返回给 Laravel,由 Laravel 决定是否落库或转化为业务动作。
|
||||
|
||||
## 接口
|
||||
- 前缀 `/internal/v1/`,如 `POST /internal/v1/inventory/forecast`。
|
||||
- 内部鉴权(Token / 签名),不对公网暴露。
|
||||
- 请求必须带 `tenant_code`,缓存与结果按租户隔离。
|
||||
|
||||
## 结构与编码
|
||||
```
|
||||
py-service/app/
|
||||
├── main.py api/ services/ schemas/ models/
|
||||
├── analysis/ ai/ tasks/ core/
|
||||
```
|
||||
- 路由在 `api/`,业务在 `services/`,请求响应模型用 Pydantic 定义在 `schemas/`。
|
||||
- 全部函数写类型注解;配置用 pydantic-settings 从环境变量读取,密钥不入库不入 Git。
|
||||
- 重型依赖(PyTorch 等)按需引入,不提前加入。
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: Laravel Queue Job 与 Scheduler 规范
|
||||
globs: backend/app/Jobs/**,backend/app/Console/**,backend/app/Listeners/**,backend/routes/console.php
|
||||
alwaysApply: false
|
||||
---
|
||||
# Queue / Scheduler
|
||||
|
||||
详见 `docs/08-queue-scheduler.md`。
|
||||
|
||||
## 必须入队的任务
|
||||
第三方订单 / 库存 / 物流 / Tracking 同步、批量导入导出、面单生成、大量库存计算、报表生成、AI 分析、邮件通知、Webhook 处理。
|
||||
**用户 HTTP 请求不得同步等待第三方 API。**
|
||||
|
||||
## Job 要求
|
||||
- 构造参数携带 `tenant_code`,`handle()` 开始时恢复 TenantContext。
|
||||
- 幂等:重复执行不重复建单、不重复扣库存(用业务唯一键或幂等键判断)。
|
||||
- 显式设置 `$tries`、`$backoff`、`$timeout`,失败记录日志(`failed()`)。
|
||||
- 传递业务编码 / 主键,不序列化大对象。
|
||||
|
||||
## Scheduler 要求
|
||||
- 任务可配置(开关、频率在配置或租户设置中)。
|
||||
- 使用 `withoutOverlapping()` / `onOneServer()` 防重复执行。
|
||||
- 设置超时、失败重试与日志;按租户分发 Job,保证租户隔离。
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
alwaysApply: true
|
||||
---
|
||||
# 身份设定
|
||||
你现在是一名资深 SaaS / WMS 系统架构师、Laravel 后端工程师、Vue 3 前端工程师,同时具备仓储物流、ERP、3PL、跨境电商仓储业务经验。
|
||||
|
||||
我要从零开发一个商业化、多租户 SaaS WMS(Warehouse Management System)。
|
||||
|
||||
请不要把它当成简单的 CRUD 后台,而要按照一个未来可以长期商业化、支持多个租户、多个仓库、3PL/海外仓、电商订单接入的正式 SaaS 产品进行设计和开发。
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
description: 安全、审计日志与密钥管理规则;处理认证、权限、上传、Webhook、日志、第三方凭证时使用
|
||||
globs: backend/app/**/*.php,backend/config/**/*.php,backend/routes/**/*.php
|
||||
alwaysApply: false
|
||||
---
|
||||
# 安全与审计
|
||||
|
||||
详见 `docs/12-security-audit.md`。
|
||||
|
||||
## 审计
|
||||
- 库存、订单、入库、出库状态变更及用户权限变更,必须记录:操作人、时间、动作、修改前、修改后、来源 IP、请求 ID。
|
||||
- 记录登录日志、操作日志、API 日志;请求 ID 贯穿 HTTP → Job → 外部调用。
|
||||
|
||||
## 安全
|
||||
- 查询只用 Eloquent / Query Builder 参数绑定;禁止拼接用户输入到 `DB::raw`。
|
||||
- 所有接口:Sanctum 认证 + Policy 授权 + 租户隔离 + 必要的 Rate Limit。
|
||||
- 文件上传校验类型、大小、扩展名,存储于非公开目录,文件名重新生成。
|
||||
- 第三方 Webhook 必须校验签名与时间戳,防重放。
|
||||
|
||||
## 密钥
|
||||
- Token / Secret **禁止写入 Git**:使用 `.env`,`.env.example` 只放占位。
|
||||
- 租户级第三方凭证使用 Laravel 加密(`encrypted` cast)存储。
|
||||
- 日志脱敏:不输出密码、Token、完整手机号 / 地址等敏感信息。
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
description: 多租户 tenant_code 隔离规则(后端模型、查询、任务、缓存)
|
||||
globs: backend/app/**/*.php,backend/database/**/*.php,backend/routes/**/*.php
|
||||
alwaysApply: false
|
||||
---
|
||||
# 租户隔离
|
||||
|
||||
详见 `docs/03-multi-tenancy.md`。**严禁租户 A 查询或修改租户 B 的数据。**
|
||||
|
||||
- 方案:单数据库 + `tenant_code`;所有核心业务表必须有 `tenant_code`。
|
||||
- 通过 TenantContext + 全局 Scope / Trait 自动过滤查询、自动填充 `tenant_code`,不要到处手写 where。
|
||||
|
||||
```php
|
||||
// ❌ 手工拼接,容易遗漏
|
||||
Sku::where('tenant_code', $request->user()->tenant_code)->get();
|
||||
|
||||
// ✅ 模型使用租户 Trait,查询自动限定当前租户
|
||||
Sku::query()->get();
|
||||
```
|
||||
|
||||
- 绕过租户 Scope(`withoutGlobalScope`)只允许出现在平台级管理功能中,并需注释说明原因。
|
||||
- 根据业务编码查找数据时,也必须受租户限制(编码只在租户内唯一)。
|
||||
- Queue Job 必须携带 `tenant_code`,执行时恢复 TenantContext。
|
||||
- Scheduler / Console Command 按租户遍历执行,不能一次性处理全部租户数据而不区分。
|
||||
- Webhook 根据店铺 / 应用凭证解析租户后再处理。
|
||||
- 缓存 Key、锁 Key 必须带 `tenant_code` 前缀。
|
||||
- 新增接口需有租户隔离测试。
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
description: 测试要求(后端 Pest/PHPUnit、Python pytest)
|
||||
globs: backend/tests/**,py-service/tests/**
|
||||
alwaysApply: false
|
||||
---
|
||||
# 测试要求
|
||||
|
||||
详见 `docs/14-testing.md`。核心业务没有测试不继续堆功能。
|
||||
|
||||
## 必测
|
||||
Tenant Isolation、RBAC、Inventory、Concurrent Inventory、Inbound、Outbound、Allocation、Picking、Stocktake、Order Status、Queue、API Authorization。
|
||||
|
||||
## 关键用例
|
||||
- **库存并发**:库存 10,两个请求同时扣 8 → 只能成功一个,不出现 `available_qty = -6`。并发测试需使用真实 MySQL(不用 SQLite),多进程 / 多连接触发。
|
||||
- **租户隔离**:租户 A 通过列表、详情、业务编码、批量操作都无法访问租户 B 数据。
|
||||
- **状态机**:合法转换成功并记录日志;非法转换(如 `draft → shipped`)被拒绝。
|
||||
- **库存流水**:每次余额变化都有流水,流水累计与余额一致。
|
||||
- **授权**:无权限用户调用接口返回失败格式与正确状态码。
|
||||
|
||||
## 约定
|
||||
- Feature 测试覆盖 API(含返回格式),Unit 测试覆盖 Domain 规则与状态机。
|
||||
- 使用 Factory 构造数据,Factory 默认带 `tenant_code`。
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
description: WMS 领域规则:业务编码、状态机、统一订单模型、第三方平台 Connector
|
||||
globs: backend/app/Domain/**,backend/app/Application/**,backend/app/Infrastructure/**,backend/app/Models/**
|
||||
alwaysApply: false
|
||||
---
|
||||
# WMS 领域规则
|
||||
|
||||
详见 `docs/04-domain-model.md`。
|
||||
|
||||
## 业务编码
|
||||
- 业务关联优先使用 `tenant_code`、`warehouse_code`、`location_code`、`customer_code`、`sku_code`、`order_no`、`inbound_no`、`outbound_no`、`picking_no`、`shipment_no`、`package_no`。
|
||||
- 单号生成集中在一个编号服务中(租户内唯一、并发安全),不要各模块各自拼接。
|
||||
|
||||
## 状态机
|
||||
- 状态定义为 Enum,合法转换集中声明,非法转换抛异常;状态变更写日志。
|
||||
- 出库:`draft → allocated → picking → picked → packing → packed → shipped → completed`
|
||||
|
||||
```php
|
||||
// ❌
|
||||
if ($outbound->status == 'packed') { $outbound->status = 'shipped'; }
|
||||
|
||||
// ✅
|
||||
$outbound->transitionTo(OutboundStatus::Shipped); // 内部校验 canTransitionTo,失败抛 InvalidStatusTransition
|
||||
```
|
||||
|
||||
## 统一订单模型
|
||||
- `order` / `order_item` / `order_source` / `order_channel` / `order_external_no` / `order_status`。
|
||||
- 核心订单表、Domain、Application 中**不得出现** Amazon / Shopify / TikTok 等平台特有字段与分支判断。
|
||||
|
||||
## 第三方平台
|
||||
- 实现 `MarketplaceConnector` 接口,放 `app/Infrastructure/Platforms/{Platform}/`。
|
||||
- Connector 负责平台数据 ↔ 统一模型(订单、SKU、库存、物流、状态)的映射。
|
||||
- 新增平台只新增 Connector 与配置,不修改核心 WMS 代码。
|
||||
- 平台调用走 Queue,不在用户 HTTP 请求中同步等待。
|
||||
Reference in New Issue
Block a user