|
|
109f45f22a
|
feat: 产品/任务搜索支持业务序列号(external_serial)检索
|
2026-09-07 11:08:49 +08:00 |
|
|
|
3019653dfa
|
refactor: 宏观状态统一(待仓库收货/已入库)废弃"在库"; WIP矩阵返回product_name并新增下钻明细
|
2026-09-02 10:38:49 +08:00 |
|
|
|
262e28b9f2
|
fix: 仓储任务节点修复(assignee=None + WAREHOUSE 类型) + 前端防御性渲染
- webhook 生成任务 assignee_id 置 None,不再填中文,避免前端解析报错跳过渲染
- task_type=WAREHOUSE,并同步 isMain 判断(后端+双端前端)使其画在中央主干道
- 前端对扫码入库/出库任务:不请求用户数据,直接显示 📦 + 'MOM 仓储系统'
|
2026-09-01 17:25:22 +08:00 |
|
|
|
73faa1fd93
|
feat: Track 打通已完成/已入库/已出库状态闭环与外部联动
- 完工转交入库同步 status=COMPLETED;MOM 入库/出库回调同步 status
- 新增 mom-outbound webhook(发货出库标记已出库),lookup 返回 material_id
- VALID_OVERALL_STATUS 新增已出库;update_overall_status 同步 status 字段
- WIP 矩阵区分已入库/待仓库收货;虚拟节点正确处理已出库/转入在库人
|
2026-09-01 13:53:24 +08:00 |
|
|
|
7f5bedf87c
|
fix(流转树): 在库设备无在库任务时追加虚拟在库节点
- 设备在库(virtual_warehouse)但无在库任务时,流转树追加虚拟「在库」节点
- 转入人用最后一道主工序负责人兜底(近似),显示在库归属
- 递归检查任务树避免重复追加(在库任务可能是子任务)
|
2026-08-31 17:38:38 +08:00 |
|
|
|
39019f4312
|
fix(流转树): 在库任务无创建日志时兜底显示转入人
- 有 create 日志的在库任务用真实转入人(张欣欣/孔贺等)
- 无日志的历史在库任务,用该产品在库前最近一道主工序的负责人兜底
- 解决『流转树到负责人就结束、不显示谁入库』的问题
|
2026-08-31 17:26:57 +08:00 |
|
|
|
0dea116faa
|
feat(backend): 流转树 created_by 加入中文名映射
- get_product_by_serial 把任务创建人(created_by)纳入 assignee_names 中文名映射
- 前端可显示『谁转入在库』等创建人信息
|
2026-08-31 17:20:41 +08:00 |
|
|
|
b09187ac6e
|
feat(backend): 生产总天数返回自然天+工作日两个口径
- ProductResponse 加 production_days(自然天)/production_days_workdays(工作日)
- get_all_products 计算:自然天自创建至今,工作日用 working_duration_hours 排除周末/节假日
- FlowDevice 加 total_days/total_workdays(设备生产总天数,自最早介入至今)
|
2026-08-28 15:28:56 +08:00 |
|
|
|
bad0941d67
|
fix(时长): 所有时长计算排除非工作日 + 修复两处时区多算8小时
- get_wip_tasks/get_people_workload/get_people_history/product active_duration_hours/analytics 均改用 working_duration_hours
- 修复 get_wip_tasks 与 active_duration_hours 的 naive 时间误标北京时间 bug(DB实存UTC,原多算8小时)
- 每处读取 holidays 表排除配置的放假日期
|
2026-08-28 15:08:10 +08:00 |
|
|
|
90d615cbb0
|
feat(backend): 产品列表返回当前人滞留时长 active_duration_hours
- ProductResponse 增加 active_duration_hours(小时) 字段
- get_all_products 批量计算每个产品活跃任务(WIP/PENDING)最早接手时间到现在的时长
- 复用 get_people_workload 相同的北京时间口径,前端无需额外请求
|
2026-08-28 10:46:10 +08:00 |
|
|
|
e5829c7d06
|
fix(backend): 修复并发任务聚合——当前位置汇总全部负责人、最新动态携带操作人、状态聚合补齐 REJECTED
|
2026-08-13 11:17:10 +08:00 |
|
|
|
abc8999358
|
hotfix: get_product_by_serial补全func导入 — 修复500错误
|
2026-08-13 09:01:34 +08:00 |
|
|
|
d8d42e9613
|
feat: 上游显示真实发送人 — 从task_logs追溯created_by
|
2026-08-12 17:52:35 +08:00 |
|
|
|
e511952ea0
|
feat: 最新动态列支持图片展示 — 纯文字/纯图片/图文混合三种模式
后端: ProductResponse 新增 latest_record_has_images
前端: 📷图标 + 纯图片时显示"图片记录" + Tooltip标注[含图片]
|
2026-08-12 16:01:24 +08:00 |
|
|
|
6016f92dd0
|
hotfix: func→sa_func 解决局部变量遮蔽
|
2026-08-12 15:52:06 +08:00 |
|
|
|
b21df33e0a
|
hotfix: 补充 product_service.py 顶部缺失的 func 导入
|
2026-08-12 15:50:01 +08:00 |
|
|
|
163d9c20bb
|
feat: 任务全景表格新增"最新动态"列
后端:
- ProductResponse 新增 latest_record_time/content 字段
- get_all_products 批量查询活跃任务(WIP/PENDING)的最新 task_records
- 使用窗口函数 ROW_NUMBER() PARTITION BY product_id
前端:
- AdminTasksPage: grid-cols-12→grid-cols-[14]
- 表头+数据行新增"最新动态"列
- Tooltip悬浮显示完整内容, 截断+灰字二级排版
|
2026-08-12 15:43:33 +08:00 |
|
|
|
49cbf22854
|
fix: 修复or_局部导入遮蔽模块级导入导致UnboundLocalError + Drawer改用size
1. product_service.py: 删除函数内两处 from sqlalchemy import or_
Python解析器看到函数内的import就把or_当局部变量, 在赋值前使用就报UnboundLocalError
模块顶部已有 import or_, 函数内无需重复导入
2. AdminDashboard.tsx: Drawer width→size (Antd v6 deprecation)
|
2026-08-12 15:05:39 +08:00 |
|
|
|
cc199081f9
|
perf: CTE任务树加载器 + MOM跨库查询缓存
消除两个核心N+1性能瓶颈:
1. CTE任务树加载器 (task_tree_loader.py)
- PostgreSQL Recursive CTE一次性加载完整任务树
- 无论树深度多大,仅2条SQL(CTE + records selectinload)
- set_committed_value安全注入,避免Session脏数据
- 修复add_task_record双重加载问题
- 移除get_all_tasks中冗余的selectinload(child_tasks)
2. MOM跨库查询缓存 (mom_cache.py)
- 零依赖TTL内存缓存(threading.RLock + time.monotonic)
- 参数化ANY(:user_ids)替代OR拼接LIKE(防注入)
- get_all_products中3次调用共享缓存,2h TTL内零跨库查询
|
2026-08-12 12:03:02 +08:00 |
|
|
|
b97dfaa95d
|
fix(backend): 宏观状态权限校验 — 根除 current_user 空值绕过漏洞
Bug: if current_user: 在 Python 中 None/空dict均为falsy,
一旦 current_user 为空则整个权限块被跳过直接放行。
修复:
1. if not current_user → 直接 raise 401
2. 反转 SUPER_ADMIN 判断: if user_role != 'SUPER_ADMIN' 进入校验
(避免 if/else/pass 空分支带来的逻辑歧义)
3. main_task is not None 显式判断 (替代隐式 truthy)
|
2026-08-11 17:39:30 +08:00 |
|
|
|
88dc7381f6
|
fix(backend): 权限漏洞修复 + 业务逻辑审查修复
1. 宏观状态越权修复 (products.py + product_service.py):
- update_overall_status 增加权限校验:仅 SUPER_ADMIN 或当前操作该产品主线任务的人可修改,否则 403
2. 任务撤回越权修复 (task_service.py + tasks.py):
- recall_task 增加校验:操作人必须等于上游任务负责人(谁发出的谁撤回),否则 403
- 管理员 (SUPER_ADMIN/SUPERVISOR) 直接放行
3. 驳回上游溯源修复 (task_service.py - reject_task):
- 将 TaskLog (action_type=create) 提升为优先溯源方式,解决协助分支转交后驳回找不到正确发起人的 Bug
- 保留 parent_task.assignee_id + task.assignee_id 两级兜底
4. complete_task 父节点继承修复:
- 修复 task_type == 'MAIN' 永不匹配的 Bug(模型无此值)
- 改为 not parent_task_id or task_type in (TRANSFER, RECOVERY)
|
2026-08-11 15:05:30 +08:00 |
|
|
|
2440e9bdaa
|
fix: 修复产品删除 500 — ImportError + FK 自引用约束
- 修正 TaskLog 导入路径:app.models.task → app.models.task_log
- 删除任务前先切断 parent_task_id 自引用外键
- 删除产品前先切断 parent_product_id 自引用外键
- 真正执行 delete(TaskRecord) 和 delete(TaskLog) 替代空 select
|
2026-08-10 17:36:48 +08:00 |
|
|
|
34724e478c
|
fix: SQL语法错误—func.and_()/or_()改为sqlalchemy.and_()/or_()
|
2026-08-10 11:41:10 +08:00 |
|
|
|
e447de6cfa
|
feat: 当前位置100%动态主干化—与宏观状态同源,只跟主分支,静态字段仅兜底
|
2026-08-10 11:32:07 +08:00 |
|
|
|
b43bded0ef
|
feat: 宏观状态动态从主干任务获取+任务树assignee中文姓名映射(后端+前端)
|
2026-08-10 11:25:44 +08:00 |
|
|
|
45b5376537
|
fix: 三致命Bug—macro_status预计算+排除已完工脏读+flush落盘+递归深度限制10
|
2026-08-09 18:23:55 +08:00 |
|
|
|
beea543fbd
|
fix: 创建产品时自动将当前位置设为当前登录用户(谁创建谁持有)
|
2026-08-07 15:42:10 +08:00 |
|
|
|
bc43b5a732
|
feat: 产品管理 — 当前位置显示真实姓名 + 编辑弹窗 + 删除确认
|
2026-08-07 15:38:01 +08:00 |
|
|
|
b71c5a2d07
|
feat: 双Token认证(Access 2h/Refresh 7d) + 通知系统(转交/驳回自动推送)
|
2026-08-07 11:44:04 +08:00 |
|
|
|
9846dd6c8f
|
修复: MissingGreenlet_product访问try/catch + spawn_subtask不再覆盖overall_status
|
2026-08-06 11:16:07 +08:00 |
|
|
|
d9f4e7e66e
|
紧急修复: product_service._task_to_response补remark — 扫码详情页remark=null的根因
|
2026-08-05 17:41:09 +08:00 |
|
|
|
1fed716829
|
feat(services): 核心业务逻辑 — 接收/返工/裂变/记录/标签打印
task_service:
- receive_task() — PENDING→WIP, 记录 received_at
- reject_task() — →REJECTED + 自动返工闭环
- transfer_task() — →COMPLETED + 多路裂变 + virtual_warehouse入库
- add_task_record() — 图文记录追加
- 全链路 selectinload(Task.records)
- 全部 now 改用 get_beijing_time()
product_service:
- create_product() — PG Sequence 自动生成16位HEX
- update_overall_status() — 宏观状态校验+更新
- 扫码返回完整 task_tree (含 records)
- order_no 自由文本→自动创建 ProductionOrder
- update_product() 支持 order_no 编辑
label_service:
- 480×360 工业级排版 (QR+名/规/单+底部通栏码)
- simhei.ttf 34px/28px + stroke_width 描边
- TSPL Socket 发送到打标机
|
2026-08-05 14:00:55 +08:00 |
|
|
|
8028be58c4
|
feat(services): 重写核心业务逻辑 — 接收/驳回返工/裂变转交
task_service 新增 3 个核心业务函数:
- receive_task(): PENDING→WIP, 记录 received_at, 仅 PENDING 状态可接收
- reject_task(): →REJECTED, 记录 reject_reason+completed_at,
防呆闭环: 自动查找父任务负责人, 创建 is_rework=True 的返工任务
- transfer_task(): →COMPLETED, 记录 completed_at,
裂变转交: 遍历 next_assignees 批量创建 PENDING 任务,
多路裂变(>1)时子任务挂载形成树状分支,
virtual_warehouse 入库逻辑更新 Product.current_location_id
- complete_task(): 保留兼容, 同步使用新状态常量 TASK_STATUS_*
product_service 重构:
- get_product_by_serial(): 新增 task_tree 返回完整递归任务树
- _load_task_tree(): 递归加载产品关联的所有任务嵌套关系
|
2026-08-04 17:03:37 +08:00 |
|