7.8 KiB
7.8 KiB
样品状态同步问题修复说明
问题描述
删除数据库中的工单数据后,重新生成工单时提示"已有工单",无法创建新工单。
根本原因
与 Redis 无关,问题在于样品表(warehouse_sample)的状态字段与工单表不同步:
- 样品生成工单时,样品状态从
'0'(待测试)更新为'1'(测试中) - 删除工单时,只删除了工单数据,没有重置样品状态
- 再次生成工单时,系统检查到样品状态不是
'0',认为"已有工单",拒绝创建
相关代码
样品状态检查逻辑
文件: warehouse_sample_service.py 第 162-171 行
# 4.2 验证样品状态(只允许待测试状态的样品,除非force=True)
if not request_model.force and sample.status != '0':
failed_samples.append(FailedSampleInfo(
sampleId=sample_id,
sampleSn=sample.sample_sn,
reason='已有工单'
))
failed_count += 1
continue
样品状态更新逻辑
文件: warehouse_sample_service.py 第 237-243 行
# 4.8 如果该样品至少创建了一个工单,更新样品状态为"测试中"
if sample_work_order_count > 0:
# 只有当样品状态为"待测试"时才更新为"测试中"
if sample.status == '0':
sample.status = '1' # 测试中
sample.update_time = datetime.now()
await db.flush()
解决方案
方案 1:重置样品状态(快速修复)✅ 推荐
执行 SQL 脚本重置样品状态:
mysql -u root -p your_database < reset_sample_status.sql
SQL 内容:
-- 重置所有样品状态为"待测试"
UPDATE warehouse_sample
SET status = '0',
update_time = NOW()
WHERE status != '0';
适用场景:
- 开发/测试环境
- 需要快速清理数据重新测试
- 确认所有工单都已删除
方案 2:使用 force 参数(临时方案)
前端在生成工单时传递 force: true 参数:
// 前端代码
const response = await generateWorkOrderFromSamples({
sampleIds: selectedSampleIds,
testFlowId: testFlowId,
workOrderName: workOrderName,
force: true // 强制生成,跳过状态检查
});
适用场景:
- 临时需要重新生成工单
- 不想修改数据库数据
- 明确知道样品没有关联的工单
方案 3:添加级联删除逻辑(长期方案)
修改工单删除逻辑,删除工单时自动重置样品状态。
3.1 修改工单删除 Service
文件: test_work_order_service.py
@classmethod
async def delete_test_work_order_services(cls, query_db: AsyncSession, page_object: DeleteTest_work_orderModel):
"""
删除测试工单信息service
"""
if page_object.ids:
id_list = page_object.ids.split(',')
try:
# 1. 查询要删除的工单,获取关联的test_eut_id
work_order_ids = [int(id) for id in id_list]
work_orders = await Test_work_orderDao.get_work_orders_by_ids(query_db, work_order_ids)
# 2. 收集所有test_eut_id
test_eut_ids = list(set([wo.test_eut_id for wo in work_orders if wo.test_eut_id]))
# 3. 删除工单
for id in id_list:
await Test_work_orderDao.delete_test_work_order_dao(query_db, Test_work_orderModel(id=id))
# 4. 检查每个test_eut是否还有其他工单
from module_admin.system.entity.do.test_eut_do import TestEut
from module_admin.dao.warehouse_sample_dao import WarehouseSampleDao
from sqlalchemy import select, func
for test_eut_id in test_eut_ids:
# 查询该test_eut是否还有其他工单
remaining_count = (await query_db.execute(
select(func.count(TestWorkOrder.id))
.where(TestWorkOrder.test_eut_id == test_eut_id)
)).scalar()
# 如果没有其他工单了,重置对应样品的状态
if remaining_count == 0:
# 通过test_eut的SN查找样品
test_eut = await query_db.get(TestEut, test_eut_id)
if test_eut:
sample = await WarehouseSampleDao.get_sample_by_sn(query_db, test_eut.sn)
if sample:
sample.status = '0' # 重置为待测试
sample.update_time = datetime.now()
await query_db.commit()
return CrudResponseModel(is_success=True, message='删除成功')
except Exception as e:
await query_db.rollback()
raise e
else:
raise ServiceException(message='传入工单ID为空')
3.2 添加 DAO 方法
文件: warehouse_sample_dao.py
@classmethod
async def get_sample_by_sn(cls, db: AsyncSession, sample_sn: str):
"""
根据样品SN获取样品信息
:param db: orm对象
:param sample_sn: 样品SN
:return: 样品对象
"""
result = await db.execute(
select(WarehouseSample)
.where(WarehouseSample.sample_sn == sample_sn)
)
return result.scalars().first()
适用场景:
- 生产环境
- 需要保证数据一致性
- 长期维护的系统
样品状态说明
| 状态值 | 状态名称 | 说明 |
|---|---|---|
| '0' | 待测试 | 样品已入库,未生成工单 |
| '1' | 测试中 | 样品已生成工单,正在测试 |
| '2' | 已完成 | 样品测试完成 |
数据一致性检查
检查样品状态与工单的一致性
-- 查找状态为"测试中"但没有工单的样品
SELECT
s.sample_id,
s.sample_sn,
s.status,
COUNT(wo.id) AS work_order_count
FROM warehouse_sample s
LEFT JOIN test_eut te ON s.sample_sn = te.sn
LEFT JOIN test_work_order wo ON te.id = wo.test_eut_id
WHERE s.status = '1' -- 测试中
GROUP BY s.sample_id, s.sample_sn, s.status
HAVING work_order_count = 0;
修复不一致的数据
-- 重置没有工单的"测试中"样品
UPDATE warehouse_sample s
LEFT JOIN test_eut te ON s.sample_sn = te.sn
LEFT JOIN test_work_order wo ON te.id = wo.test_eut_id
SET s.status = '0',
s.update_time = NOW()
WHERE s.status = '1'
AND wo.id IS NULL;
验证步骤
1. 执行重置脚本
mysql -u root -p your_database < reset_sample_status.sql
2. 检查样品状态
SELECT status, COUNT(*) FROM warehouse_sample GROUP BY status;
预期结果:所有样品状态应该是 '0'(待测试)
3. 重新生成工单
- 进入样品管理页面
- 选择样品
- 点击"生成工单"
- 应该能够成功创建工单
4. 验证样品状态更新
-- 查看刚才生成工单的样品状态
SELECT sample_id, sample_sn, status
FROM warehouse_sample
WHERE sample_id IN (选中的样品ID);
预期结果:状态应该变为 '1'(测试中)
常见问题
Q1: 为什么不是 Redis 缓存问题?
A: 代码中没有使用 Redis 缓存样品状态或工单数据。状态检查直接查询数据库。
Q2: 重启 Redis 有用吗?
A: 无用。问题在于数据库中的样品状态字段,与 Redis 无关。
Q3: 如果只想重置特定样品的状态怎么办?
A: 使用带条件的 UPDATE 语句:
UPDATE warehouse_sample
SET status = '0', update_time = NOW()
WHERE sample_id IN (1, 2, 3); -- 指定样品ID
Q4: 删除工单后为什么不自动重置样品状态?
A: 当前代码没有实现级联更新逻辑。建议采用方案 3 添加级联删除逻辑。
相关文件
warehouse_sample_service.py- 样品服务(状态检查和更新)test_work_order_service.py- 工单服务(删除逻辑)warehouse_sample_dao.py- 样品DAOreset_sample_status.sql- 重置样品状态脚本 ✅
完成时间
2026-01-08 23:45