# MES 模块结构说明

本文档用于业务评审和联调前核对，描述当前 `MES` 模块已经落地的代码结构、数据对象、公开边界和暂未进入本轮范围的能力。

## 当前模块目标

当前 `MES` 模块的落点是两个基础能力：

- 设备分类管理
- 设备管理
- 生产指派管理

它们共同服务于后续更深入的排产、派工、产能统计，但当前阶段还没有实现复杂的汇总、排程算法和业务编排。

## 目录结构

当前 `mes` app 目录如下：

| 路径 | 说明 |
|------|------|
| `mes/apps.py` | Django app 注册入口 |
| `mes/models.py` | MES 核心模型定义，包含枚举、设备分类、设备、生产指派 |
| `mes/services.py` | 服务层，封装 CRUD、校验、状态流转和商户隔离规则 |
| `mes/tests.py` | service 层测试 |
| `mes/migrations/` | 数据库迁移文件 |

对外 API 入口位于：

| 路径 | 说明 |
|------|------|
| `api_v2/views/mes.py` | MES 对外 API 视图、序列化和请求参数解析 |
| `api_v2/urls.py` | MES API 路由注册 |
| `api_v2/test_mes_api.py` | API 层测试 |
| `docs/api_v2_mes_api.md` | 当前公开 API 文档 |

## 数据对象

### 1. DeviceCategory

用途：设备分类，例如打印机、滚筒机等。

当前字段：

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | bigint | 主键 |
| `merchant` | FK | 所属商户 |
| `name` | string | 分类名称，同商户下唯一 |
| `created_by` | FK | 创建用户 |
| `operator` | FK | 当前操作员工 |
| `created_at` | datetime | 创建时间 |
| `updated_at` | datetime | 更新时间 |

当前规则：

- `operator` 必须属于当前商户。
- `merchant + name` 唯一。

### 2. Device

用途：具体生产设备。

当前字段：

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | bigint | 主键 |
| `merchant` | FK | 所属商户 |
| `category` | FK | 设备分类 |
| `name` | string | 设备名称，同商户下唯一 |
| `peak_capacity` | integer | 峰值产能，必须大于 0 |
| `capacity_unit` | integer enum | 产能单位，当前 `1=米`、`2=码` |
| `extra` | json/null | 扩展参数，后端不解释内容 |
| `created_by` | FK | 创建用户 |
| `operator` | FK | 当前操作员工 |
| `created_at` | datetime | 创建时间 |
| `updated_at` | datetime | 更新时间 |

当前规则：

- `category` 必须属于当前商户。
- `operator` 必须属于当前商户。
- `peak_capacity > 0`。
- 支持按 `extra` 指定 JSON 路径和值做精确筛选。

### 3. ProductionAssignment

用途：把某个业务对象指派到某台设备，并记录指派数量和状态。

当前字段：

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | bigint | 主键 |
| `merchant` | FK | 所属商户 |
| `device` | FK | 被指派设备 |
| `content_type` | FK | 关联业务对象类型 |
| `object_id` | bigint | 关联业务对象 ID |
| `content_object` | GenericForeignKey | 运行时关联对象，不单独出现在 API 请求体中 |
| `assigner` | FK | 指派者 |
| `assignee` | FK/null | 被指派人，可空 |
| `production_quantity` | integer | 生产数量，必须大于 0，单位跟随设备 `capacity_unit` |
| `status` | integer enum | 状态，当前 `1=Draft`、`2=已发布`、`3=已接收`、`4=已取消`、`5=已完工` |
| `extra` | json/null | 扩展参数，后端不解释内容 |
| `created_by` | FK | 创建用户 |
| `operator` | FK | 当前操作员工 |
| `created_at` | datetime | 创建时间 |
| `updated_at` | datetime | 更新时间 |

当前规则：

- `device`、`assigner`、`assignee`、`operator` 必须属于当前商户。
- `content_type + object_id` 指向的对象必须存在。
- 如果目标对象带 `merchant_id`，则必须与当前商户一致。
- `production_quantity > 0`。

## 当前状态机

`ProductionAssignment.status` 当前是简单状态机：

| 状态值 | 显示值 | 含义 |
|------|------|------|
| `1` | `Draft` | 草稿 |
| `2` | `已发布` | 已正式发出指派 |
| `3` | `已接收` | 执行方已接收 |
| `4` | `已取消` | 指派取消 |
| `5` | `已完工` | 指派完成 |

当前允许流转：

- `Draft -> Draft / 已发布 / 已取消`
- `已发布 -> 已发布 / 已接收 / 已取消`
- `已接收 -> 已接收 / 已完工`
- `已取消 -> 已取消`
- `已完工 -> 已完工`

当前明确禁止：

- `已接收 -> 已取消`
- `已完工 -> 已取消`
- 任意终态回退到前置状态

## 服务层职责

`mes/services.py` 当前负责：

- 统一商户隔离校验
- 统一名称、数量、状态值校验
- 设备分类 CRUD
- 设备 CRUD
- 生产指派 CRUD
- 生产指派状态流转校验
- 设备 `extra` JSON 路径筛选

这意味着当前 API 层主要是参数适配和错误转译，核心业务校验已经集中到 service 层。

## 当前公开 API 边界

当前已经公开到 `api_v2` 的接口包括：

- 设备分类：列表、创建、详情、更新、删除
- 设备：列表、创建、详情、更新、删除
- 生产指派：列表、创建、详情、更新、删除

当前 API 文档见：`docs/api_v2_mes_api.md`

## 当前未进入本轮范围的能力

以下能力尚未在本轮实现，业务评审时需要明确它们仍属于后续扩展：

- 设备产能利用率汇总
- 指派数量聚合统计
- 更复杂的排产/排队/冲突检测
- 基于业务对象类型的定制校验规则
- 更细粒度的状态副作用，例如发布后自动通知、接收后自动开工等

## 评审建议

如果你要先去业务部门开会和做实验，建议重点确认这几件事：

- `production_quantity` 的业务口径是否始终跟随设备 `capacity_unit`
- `ProductionAssignment` 的五个状态是否够用
- `assignee` 是否允许为空，以及在哪个环节允许为空
- `extra` 里是否会出现需要前端按路径筛选的高频字段
- `content_type + object_id` 是否符合业务上“一个指派对应一个目标对象”的表达方式