1
0
forked from erp-dev/erp

fix: little bugs, feat: woodpecker settings

This commit is contained in:
2025-11-14 15:11:26 +08:00
parent 107e65afc0
commit af523d0350
9 changed files with 852 additions and 27 deletions

View File

@@ -8,6 +8,7 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from basic_info import models as basic_models
from printing import models as printing_models
from stateflow import models as stateflow_models
User = get_user_model()
@@ -76,6 +77,19 @@ class PlateOrderAPITestCase(TestCase):
change_perm = Permission.objects.get(codename='change_plateorder')
delete_perm = Permission.objects.get(codename='delete_plateorder')
self.user.user_permissions.add(view_perm, add_perm, change_perm, delete_perm)
# 创建测试流程
self.state1 = stateflow_models.State.objects.create(name='画图', description='画图阶段')
self.state2 = stateflow_models.State.objects.create(name='调色', description='调色阶段')
self.state3 = stateflow_models.State.objects.create(name='套样', description='套样阶段')
self.process = stateflow_models.Process.objects.create(
name='开版流程',
description='标准开版流程'
)
stateflow_models.ProcessNode.objects.create(process=self.process, state=self.state1, order=0)
stateflow_models.ProcessNode.objects.create(process=self.process, state=self.state2, order=1)
stateflow_models.ProcessNode.objects.create(process=self.process, state=self.state3, order=2)
def test_create_plate_order(self):
"""测试创建开版订单"""
@@ -401,6 +415,298 @@ class PlateOrderAPITestCase(TestCase):
else:
self.assertEqual(response.data[0]['id'], order1.id)
self.assertEqual(response.data[1]['id'], order2.id)
def test_create_plate_order_with_process(self):
"""测试创建开版订单时指定流程"""
data = {
'customer': self.customer.id,
'design_code': 'DESIGN100',
'plate_type': '圆网',
'style_name': '测试款式',
'fabric': '棉布',
'process': self.process.id,
}
response = self.client.post('/api/v1/plate-orders/', data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data['process'], self.process.id)
# 验证数据库中创建了 BusinessObject
plate_order = printing_models.PlateOrder.objects.get(id=response.data['id'])
self.assertIsNotNone(plate_order.business_object)
self.assertEqual(plate_order.business_object.process.id, self.process.id)
def test_create_plate_order_without_process(self):
"""测试创建开版订单时不指定流程(使用默认流程)"""
data = {
'customer': self.customer.id,
'design_code': 'DESIGN101',
'plate_type': '圆网',
'style_name': '测试款式',
'fabric': '棉布',
}
response = self.client.post('/api/v1/plate-orders/', data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
# 应该使用默认流程
self.assertIsNotNone(response.data['process'])
# 验证使用了默认流程
plate_order = printing_models.PlateOrder.objects.get(id=response.data['id'])
from django.conf import settings
self.assertEqual(plate_order.process, settings.PLATE_ORDER_DEFAULT_PROCESS_ID)
def test_create_plate_order_with_invalid_process(self):
"""测试创建开版订单时指定无效的流程ID"""
data = {
'customer': self.customer.id,
'design_code': 'DESIGN102',
'plate_type': '圆网',
'style_name': '测试款式',
'fabric': '棉布',
'process': 99999, # 不存在的流程ID
}
response = self.client.post('/api/v1/plate-orders/', data, format='json')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertIn('process', response.data)
def test_retrieve_plate_order_with_process_name(self):
"""测试获取开版订单详情时包含流程名称"""
plate_order = printing_models.PlateOrder.objects.create(
customer=self.customer,
design_code='DESIGN103',
plate_type='圆网',
style_name='测试款式',
fabric='棉布',
process=self.process.id,
)
response = self.client.get(f'/api/v1/plate-orders/{plate_order.id}/')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['process'], self.process.id)
self.assertEqual(response.data['process_name'], self.process.name)
# 验证自动创建了 business_object
self.assertIsNotNone(response.data['business_object_id'])
def test_list_plate_orders_includes_process_name(self):
"""测试列表接口包含流程名称"""
printing_models.PlateOrder.objects.create(
customer=self.customer,
design_code='DESIGN104',
plate_type='圆网',
style_name='款式1',
process=self.process.id,
)
response = self.client.get('/api/v1/plate-orders/')
self.assertEqual(response.status_code, status.HTTP_200_OK)
if isinstance(response.data, dict):
result = response.data['results'][0]
else:
result = response.data[0]
self.assertEqual(result['process'], self.process.id)
self.assertEqual(result['process_name'], self.process.name)
def test_update_plate_order_process(self):
"""测试更新开版订单的流程"""
# 创建另一个流程
process2 = stateflow_models.Process.objects.create(
name='快速开版流程',
description='简化的开版流程'
)
stateflow_models.ProcessNode.objects.create(process=process2, state=self.state1, order=0)
plate_order = printing_models.PlateOrder.objects.create(
customer=self.customer,
design_code='DESIGN105',
plate_type='圆网',
style_name='测试款式',
process=self.process.id,
)
# 获取原来的 business_object
old_business_object_id = plate_order.business_object.id if plate_order.business_object else None
# 更新流程(注意:这只会更新 process 字段,不会重新创建 business_object
data = {
'customer': self.customer.id,
'design_code': 'DESIGN105',
'plate_type': '圆网',
'style_name': '测试款式',
'process': process2.id,
}
response = self.client.put(f'/api/v1/plate-orders/{plate_order.id}/', data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['process'], process2.id)
# 验证 business_object 没有改变(因为已经存在)
plate_order.refresh_from_db()
if old_business_object_id:
self.assertEqual(plate_order.business_object.id, old_business_object_id)
def test_business_object_auto_creation(self):
"""测试 BusinessObject 自动创建逻辑"""
# 直接创建 PlateOrder不通过 API
plate_order = printing_models.PlateOrder(
customer=self.customer,
design_code='DESIGN106',
plate_type='圆网',
style_name='测试款式',
process=self.process.id,
)
# 保存前没有 business_object
self.assertIsNone(plate_order.business_object)
# 保存后自动创建
plate_order.save()
plate_order.refresh_from_db()
self.assertIsNotNone(plate_order.business_object)
self.assertEqual(plate_order.business_object.process.id, self.process.id)
def test_advance_to_next_state(self):
"""测试推进到下一个状态"""
plate_order = printing_models.PlateOrder.objects.create(
customer=self.customer,
design_code='DESIGN107',
plate_type='圆网',
style_name='测试款式',
process=self.process.id,
)
# 确保有 business_object
self.assertIsNotNone(plate_order.business_object)
response = self.client.post(f'/api/v1/plate-orders/{plate_order.id}/advance-to-next-state/')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('detail', response.data)
self.assertIn('data', response.data)
# 验证状态改变
plate_order.refresh_from_db()
self.assertIsNotNone(plate_order.status)
def test_advance_to_next_state_without_business_object(self):
"""测试没有 business_object 时推进状态"""
plate_order = printing_models.PlateOrder.objects.create(
customer=self.customer,
design_code='DESIGN108',
plate_type='圆网',
style_name='测试款式',
)
# 手动清除 business_object
plate_order.business_object = None
plate_order.save(update_fields=['business_object'])
response = self.client.post(f'/api/v1/plate-orders/{plate_order.id}/advance-to-next-state/')
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertIn('没有关联的流程实例', response.data['detail'])
def test_step_back_one_state(self):
"""测试回退一步"""
plate_order = printing_models.PlateOrder.objects.create(
customer=self.customer,
design_code='DESIGN109',
plate_type='圆网',
style_name='测试款式',
process=self.process.id,
)
# 先推进一步
from stateflow import services as stateflow_services
stateflow_services.advance_to_next_state(plate_order.business_object, self.user)
# 再回退
response = self.client.post(f'/api/v1/plate-orders/{plate_order.id}/step-back-one-state/')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('detail', response.data)
self.assertIn('data', response.data)
def test_completed_states(self):
"""测试查询已完成的流程列表"""
plate_order = printing_models.PlateOrder.objects.create(
customer=self.customer,
design_code='DESIGN110',
plate_type='圆网',
style_name='测试款式',
process=self.process.id,
)
# 推进几步
from stateflow import services as stateflow_services
stateflow_services.advance_to_next_state(plate_order.business_object, self.user)
stateflow_services.advance_to_next_state(plate_order.business_object, self.user)
response = self.client.get(f'/api/v1/plate-orders/{plate_order.id}/completed-states/')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('count', response.data)
self.assertIn('results', response.data)
self.assertEqual(response.data['count'], 2)
def test_completed_states_include_cancelled(self):
"""测试查询包含已撤销的流程"""
plate_order = printing_models.PlateOrder.objects.create(
customer=self.customer,
design_code='DESIGN111',
plate_type='圆网',
style_name='测试款式',
process=self.process.id,
)
response = self.client.get(f'/api/v1/plate-orders/{plate_order.id}/completed-states/?include_cancelled=true')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('count', response.data)
self.assertIn('results', response.data)
def test_timeline(self):
"""测试获取流程时间线"""
plate_order = printing_models.PlateOrder.objects.create(
customer=self.customer,
design_code='DESIGN112',
plate_type='圆网',
style_name='测试款式',
process=self.process.id,
)
# 推进一步
from stateflow import services as stateflow_services
stateflow_services.advance_to_next_state(plate_order.business_object, self.user)
response = self.client.get(f'/api/v1/plate-orders/{plate_order.id}/timeline/')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('count', response.data)
self.assertIn('results', response.data)
# 验证返回的数据结构
if response.data['count'] > 0:
first_item = response.data['results'][0]
self.assertIn('state_id', first_item)
self.assertIn('state_name', first_item)
self.assertIn('state_description', first_item)
self.assertIn('order', first_item)
self.assertIn('status', first_item)
def test_timeline_without_business_object(self):
"""测试没有 business_object 时获取时间线"""
plate_order = printing_models.PlateOrder.objects.create(
customer=self.customer,
design_code='DESIGN113',
plate_type='圆网',
style_name='测试款式',
)
# 手动清除 business_object
plate_order.business_object = None
plate_order.save(update_fields=['business_object'])
response = self.client.get(f'/api/v1/plate-orders/{plate_order.id}/timeline/')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['count'], 0)
class PlateOrderInvalidateAPITestCase(TestCase):
@@ -448,6 +754,14 @@ class PlateOrderInvalidateAPITestCase(TestCase):
add_perm = Permission.objects.get(codename='add_plateorder')
change_perm = Permission.objects.get(codename='change_plateorder')
self.user.user_permissions.add(view_perm, add_perm, change_perm)
# 创建测试流程(用于测试)
self.state1 = stateflow_models.State.objects.create(name='画图', description='画图阶段')
self.process = stateflow_models.Process.objects.create(
name='开版流程',
description='标准开版流程'
)
stateflow_models.ProcessNode.objects.create(process=self.process, state=self.state1, order=0)
def test_invalidate_plate_order_without_permission(self):
"""测试无权限作废开版订单"""