From 02a1b77e19b46ef40dfa93773b922893751e1725 Mon Sep 17 00:00:00 2001 From: colaftc Date: Mon, 17 Nov 2025 10:10:32 +0800 Subject: [PATCH] patch: patch testing (api & services) --- api_v1/views/printing/views.py | 178 +++++++++++++++++++- printing/models.py | 50 ++++-- printing/test_plate_order.py | 2 +- stateflow/services.py | 51 ++++-- stateflow/test_api.py | 32 +--- stateflow/tests/test_business_object_api.py | 65 ++++++- stateflow/tests/test_parameters.py | 8 +- stateflow/tests/test_services.py | 22 +-- stateflow/tests/test_step_back.py | 30 ++-- test_output.log | 1 + 10 files changed, 337 insertions(+), 102 deletions(-) create mode 100644 test_output.log diff --git a/api_v1/views/printing/views.py b/api_v1/views/printing/views.py index 6d77070..1d05149 100644 --- a/api_v1/views/printing/views.py +++ b/api_v1/views/printing/views.py @@ -257,12 +257,15 @@ class PrintingJobViewSet(viewsets.ModelViewSet): create: 创建款式明细 update: 更新款式明细 partial_update: 部分更新款式明细 + advance_to_next_state: 推进到下一个状态 + step_back_one_state: 回退一步 completed_states: 查询已完成的流程列表 timeline: 获取流程时间线 - 注意:状态流转功能已迁移至 stateflow 模块的业务对象接口 - - 推进到下一步: POST /api/v1/stateflow/business-objects/{business_object_id}/advance/ - - 回退一步: POST /api/v1/stateflow/business-objects/{business_object_id}/step_back/ + 注意:状态流转接口是对 stateflow 模块的便捷包装 + - 前端只需提供 printing_job 的 ID + - 系统会自动查找关联的 business_object 并进行状态流转 + - 也可以直接使用 stateflow 的原始接口(需要 business_object_id) 查询参数: - printing_order: 印染订单ID @@ -308,6 +311,86 @@ class PrintingJobViewSet(viewsets.ModelViewSet): status=status.HTTP_405_METHOD_NOT_ALLOWED ) + @action(detail=True, methods=['post'], url_path='advance-to-next-state') + def advance_to_next_state(self, request, pk=None): + """ + 推进到下一个状态 + + 将印染任务推进到下一个流程状态 + + 注意:这是对 stateflow.BusinessObject.advance 接口的便捷包装, + 自动通过 printing_job 查找关联的 business_object 并调用状态流转服务。 + 前端只需提供 printing_job 的 ID,无需关心 business_object_id。 + """ + job = self.get_object() + + if not job.business_object: + return Response( + {'detail': '该任务没有关联的流程实例'}, + status=status.HTTP_400_BAD_REQUEST + ) + + # 调用 stateflow 统一服务进行状态流转 + from stateflow import services as stateflow_services + success, message, state_log = stateflow_services.advance_to_next_state( + job.business_object, request.user + ) + + if not success: + return Response( + {'detail': message}, + status=status.HTTP_400_BAD_REQUEST + ) + + # 重新获取 job 以刷新状态 + job.refresh_from_db() + serializer = PrintingJobDetailSerializer(job) + + return Response({ + 'detail': message, + 'data': serializer.data + }) + + @action(detail=True, methods=['post'], url_path='step-back-one-state') + def step_back_one_state(self, request, pk=None): + """ + 回退一步 + + 将印染任务回退到上一个流程状态 + + 注意:这是对 stateflow.BusinessObject.step_back 接口的便捷包装, + 自动通过 printing_job 查找关联的 business_object 并调用状态流转服务。 + 前端只需提供 printing_job 的 ID,无需关心 business_object_id。 + """ + job = self.get_object() + + if not job.business_object: + return Response( + {'detail': '该任务没有关联的流程实例'}, + status=status.HTTP_400_BAD_REQUEST + ) + + # 调用 stateflow 统一服务进行状态回退 + from stateflow import services as stateflow_services + success, message = stateflow_services.step_back_one_state( + job.business_object, request.user + ) + + if not success: + return Response( + {'detail': message}, + status=status.HTTP_400_BAD_REQUEST + ) + + # 重新获取 job 以刷新状态 + job.refresh_from_db() + serializer = PrintingJobDetailSerializer(job) + + return Response({ + 'detail': message, + 'data': serializer.data + }) + @action(detail=True, methods=['get'], url_path='completed-states') def completed_states(self, request, pk=None): """ @@ -452,12 +535,15 @@ class PlateOrderViewSet(viewsets.ModelViewSet): partial_update: 部分更新开版订单 invalidate: 作废开版订单 activate: 恢复开版订单 + advance_to_next_state: 推进到下一个状态(便捷包装) + step_back_one_state: 回退一步(便捷包装) completed_states: 查询已完成的流程列表 timeline: 获取流程时间线 - 注意:状态流转功能已迁移至 stateflow 模块的业务对象接口 - - 推进到下一步: POST /api/v1/stateflow/business-objects/{business_object_id}/advance/ - - 回退一步: POST /api/v1/stateflow/business-objects/{business_object_id}/step_back/ + 注意:状态流转接口是对 stateflow 模块的便捷包装 + - 前端只需提供 plate_order 的 ID + - 系统会自动查找关联的 business_object 并进行状态流转 + - 也可以直接使用 stateflow 的原始接口(需要 business_object_id) 查询参数: - customer: 客户ID @@ -587,6 +673,86 @@ class PlateOrderViewSet(viewsets.ModelViewSet): 'data': serializer.data }) + @action(detail=True, methods=['post'], url_path='advance-to-next-state') + def advance_to_next_state(self, request, pk=None): + """ + 推进到下一个状态 + + 将开版订单推进到下一个流程状态 + + 注意:这是对 stateflow.BusinessObject.advance 接口的便捷包装, + 自动通过 plate_order 查找关联的 business_object 并调用状态流转服务。 + """ + plate_order = self.get_object() + + if not plate_order.business_object: + return Response( + {'detail': '该开版订单没有关联的流程实例'}, + status=status.HTTP_400_BAD_REQUEST + ) + + # 调用 stateflow 统一服务进行状态流转 + from stateflow import services as stateflow_services + success, message, state_log = stateflow_services.advance_to_next_state( + plate_order.business_object, request.user + ) + + if not success: + return Response( + {'detail': message}, + status=status.HTTP_400_BAD_REQUEST + ) + + # 重新获取 plate_order 以刷新状态 + plate_order.refresh_from_db() + from .serializers import PlateOrderDetailSerializer + serializer = PlateOrderDetailSerializer(plate_order, context={'request': request}) + + return Response({ + 'detail': message, + 'data': serializer.data + }) + + @action(detail=True, methods=['post'], url_path='step-back-one-state') + def step_back_one_state(self, request, pk=None): + """ + 回退一步 + + 将开版订单回退到上一个流程状态 + + 注意:这是对 stateflow.BusinessObject.step_back 接口的便捷包装, + 自动通过 plate_order 查找关联的 business_object 并调用状态流转服务。 + """ + plate_order = self.get_object() + + if not plate_order.business_object: + return Response( + {'detail': '该开版订单没有关联的流程实例'}, + status=status.HTTP_400_BAD_REQUEST + ) + + # 调用 stateflow 统一服务进行状态回退 + from stateflow import services as stateflow_services + success, message = stateflow_services.step_back_one_state( + plate_order.business_object, request.user + ) + + if not success: + return Response( + {'detail': message}, + status=status.HTTP_400_BAD_REQUEST + ) + + # 重新获取 plate_order 以刷新状态 + plate_order.refresh_from_db() + from .serializers import PlateOrderDetailSerializer + serializer = PlateOrderDetailSerializer(plate_order, context={'request': request}) + + return Response({ + 'detail': message, + 'data': serializer.data + }) + @action(detail=True, methods=['get'], url_path='completed-states') def completed_states(self, request, pk=None): """ diff --git a/printing/models.py b/printing/models.py index db638f3..0124c72 100644 --- a/printing/models.py +++ b/printing/models.py @@ -134,26 +134,33 @@ class PlateOrder(ModelBase): @property def status(self) -> str: - """返回当前状态名称""" + """ + 返回当前状态名称(下一个待执行的状态名称) + + 规则: + - current_state 为 None:返回"已完成"(没有待执行的节点) + - current_state 不为 None + 进度 0%:返回"未开始" + - current_state 不为 None + 进度 > 0%:返回 current_state.name(正在进行) + """ if not self.business_object: return '未开始' current_state = self.business_object.get_current_state() - # current_state 为 None 有两种情况:未开始或已完成 if current_state is None: - # 检查是否有完成记录来区分 - has_completed_records = self.business_object.state_logs.filter(is_cancelled=False).exists() - if has_completed_records: - return '已完成' - else: - return '未开始' + # 没有待执行的节点,已完成 + return '已完成' + + # 有待执行的节点,配合进度判断是"未开始"还是"进行中" + progress = self.business_object.get_progress_percentage() + if progress == 0: + return '未开始' return current_state.name @property def status_id(self): - """返回当前状态ID""" + """返回当前状态ID(下一个待执行的状态ID)""" if not self.business_object: return None current_state = self.business_object.get_current_state() @@ -291,26 +298,33 @@ class PrintingJob(ModelBase): @property def status(self) -> str: - """返回当前状态名称""" + """ + 返回当前状态名称(下一个待执行的状态名称) + + 规则: + - current_state 为 None:返回"已完成"(没有待执行的节点) + - current_state 不为 None + 进度 0%:返回"未开始" + - current_state 不为 None + 进度 > 0%:返回 current_state.name(正在进行) + """ if not self.business_object: return '未开始' current_state = self.business_object.get_current_state() - # current_state 为 None 有两种情况:未开始或已完成 if current_state is None: - # 检查是否有完成记录来区分 - has_completed_records = self.business_object.state_logs.filter(is_cancelled=False).exists() - if has_completed_records: - return '已完成' - else: - return '未开始' + # 没有待执行的节点,已完成 + return '已完成' + + # 有待执行的节点,配合进度判断是"未开始"还是"进行中" + progress = self.business_object.get_progress_percentage() + if progress == 0: + return '未开始' return current_state.name @property def status_id(self): - """返回当前状态ID""" + """返回当前状态ID(下一个待执行的状态ID)""" if not self.business_object: return None current_state = self.business_object.get_current_state() diff --git a/printing/test_plate_order.py b/printing/test_plate_order.py index a7c4e6b..2aad6bc 100644 --- a/printing/test_plate_order.py +++ b/printing/test_plate_order.py @@ -174,7 +174,7 @@ class PlateOrderModelTestCase(TestCase): # 刷新并检查状态 plate_order.refresh_from_db() - self.assertEqual(plate_order.status, state1.name) # current_state 是最后完成的状态(state1) + self.assertEqual(plate_order.status, state2.name) # current_state 是下一个待执行的状态(state2) self.assertFalse(plate_order.is_completed) self.assertTrue(plate_order.has_started) self.assertGreater(plate_order.progress_percentage, 0) diff --git a/stateflow/services.py b/stateflow/services.py index 1163b4f..94f8d30 100644 --- a/stateflow/services.py +++ b/stateflow/services.py @@ -11,27 +11,24 @@ User = get_user_model() def get_business_object_current_state(business_object: 'models.BusinessObject') -> Optional['models.State']: """ - 获取业务对象的当前状态(最后完成的状态) + 获取业务对象的当前状态(下一个待执行的节点) 规则: - 1. 如果没有任何完成记录(或所有记录都被撤销),返回 None(未开始) - 2. 如果有完成记录,返回最后完成的状态(进行中或已完成) + - 返回下一个待执行的节点(第一个未完成的节点) + - 如果所有节点都已完成,返回 None - 注意:current_state 表示"最后完成的状态",而不是"待执行的状态" + 注意:current_state 始终返回"下一个待执行的节点",配合进度可以判断具体状态 + - 进度 0% + current_state 非空 → 显示"未开始"(还没开始执行,但知道第一个节点是什么) + - 进度 > 0% + current_state 非空 → 显示 current_state.name(正在进行) + - current_state = None → 显示"已完成"(没有待执行的节点了) """ - # 获取最后一条完成且未撤销的记录 - last_completed_record = ( - business_object.state_logs - .filter(is_cancelled=False) - .select_related('state') - .order_by('-completed_at', '-id') - .first() - ) + # 使用 get_next_pending_state 获取下一个待执行的节点 + next_pending = get_next_pending_state(business_object, include_parameters=False) - if last_completed_record: - return last_completed_record.state + if next_pending: + return next_pending['state'] - # 没有任何完成记录,返回 None(未开始) + # 所有节点都已完成,返回 None return None @@ -239,13 +236,13 @@ def can_advance_to_next_state(business_object: 'models.BusinessObject') -> Tuple def get_business_object_state_timeline(business_object: 'models.BusinessObject') -> List[dict]: """ - 获取业务对象状态时间线(包括未开始和已完成的状态) + 获取业务对象状态时间线(包括未开始、进行中和已完成的状态) 返回格式: [ { 'state': State对象, - 'status': 'not_started' | 'completed' | 'cancelled', + 'status': 'not_started' | 'in_progress' | 'completed' | 'cancelled', 'order': 顺序号, 'completed_at': 完成时间(如果已完成), 'completed_by': 完成人(如果已完成), @@ -254,6 +251,12 @@ def get_business_object_state_timeline(business_object: 'models.BusinessObject') }, ... ] + + 状态判断规则: + - cancelled: 有日志记录且已撤销 + - completed: 有日志记录且未撤销 + - in_progress: 没有日志记录,但是 current_state(下一个待执行的节点),且已有完成记录 + - not_started: 其他未开始的节点 """ timeline = [] process_nodes = business_object.process.process_nodes.select_related('state').order_by('order', 'id') @@ -264,6 +267,13 @@ def get_business_object_state_timeline(business_object: 'models.BusinessObject') for log in business_object.state_logs.select_related('completed_by') } + # 获取 current_state(下一个待执行的节点) + current_state = get_business_object_current_state(business_object) + current_state_id = current_state.id if current_state else None + + # 检查是否有任何完成记录 + has_any_completed = business_object.state_logs.filter(is_cancelled=False).exists() + for node in process_nodes: state = node.state log = state_logs_map.get(state.id) @@ -278,7 +288,12 @@ def get_business_object_state_timeline(business_object: 'models.BusinessObject') cancelled_at = log.cancelled_at is_cancelled = log.is_cancelled else: - status = 'not_started' + # 未开始的节点,判断是 in_progress 还是 not_started + # 如果是 current_state 且有任何完成记录,则为 in_progress + if has_any_completed and state.id == current_state_id: + status = 'in_progress' + else: + status = 'not_started' completed_at = None completed_by = None cancelled_at = None diff --git a/stateflow/test_api.py b/stateflow/test_api.py index 074548c..158dd46 100644 --- a/stateflow/test_api.py +++ b/stateflow/test_api.py @@ -565,48 +565,30 @@ class BusinessObjectNewAPITestCase(TestCase): self.assertEqual(response.data['count'], 0) def test_current_state_parameters_api(self): - """测试获取当前状态(最后完成状态)参数 API""" - # 未开始时,current_state 为 None,应返回无参数消息 + """测试获取当前状态(下一个待执行状态)参数 API""" + # 未开始时,current_state 为 state1(第一个待执行的),应返回 state1 的参数 response = self.client.get( f'/api/v1/stateflow/business-objects/{self.business_object.id}/current_state_parameters/' ) self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(len(response.data['parameters']), 0) - self.assertIn('message', response.data) + self.assertEqual(response.data['state']['id'], self.state1.id) + self.assertEqual(len(response.data['parameters']), 2) - # 推进(完成第一个状态),current_state 变为 state1(最后完成的状态) + # 推进(完成第一个状态),current_state 变为 state2(下一个待执行的状态) self.client.post( f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/', {'parameters': {'param1': 'test_value'}}, format='json' ) - # 现在 current_state 是 state1(有参数) - response = self.client.get( - f'/api/v1/stateflow/business-objects/{self.business_object.id}/current_state_parameters/' - ) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data['state']['id'], self.state1.id) - self.assertEqual(response.data['count'], 2) - self.assertEqual(len(response.data['parameters']), 2) - - # 测试只获取必填参数 - response = self.client.get( - f'/api/v1/stateflow/business-objects/{self.business_object.id}/current_state_parameters/?required_only=true' - ) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data['count'], 1) - self.assertEqual(response.data['parameters'][0]['key'], 'param1') - - # 推进(完成第二个状态),current_state 变为 state2(无参数) - self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/') - + # 现在 current_state 是 state2(无参数) response = self.client.get( f'/api/v1/stateflow/business-objects/{self.business_object.id}/current_state_parameters/' ) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['state']['id'], self.state2.id) self.assertEqual(response.data['count'], 0) + self.assertEqual(len(response.data['parameters']), 0) def test_state_parameters_api(self): """测试 State 的参数 API""" diff --git a/stateflow/tests/test_business_object_api.py b/stateflow/tests/test_business_object_api.py index 37d8d63..4ec9634 100644 --- a/stateflow/tests/test_business_object_api.py +++ b/stateflow/tests/test_business_object_api.py @@ -73,9 +73,10 @@ class BusinessObjectAPITestCase(TestCase): self.assertTrue(response.data['success']) self.assertIn('重置', response.data['message']) - # 验证进度已重置 + # 验证进度已重置(current_state 返回第一个待执行的节点) self.business_object.refresh_from_db() - self.assertIsNone(services.get_business_object_current_state(self.business_object)) + current_state = services.get_business_object_current_state(self.business_object) + self.assertEqual(current_state.name, self.state1.name) self.assertEqual(self.business_object.state_logs.filter(is_cancelled=False).count(), 0) def test_reset_api_not_started(self): @@ -120,8 +121,8 @@ class BusinessObjectAPITestCase(TestCase): self.assertEqual(response.data[0]['completed_by'], 'testuser') self.assertFalse(response.data[0]['is_cancelled']) - # 其他状态仍是待执行 - self.assertEqual(response.data[1]['status'], 'not_started') + # 第二个状态是进行中(下一个待执行的) + self.assertEqual(response.data[1]['status'], 'in_progress') self.assertEqual(response.data[2]['status'], 'not_started') def test_timeline_api_with_step_back(self): @@ -469,3 +470,59 @@ class BusinessObjectAPITestCase(TestCase): self.assertIsNotNone(item['completed_at']) self.assertIsNotNone(item['completed_by']) self.assertFalse(item['is_cancelled']) + + def test_advance_when_already_completed(self): + """测试流程已完成时尝试推进(预期错误)""" + # 完成所有状态 + self.client.post( + f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/', + {'parameters': {'temperature': '25.5'}}, + format='json' + ) + self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/') + self.client.post(f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/') + + # 验证已完成 + self.assertEqual(services.get_overall_status(self.business_object), 'completed') + + # 尝试再次推进(应该失败) + response = self.client.post( + f'/api/v1/stateflow/business-objects/{self.business_object.id}/advance/' + ) + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertFalse(response.data['success']) + self.assertIn('流程已完成', response.data['message']) + self.assertIn('无法继续推进', response.data['message']) + + def test_step_back_when_not_started(self): + """测试未开始时尝试回退(预期错误)""" + # 验证未开始 + self.assertEqual(services.get_overall_status(self.business_object), 'not_started') + + # 尝试回退(应该失败) + response = self.client.post( + f'/api/v1/stateflow/business-objects/{self.business_object.id}/step_back/' + ) + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertFalse(response.data['success']) + self.assertIn('没有任何状态流转记录', response.data['message']) + + def test_advance_process_without_nodes(self): + """测试流程没有节点时尝试推进(预期错误)""" + # 创建一个没有节点的流程 + empty_process = models.Process.objects.create(name='空流程') + empty_business_object = models.BusinessObject.objects.create( + name='空业务对象', + process=empty_process + ) + + # 尝试推进(应该失败) + response = self.client.post( + f'/api/v1/stateflow/business-objects/{empty_business_object.id}/advance/' + ) + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertFalse(response.data['success']) + self.assertIn('流程没有任何节点', response.data['message']) diff --git a/stateflow/tests/test_parameters.py b/stateflow/tests/test_parameters.py index c055042..254a441 100644 --- a/stateflow/tests/test_parameters.py +++ b/stateflow/tests/test_parameters.py @@ -72,9 +72,9 @@ class ParameterManagementTestCase(TestCase): self.assertIn('temperature', message) self.assertIsNone(state_log) - # 验证状态未改变 + # 验证状态未改变(仍然是第一个待执行的节点) current_state = services.get_business_object_current_state(self.business_object) - self.assertIsNone(current_state) + self.assertEqual(current_state.name, self.state1.name) # 验证没有创建状态流转记录 self.assertEqual(self.business_object.state_logs.count(), 0) @@ -92,9 +92,9 @@ class ParameterManagementTestCase(TestCase): self.assertTrue(success) self.assertIsNotNone(state_log) - # 验证状态已推进 + # 验证状态已推进(下一个待执行的是 state2) current_state = services.get_business_object_current_state(self.business_object) - self.assertEqual(current_state.name, self.state1.name) + self.assertEqual(current_state.name, self.state2.name) # 验证参数记录已创建 self.assertEqual(state_log.parameter_records.count(), 1) diff --git a/stateflow/tests/test_services.py b/stateflow/tests/test_services.py index a9dd929..0bbf23f 100644 --- a/stateflow/tests/test_services.py +++ b/stateflow/tests/test_services.py @@ -42,9 +42,9 @@ class StateFlowServicesTestCase(TestCase): ) def test_initial_state(self): - """测试初始状态 - 应该是 None(未开始)""" + """测试初始状态 - 应该返回第一个待执行的节点""" current_state = self.business_object.get_current_state() - self.assertIsNone(current_state, '初始状态应该是 None(未开始)') + self.assertEqual(current_state.name, self.state1.name, '初始状态应该返回第一个待执行的节点') self.assertEqual(self.business_object.get_progress_percentage(), 0.0) # 整体状态应该是 not_started @@ -57,18 +57,18 @@ class StateFlowServicesTestCase(TestCase): success, message, _ = services.advance_to_next_state(self.business_object, self.user) self.assertTrue(success) - # current_state 应该是最后完成的状态(state1) + # current_state 应该是下一个待执行的状态(state2) current_state = self.business_object.get_current_state() - self.assertEqual(current_state.name, self.state1.name) + self.assertEqual(current_state.name, self.state2.name) self.assertAlmostEqual(self.business_object.get_progress_percentage(), 33.33, places=1) # 推进到状态2(完成state2) success, message, _ = services.advance_to_next_state(self.business_object, self.user) self.assertTrue(success) - # current_state 应该是 state2 + # current_state 应该是 state3(下一个待执行的) current_state = self.business_object.get_current_state() - self.assertEqual(current_state.name, self.state2.name) + self.assertEqual(current_state.name, self.state3.name) self.assertAlmostEqual(self.business_object.get_progress_percentage(), 66.67, places=1) # 完成最后一个状态(state3) @@ -76,9 +76,9 @@ class StateFlowServicesTestCase(TestCase): self.assertTrue(success) self.assertEqual(self.business_object.get_progress_percentage(), 100.0) - # current_state 应该是 state3(最后完成的状态) + # current_state 应该是 None(没有待执行的节点了) current_state = self.business_object.get_current_state() - self.assertEqual(current_state.name, self.state3.name) + self.assertIsNone(current_state) # 整体状态应该是 completed status = services.get_overall_status(self.business_object) @@ -116,7 +116,7 @@ class StateFlowServicesTestCase(TestCase): timeline = self.business_object.get_timeline() self.assertEqual(timeline[0]['status'], 'completed') - self.assertEqual(timeline[1]['status'], 'not_started') + self.assertEqual(timeline[1]['status'], 'in_progress') # 下一个待执行的节点 self.assertEqual(timeline[2]['status'], 'not_started') self.assertIsNotNone(timeline[0]['completed_by']) self.assertEqual(timeline[0]['completed_by'].id, self.user.id) @@ -141,9 +141,9 @@ class StateFlowServicesTestCase(TestCase): cancelled_count = self.business_object.state_logs.filter(is_cancelled=True).count() self.assertEqual(cancelled_count, 2) - # 应该回到初始状态(未开始) + # 应该回到初始状态(返回第一个待执行的节点) current_state = self.business_object.get_current_state() - self.assertIsNone(current_state) + self.assertEqual(current_state.name, self.state1.name) # 所有撤销的记录都应该有撤销时间 for log in self.business_object.state_logs.all(): diff --git a/stateflow/tests/test_step_back.py b/stateflow/tests/test_step_back.py index baa584c..4c3c894 100644 --- a/stateflow/tests/test_step_back.py +++ b/stateflow/tests/test_step_back.py @@ -51,9 +51,9 @@ class StepBackTestCase(TestCase): success, _, _ = services.advance_to_next_state(self.business_object, self.user) self.assertTrue(success) - # 验证 current_state 是 state1(最后完成的状态) + # 验证 current_state 是 state2(下一个待执行的状态) current_state = services.get_business_object_current_state(self.business_object) - self.assertEqual(current_state.name, self.state1.name) + self.assertEqual(current_state.name, self.state2.name) # 回退一步 success, message = services.step_back_one_state(self.business_object, self.user) @@ -63,7 +63,7 @@ class StepBackTestCase(TestCase): # 验证回到未开始状态 self.assertEqual(services.get_overall_status(self.business_object), 'not_started') current_state = services.get_business_object_current_state(self.business_object) - self.assertIsNone(current_state) + self.assertEqual(current_state.name, self.state1.name) # 验证状态1的记录已被撤销 record = models.StateFlowRecord.objects.filter( @@ -79,18 +79,18 @@ class StepBackTestCase(TestCase): services.advance_to_next_state(self.business_object, self.user) services.advance_to_next_state(self.business_object, self.user) - # 验证 current_state 是 state2(最后完成的状态) + # 验证 current_state 是 state3(下一个待执行的状态) current_state = services.get_business_object_current_state(self.business_object) - self.assertEqual(current_state.name, self.state2.name) + self.assertEqual(current_state.name, self.state3.name) # 回退一步 success, message = services.step_back_one_state(self.business_object, self.user) self.assertTrue(success) self.assertIn('状态2', message) - # 验证 current_state 变为state1 + # 验证 current_state 变为 state2(下一个待执行的) current_state = services.get_business_object_current_state(self.business_object) - self.assertEqual(current_state.name, self.state1.name) + self.assertEqual(current_state.name, self.state2.name) # 验证状态2的记录已被撤销 record = models.StateFlowRecord.objects.filter( @@ -106,20 +106,20 @@ class StepBackTestCase(TestCase): services.advance_to_next_state(self.business_object, self.user) services.advance_to_next_state(self.business_object, self.user) - # 验证已完成,current_state 是 state3 + # 验证已完成,current_state 是 None(没有待执行的节点) self.assertEqual(services.get_overall_status(self.business_object), 'completed') current_state = services.get_business_object_current_state(self.business_object) - self.assertEqual(current_state.name, self.state3.name) + self.assertIsNone(current_state) # 回退一步 success, message = services.step_back_one_state(self.business_object, self.user) self.assertTrue(success) self.assertIn('状态3', message) - # 验证回到进行中状态,current_state 变为state2 + # 验证回到进行中状态,current_state 变为 state3(下一个待执行的) self.assertEqual(services.get_overall_status(self.business_object), 'in_progress') current_state = services.get_business_object_current_state(self.business_object) - self.assertEqual(current_state.name, self.state2.name) + self.assertEqual(current_state.name, self.state3.name) def test_step_back_multiple_times(self): """测试多次回退""" @@ -132,13 +132,13 @@ class StepBackTestCase(TestCase): success, _ = services.step_back_one_state(self.business_object, self.user) self.assertTrue(success) current = services.get_business_object_current_state(self.business_object) - self.assertEqual(current.name, self.state2.name) + self.assertEqual(current.name, self.state3.name) # 第二次回退(撤销 state2) success, _ = services.step_back_one_state(self.business_object, self.user) self.assertTrue(success) current = services.get_business_object_current_state(self.business_object) - self.assertEqual(current.name, self.state1.name) + self.assertEqual(current.name, self.state2.name) # 下一个待执行的是 state2 # 第三次回退 success, _ = services.step_back_one_state(self.business_object, self.user) @@ -163,9 +163,9 @@ class StepBackTestCase(TestCase): success, _, _ = services.advance_to_next_state(self.business_object, self.user) self.assertTrue(success) - # 验证 current_state 是 state2(最后完成的) + # 验证 current_state 是 state3(下一个待执行的) current_state = services.get_business_object_current_state(self.business_object) - self.assertEqual(current_state.name, self.state2.name) + self.assertEqual(current_state.name, self.state3.name) def test_step_back_preserves_history(self): """测试回退操作保留历史记录""" diff --git a/test_output.log b/test_output.log new file mode 100644 index 0000000..a578109 --- /dev/null +++ b/test_output.log @@ -0,0 +1 @@ +zsh: 没有那个文件或目录: home/f/coding/flower/.venv/bin/python