# 2026-01-14 工作日志 ## 已完成 ### 1. 通过生产订单查询销售品 API 创建了独立的 Shipment API 模块,提供出货管理相关接口。 - **接口路径**: `GET /api/v1/shipment/sales-items/by-printing-order//` - **查询参数**: `include_already_has_shipment`(默认 false,不包含已出货的销售品) #### 新建文件 - `api_v1/views/shipment/__init__.py`: 模块入口 - `api_v1/views/shipment/views.py`: API 视图 `SalesItemByPrintingOrderView` - `api_v1/views/shipment/serializers.py`: 序列化器 `SalesItemSerializer` - `api_v1/views/shipment/test_api.py`: API 测试用例(8 个测试场景) - `shipment/services.py`: 业务逻辑层 `get_sales_items_by_printing_order()` - `docs/shipment_api.md`: API 文档 #### 修改文件 - `api_v1/urls.py`: 注册新路由 #### 业务逻辑 1. 根据 PrintingOrder ID 获取所有 PrintingJob 的 ID 2. 查询 SalesItem,过滤 printing_job_id 在这些 job_ids 中 3. 根据参数决定是否过滤已关联出货单的销售品 --- ### 2. Printing 模块添加 merchant 字段 为多租户支持,为 printing 模块的核心模型添加 `merchant` 外键字段: - `PlateOrder.merchant` - 开版订单所属商户 - `PrintingOrder.merchant` - 印染订单所属商户 - `PrintingJob.merchant` - 印染任务所属商户 所有字段设置为可空(`null=True, blank=True`),以兼容现有数据。 **迁移文件**: `printing/migrations/0029_add_merchant_to_models.py` --- ### 3. 确保 API 创建时自动绑定 merchant 修复了创建 API,确保新建记录时自动从当前用户获取 merchant: - `PrintingOrderService.create_printing_order()` - 自动绑定 merchant - `PrintingJobService.create_printing_job()` - 自动绑定 merchant - `PlateOrderViewSet.perform_create()` - 自动绑定 merchant --- ### 4. 数据补录命令 创建了 management command 用于补录历史数据的 merchant_id: ```bash # 预览(不执行) python manage.py backfill_merchant --dry-run # 执行补录 python manage.py backfill_merchant ``` **文件**: `printing/management/commands/backfill_merchant.py` --- ### 5. 创建出货单 API 实现了创建出货单的 API,支持同时关联多个销售品。 - **接口路径**: `POST /api/v1/shipment/shipments/` - **请求参数**: `customer`(客户ID)、`shipment_date`(出货日期)、`remark`(备注)、`sales_items`(销售品ID列表) #### 业务逻辑 1. 验证客户存在 2. 验证销售品存在且未被关联到其他出货单 3. 创建出货单并将销售品关联到该出货单(事务保护) #### 修改文件 - `shipment/services.py`: 添加 `create_shipment()` 函数 - `api_v1/views/shipment/views.py`: 添加 `ShipmentCreateView` - `api_v1/views/shipment/serializers.py`: 添加 `ShipmentSerializer`、`ShipmentCreateSerializer` - `api_v1/views/shipment/test_api.py`: 添加 6 个测试用例 - `api_v1/urls.py`: 注册新路由 - `docs/shipment_api.md`: 更新 API 文档 --- ### 6. 添加销售品自动创建开关 在 `settings.py` 中添加 `AUTO_CREATE_SALESITEM_FROM_PRINT_ORDER` 配置项: - **默认值**: `False`(默认关闭,避免未确认流程就自动落库) - **环境变量**: `AUTO_CREATE_SALESITEM_FROM_PRINT_ORDER` - **作用**: 当设为 `False` 时,`printing/handlers.py` 中的流程完成信号处理器将不再自动创建销售品 #### 修改文件 - `flower/settings.py`: 添加配置项 - `printing/handlers.py`: 检查开关状态,为 False 时提前返回 --- ### 6.1. 强制从 .env 读取 PRINTING_SALES_ITEM_SOURCE_STATE_ID(无默认值) 为避免遗漏配置导致“取错工序参数”,将 `PRINTING_SALES_ITEM_SOURCE_STATE_ID` 改为必须在 `.env` 中显式配置(不提供默认值)。 #### 修改文件 - `flower/settings.py`: `PRINTING_SALES_ITEM_SOURCE_STATE_ID = env.int('PRINTING_SALES_ITEM_SOURCE_STATE_ID')` --- ### 7. Printing 模块客户可见性过滤 实现了基于客户可见性的订单查询过滤功能,确保员工只能看到自己负责的客户的订单。 #### 新增权限 - `printing.view_all_plateorders`: 查看所有开版订单(突破客户可见性限制) - `printing.view_all_printingorders`: 查看所有印染订单(突破客户可见性限制) #### 可见性规则 - 超级用户:无限制 - 有 `view_all_xxx` 权限:可见本商户所有订单 - 普通员工: - 可见自己创建的客户的订单 - 可见被加入 `visible_employees` 的客户的订单 - 所有用户:受 merchant 隔离限制 #### 新建文件 - `api_v1/views/printing/mixins.py`: `CustomerVisibilityFilterMixin` #### 修改文件 - `printing/models.py`: 添加新权限定义 - `api_v1/views/printing/views.py`: 三个 ViewSet 继承 Mixin - `api_v1/views/printing/test_api.py`: 修复测试数据 + 新增 7 个权限过滤测试 #### Migration - `printing/migrations/0030_add_view_all_permissions.py` --- ### 8. Shipment 模型兼容外部遗留系统字段 为出货单与外部系统对接预留字段与模型(暂未接入业务逻辑/API)。 #### Shipment 新增字段/方法 - `status`:状态(待送货 / 已交付 / 已取消),默认「待送货」 - `cancelled_at`:取消时间(可空) - `cancelled_by`:取消人(可空,绑定用户) - `external_id`:外部订单号(可空,长度 120) - `external_finished_products`:关联多个“外部成品表”(一对多,外键在外部成品表侧) - `cancel(operator)`:取消出货单时自动记录取消时间与操作者 #### 新增模型:ExternalFinishedProduct(外部成品表) - 字段:`style_name`、`num_of_rolls`、`created_at`(来自 ModelBase)、`created_by` #### Migration - `shipment/migrations/0004_add_external_finished_product_and_shipment_status.py` - `shipment/migrations/0005_fix_shipment_external_finished_product_relation.py`(修正关系方向:Shipment 1→N ExternalFinishedProduct) #### 测试 - 运行 `api_v1.views.shipment.test_api`:17 个测试通过 --- ### 8.1. Admin 支持(Shipment) 补齐 Shipment 模块在 Django Admin 中的可用性,便于测试/排查数据: - `shipment/admin.py`: 注册 `Shipment`、`SalesItem` 并提供基础展示/筛选字段 --- ### 9. Shipment 创建 API:普通版 & External 版 新增并完善了两个创建出货单接口: #### 普通版(绑定销售品) - **接口**:`POST /api/v1/shipment/shipments/` - **参数**:`sales_items: [销售品ID...]` - **行为**:创建出货单并把销售品关联到该出货单 #### External 版(不绑定销售品 + 外部成品表批量写入) - **接口**:`POST /api/v1/shipment/shipments/external/` - **参数**: - `external_id` 必填 - `external_finished_products`(数组)必填,用于写入 `ExternalFinishedProduct` 并关联到 Shipment - **行为**:创建出货单 + 批量创建外部成品表记录(不关联任何销售品) #### 代码位置 - `shipment/services.py`: 新增 `create_external_shipment()` - `api_v1/views/shipment/views.py`: 新增 `ShipmentExternalCreateView` - `api_v1/views/shipment/serializers.py`: 新增 external 创建序列化器与响应字段扩展 - `api_v1/urls.py`: 注册 external 创建路由 - `api_v1/views/shipment/test_api.py`: 新增 external create 测试 #### merchant 强制归属(非空) - 为 `Shipment` 与 `SalesItem` 增加 `merchant` 外键且不允许为空 - 创建时从 `request.user.employee.merchant` 自动绑定,并校验 customer 同商户 - 普通版在关联销售品时校验销售品同商户,避免跨商户关联(不一致则报错并回滚) - printing 流程完成自动创建 `SalesItem` 时增加 merchant 推导兜底(job → order → operator),避免 merchant 为空导致创建失败 #### Migration - `shipment/migrations/0006_add_merchant_to_shipment_and_salesitem.py` - 先以可空字段落库 → RunPython 补齐 → 再改为 `null=False`(避免 makemigrations 交互式默认值) #### 响应字段补充 - Shipment 响应增加 `merchant_id` / `merchant_name`(便于前端展示/二次校验) #### 文档 - `docs/shipment_api.md`: 补充 external create API 文档 --- ## 待办 --- ## 备注 - API 独立于 printing 模块,避免影响现有功能 - 完整的测试覆盖:正常查询、包含已出货、数据格式、404 错误、空结果、未认证 - printing 和 shipment 模块相关测试通过(`api_v1.views.shipment.test_api` 共 17 个用例)