forked from erp-dev/erp
feat: new api for plate order (get_plate_order_by_state_status)
This commit is contained in:
233
api_v2/tests.py
233
api_v2/tests.py
@@ -960,6 +960,239 @@ class PlateOrderByProcessV2APITest(TestCase):
|
||||
self.assertEqual(resp.status_code, 400)
|
||||
|
||||
|
||||
class PlateOrderByStateStatusV2APITest(TestCase):
|
||||
def setUp(self):
|
||||
self.client = APIClient()
|
||||
|
||||
self.merchant = basic_models.Merchant.objects.create(
|
||||
name='开版工厂3',
|
||||
type=basic_models.MerchantTypeEnum.FACTORY,
|
||||
)
|
||||
self.user = get_user_model().objects.create_user(username='state_status_user', password='pass12345')
|
||||
basic_models.Employee.objects.create(
|
||||
merchant=self.merchant,
|
||||
sys_user=self.user,
|
||||
name='开版员工3',
|
||||
)
|
||||
self.client.force_authenticate(user=self.user)
|
||||
|
||||
self.customer = basic_models.Customer.objects.create(
|
||||
merchant=self.merchant,
|
||||
name='客户SS',
|
||||
created_by=None,
|
||||
)
|
||||
|
||||
self.state_prepare = stateflow_models.State.objects.create(name='画图')
|
||||
self.state_target = stateflow_models.State.objects.create(name='调色')
|
||||
self.state_unlinked = stateflow_models.State.objects.create(name='未绑定')
|
||||
self.param_temp = stateflow_models.StateParameter.objects.create(key='temperature', value='25')
|
||||
self.state_target.parameters.add(self.param_temp)
|
||||
|
||||
self.process = stateflow_models.Process.objects.create(name='主流程')
|
||||
self.node_prepare = stateflow_models.ProcessNode.objects.create(process=self.process, state=self.state_prepare, order=0)
|
||||
self.node_target = stateflow_models.ProcessNode.objects.create(process=self.process, state=self.state_target, order=1)
|
||||
|
||||
self.other_process = stateflow_models.Process.objects.create(name='其他流程')
|
||||
stateflow_models.ProcessNode.objects.create(process=self.other_process, state=self.state_target, order=0)
|
||||
|
||||
self.po_not_started = printing_models.PlateOrder.objects.create(
|
||||
customer=self.customer,
|
||||
process=self.process.id,
|
||||
design_code='PO-NOT',
|
||||
style_name='款式N',
|
||||
)
|
||||
self.po_no_logs = printing_models.PlateOrder.objects.create(
|
||||
customer=self.customer,
|
||||
process=self.process.id,
|
||||
design_code='PO-ZERO',
|
||||
style_name='款式Z',
|
||||
)
|
||||
self.po_completed_old = printing_models.PlateOrder.objects.create(
|
||||
customer=self.customer,
|
||||
process=self.process.id,
|
||||
design_code='PO-C-OLD',
|
||||
style_name='款式CO',
|
||||
)
|
||||
self.po_completed_new = printing_models.PlateOrder.objects.create(
|
||||
customer=self.customer,
|
||||
process=self.process.id,
|
||||
design_code='PO-C-NEW',
|
||||
style_name='款式CN',
|
||||
)
|
||||
self.po_cancelled = printing_models.PlateOrder.objects.create(
|
||||
customer=self.customer,
|
||||
process=self.process.id,
|
||||
design_code='PO-CAN',
|
||||
style_name='款式CA',
|
||||
)
|
||||
self.po_other_process = printing_models.PlateOrder.objects.create(
|
||||
customer=self.customer,
|
||||
process=self.other_process.id,
|
||||
design_code='PO-OTHER',
|
||||
style_name='款式OP',
|
||||
)
|
||||
|
||||
self._complete_state(self.po_not_started, self.state_prepare)
|
||||
self._complete_state(self.po_completed_old, self.state_prepare)
|
||||
self._complete_state(self.po_completed_new, self.state_prepare)
|
||||
self._complete_state(self.po_cancelled, self.state_prepare)
|
||||
|
||||
self._complete_state(self.po_completed_old, self.state_target, parameters={'temperature': '28'})
|
||||
self._complete_state(self.po_completed_new, self.state_target, parameters={'temperature': '32'})
|
||||
self._complete_state(self.po_cancelled, self.state_target, is_cancelled=True, parameters={'temperature': '99'})
|
||||
self._complete_state(self.po_other_process, self.state_target, parameters={'temperature': '88'})
|
||||
|
||||
tz = timezone.get_default_timezone()
|
||||
t_old = timezone.make_aware(datetime.datetime(2025, 12, 1, 9, 0, 0), tz)
|
||||
t_new = timezone.make_aware(datetime.datetime(2025, 12, 3, 9, 0, 0), tz)
|
||||
printing_models.PlateOrder.objects.filter(id=self.po_completed_old.id).update(created_at=t_old)
|
||||
printing_models.PlateOrder.objects.filter(id=self.po_completed_new.id).update(created_at=t_new)
|
||||
|
||||
self.url = '/api/v2/plate-orders/by-state-status/'
|
||||
|
||||
def _complete_state(self, plate_order, state, *, is_cancelled=False, parameters=None):
|
||||
log = stateflow_models.StateFlowRecord.objects.create(
|
||||
business_object=plate_order.business_object,
|
||||
state=state,
|
||||
completed_by=self.user,
|
||||
is_cancelled=is_cancelled,
|
||||
)
|
||||
if parameters is not None:
|
||||
stateflow_models.StateLogParameterRecord.objects.create(
|
||||
state_log=log,
|
||||
parameters=parameters,
|
||||
)
|
||||
return log
|
||||
|
||||
def test_completed_status_returns_sorted_plate_orders(self):
|
||||
resp = self.client.get(
|
||||
self.url,
|
||||
{
|
||||
'process_id': self.process.id,
|
||||
'state_id': self.state_target.id,
|
||||
'status': 'completed',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(resp.data['state']['id'], self.state_target.id)
|
||||
self.assertEqual(resp.data['status'], 'completed')
|
||||
ids = [item['id'] for item in resp.data['results']]
|
||||
self.assertEqual(ids, [self.po_completed_new.id, self.po_completed_old.id])
|
||||
|
||||
template_keys = [p['key'] for p in resp.data['state_parameters']]
|
||||
self.assertEqual(template_keys, ['temperature'])
|
||||
|
||||
by_id = {item['id']: item for item in resp.data['results']}
|
||||
self.assertEqual(by_id[self.po_completed_new.id]['state_parameters'][0]['value'], '32')
|
||||
self.assertEqual(by_id[self.po_completed_old.id]['state_parameters'][0]['value'], '28')
|
||||
self.assertIsNotNone(by_id[self.po_completed_new.id]['state_log'])
|
||||
self.assertFalse(by_id[self.po_completed_new.id]['state_log']['is_cancelled'])
|
||||
|
||||
def test_default_status_is_completed(self):
|
||||
resp = self.client.get(
|
||||
self.url,
|
||||
{
|
||||
'process_id': self.process.id,
|
||||
'state_id': self.state_target.id,
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
ids = [item['id'] for item in resp.data['results']]
|
||||
self.assertEqual(set(ids), {self.po_completed_new.id, self.po_completed_old.id})
|
||||
|
||||
def test_state_id_with_not_started_status_is_invalid(self):
|
||||
resp = self.client.get(
|
||||
self.url,
|
||||
{
|
||||
'process_id': self.process.id,
|
||||
'state_id': self.state_target.id,
|
||||
'status': 'not_started',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp.status_code, 400)
|
||||
|
||||
def test_cancelled_status_returns_orders_with_cancelled_logs(self):
|
||||
resp = self.client.get(
|
||||
self.url,
|
||||
{
|
||||
'process_id': self.process.id,
|
||||
'state_id': self.state_target.id,
|
||||
'status': 'cancelled',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(resp.data['results'][0]['id'], self.po_cancelled.id)
|
||||
self.assertTrue(resp.data['results'][0]['state_log']['is_cancelled'])
|
||||
|
||||
def test_invalid_process_state_pair_returns_400(self):
|
||||
resp = self.client.get(
|
||||
self.url,
|
||||
{
|
||||
'process_id': self.process.id,
|
||||
'state_id': self.state_unlinked.id,
|
||||
'status': 'completed',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp.status_code, 400)
|
||||
self.assertIn('state 不属于该 process', resp.data['detail'])
|
||||
|
||||
def test_ordering_created_at_and_pagination(self):
|
||||
resp = self.client.get(
|
||||
self.url,
|
||||
{
|
||||
'process_id': self.process.id,
|
||||
'state_id': self.state_target.id,
|
||||
'status': 'completed',
|
||||
'ordering': 'created_at',
|
||||
'limit': 1,
|
||||
'offset': 1,
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(resp.data['count'], 2)
|
||||
self.assertEqual(len(resp.data['results']), 1)
|
||||
self.assertEqual(resp.data['results'][0]['id'], self.po_completed_new.id)
|
||||
|
||||
def test_other_process_records_are_excluded(self):
|
||||
resp = self.client.get(
|
||||
self.url,
|
||||
{
|
||||
'process_id': self.process.id,
|
||||
'state_id': self.state_target.id,
|
||||
'status': 'completed',
|
||||
}
|
||||
)
|
||||
ids = [item['id'] for item in resp.data['results']]
|
||||
self.assertNotIn(self.po_other_process.id, ids)
|
||||
|
||||
def test_without_state_id_returns_orders_without_any_logs(self):
|
||||
resp = self.client.get(
|
||||
self.url,
|
||||
{
|
||||
'process_id': self.process.id,
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(resp.data['status'], 'not_started')
|
||||
self.assertIsNone(resp.data['state'])
|
||||
self.assertEqual(resp.data['state_parameters'], [])
|
||||
ids = [item['id'] for item in resp.data['results']]
|
||||
self.assertEqual(ids, [self.po_no_logs.id])
|
||||
self.assertEqual(resp.data['results'][0]['state_parameters'], [])
|
||||
self.assertIsNone(resp.data['results'][0]['state_log'])
|
||||
|
||||
def test_without_state_id_only_allows_not_started_status(self):
|
||||
resp = self.client.get(
|
||||
self.url,
|
||||
{
|
||||
'process_id': self.process.id,
|
||||
'status': 'completed',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp.status_code, 400)
|
||||
self.assertIn('state_id 为空时仅支持 status=not_started', resp.data['detail'])
|
||||
|
||||
|
||||
class PlateOrderBatchUpdateV2APITest(TestCase):
|
||||
def setUp(self):
|
||||
self.client = APIClient()
|
||||
|
||||
Reference in New Issue
Block a user