from decimal import Decimal
import datetime

from django.contrib.auth import get_user_model
from django.test import TestCase
from django.utils import timezone
from rest_framework.test import APIClient, APIRequestFactory

from basic_info import models as basic_models
from printing import models as printing_models
from business import models as business_models
from api_v2.views.printing import PrintingJobByCustomerView
from django.contrib.contenttypes.models import ContentType
from stateflow import models as stateflow_models


class QuickCreateEmployeeUserAPITest(TestCase):
    def setUp(self):
        self.client = APIClient()
        self.merchant = basic_models.Merchant.objects.create(
            name='测试商户',
            type=basic_models.MerchantTypeEnum.FACTORY,
        )
        self.admin_user = get_user_model().objects.create_user(username='admin', password='pass12345')
        self.admin_employee = basic_models.Employee.objects.create(
            merchant=self.merchant,
            sys_user=self.admin_user,
            name='管理员',
        )
        self.client.force_authenticate(user=self.admin_user)
        self.url = '/api/v2/users/quick-create/'
        self.payload = {
            'username': 'new_user',
            'password': 'strongPass#1',
            'display_name': '新员工',
            'merchant_id': self.merchant.id,
            'mobile': '13800000000',
        }

    def test_quick_create_employee_user_success(self):
        response = self.client.post(self.url, self.payload, format='json')
        self.assertEqual(response.status_code, 201)
        data = response.data
        self.assertIn('user', data)
        self.assertIn('employee', data)
        self.assertEqual(data['user']['username'], self.payload['username'])

        created_user = get_user_model().objects.get(username=self.payload['username'])
        self.assertEqual(created_user.employee.merchant, self.merchant)
        self.assertEqual(created_user.employee.name, self.payload['display_name'])

    def test_quick_create_employee_user_duplicate_username(self):
        get_user_model().objects.create_user(username=self.payload['username'], password='pass12345')
        response = self.client.post(self.url, self.payload, format='json')
        self.assertEqual(response.status_code, 400)
        self.assertIn('用户名已存在', str(response.data))

    def test_quick_create_employee_user_invalid_merchant(self):
        payload = {**self.payload, 'merchant_id': 9999}
        response = self.client.post(self.url, payload, format='json')
        self.assertEqual(response.status_code, 400)
        self.assertIn('商户不存在', str(response.data))


class PrintingJobByCustomerAPITest(TestCase):
    def setUp(self):
        self.factory = APIRequestFactory()
        self.client = APIClient()
        self.merchant = basic_models.Merchant.objects.create(
            name='印染商户',
            type=basic_models.MerchantTypeEnum.FACTORY,
        )
        self.customer = basic_models.Customer.objects.create(
            merchant=self.merchant,
            name='客户X',
            created_by=None,
        )
        category = basic_models.ProductCategory.objects.create(
            merchant=self.merchant,
            name='品类',
            product_prefix='FAB',
        )
        self.product = basic_models.Product.objects.create(
            merchant=self.merchant,
            category=category,
            name='产品A',
            human_id='FAB-001',
            width_size=Decimal('150.00'),
            color='红色',
            unit=basic_models.ProductUnitEnum.METER,
        )
        self.other_product = basic_models.Product.objects.create(
            merchant=self.merchant,
            category=category,
            name='产品B',
            human_id='FAB-002',
            width_size=Decimal('160.00'),
            color='蓝色',
            unit=basic_models.ProductUnitEnum.METER,
        )
        self.printing_order = printing_models.PrintingOrder.objects.create(
            customer=self.customer,
            fabric='棉',
            width='150cm',
        )
        self.printing_order_other = printing_models.PrintingOrder.objects.create(
            customer=self.customer,
            fabric='麻',
            width='160cm',
        )

        tz = timezone.get_default_timezone()
        in_range = timezone.make_aware(datetime.datetime(2025, 12, 5, 10, 0, 0), tz)
        out_range = timezone.make_aware(datetime.datetime(2025, 11, 20, 10, 0, 0), tz)

        self.job_in_range = printing_models.PrintingJob.objects.create(
            printing_order=self.printing_order,
            product=self.product,
            quantity=10,
            unit='米',
        )
        printing_models.PrintingJob.objects.filter(id=self.job_in_range.id).update(created_at=in_range)

        self.job_out_range = printing_models.PrintingJob.objects.create(
            printing_order=self.printing_order_other,
            product=self.other_product,
            quantity=20,
            unit='米',
        )
        printing_models.PrintingJob.objects.filter(id=self.job_out_range.id).update(created_at=out_range)

        # 关联销售单，验证 billed_quantity
        warehouse = basic_models.WareHouse.objects.create(
            merchant=self.merchant,
            name='仓库A',
            mode=basic_models.WareHouseModeEnum.UNRESTRICTED,
        )
        operator = basic_models.Employee.objects.create(
            merchant=self.merchant,
            name='操作员',
        )
        sales_order = business_models.SalesOrder.objects.create(
            merchant=self.merchant,
            customer=self.customer,
            sales_date=datetime.date(2025, 12, 5),
            operator=operator,
            warehouse=warehouse,
        )
        business_models.SalesOrderItem.objects.create(
            sales_order=sales_order,
            product=self.product,
            price=Decimal('10'),
            quantity=Decimal('12.5'),
            unit='米',
            empty_diff_percent=Decimal('0'),
            num_of_rolls=1,
            printing_job=self.job_in_range,
        )
        business_models.SalesOrderItem.objects.create(
            sales_order=sales_order,
            product=self.product,
            price=Decimal('8'),
            quantity=Decimal('7.5'),
            unit='米',
            empty_diff_percent=Decimal('0'),
            num_of_rolls=1,
            printing_job=self.job_in_range,
        )

        self.view = PrintingJobByCustomerView.as_view()

    def _get(self, params):
        request = self.factory.get('/api/v2/printing/jobs/', params)
        return self.view(request)

    def test_basic_date_and_customer_filter(self):
        resp = self._get({
            'customer_id': self.customer.id,
            'date_from': '2025-12-01',
            'date_to': '2025-12-10',
        })
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(len(resp.data), 1)
        self.assertEqual(resp.data[0]['id'], self.job_in_range.id)
        self.assertEqual(resp.data[0]['billed_quantity'], '20.00')

    def test_filter_by_printing_order(self):
        resp = self._get({
            'customer_id': self.customer.id,
            'date_from': '2025-12-01',
            'date_to': '2025-12-10',
            'printing_order': self.printing_order.id,
        })
        self.assertEqual(len(resp.data), 1)
        self.assertEqual(resp.data[0]['printing_order'], self.printing_order.id)

    def test_filter_by_product_fields(self):
        resp = self._get({
            'customer_id': self.customer.id,
            'date_from': '2025-12-01',
            'date_to': '2025-12-10',
            'product_id': self.product.id,
            'product_name': '产品A',
            'product_human_id': 'FAB-001',
            'product_width_size': '150',
            'product_color': '红',
        })
        self.assertEqual(len(resp.data), 1)
        data = resp.data[0]
        self.assertEqual(data['product']['id'], self.product.id)
        self.assertEqual(data['billed_quantity'], '20.00')


class PrintingJobBatchAdvanceV2APITest(TestCase):
    def setUp(self):
        self.client = APIClient()

        # 工厂用户（满足 IsPrintingFactory）
        self.merchant = basic_models.Merchant.objects.create(
            name='印染工厂',
            type=basic_models.MerchantTypeEnum.FACTORY,
        )
        self.user = get_user_model().objects.create_user(username='factory_user', password='pass12345')
        self.employee = basic_models.Employee.objects.create(
            merchant=self.merchant,
            sys_user=self.user,
            name='工厂员工',
        )
        self.client.force_authenticate(user=self.user)

        # 基础客户/产品
        self.customer = basic_models.Customer.objects.create(
            merchant=self.merchant,
            name='客户A',
            created_by=None,
        )
        category = basic_models.ProductCategory.objects.create(
            merchant=self.merchant,
            name='品类',
            product_prefix='FAB',
        )
        self.product = basic_models.Product.objects.create(
            merchant=self.merchant,
            category=category,
            name='产品A',
            human_id='FAB-100',
            width_size=Decimal('150.00'),
            color='红色',
            unit=basic_models.ProductUnitEnum.METER,
        )

        # stateflow：流程 + 3个节点 + 节点参数（第一步必填）
        self.state1 = stateflow_models.State.objects.create(name='待处理1', description='第一个节点')
        self.state2 = stateflow_models.State.objects.create(name='待处理2', description='第二个节点')
        self.state3 = stateflow_models.State.objects.create(name='待处理3', description='第三个节点')

        self.param_required = stateflow_models.StateParameter.objects.create(
            key='temperature',
            value='',
            is_required=True,
            description='温度（必填）',
        )
        self.state1.parameters.add(self.param_required)

        self.process = stateflow_models.Process.objects.create(name='印染流程')
        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)

        # printing：订单 + 两条明细（每条明细都有 business_object）
        self.printing_order = printing_models.PrintingOrder.objects.create(
            customer=self.customer,
            fabric='棉',
            width='150cm',
            process=self.process,
        )
        bo1 = stateflow_models.BusinessObject.objects.create(
            name='BO-1',
            process=self.process,
        )
        bo2 = stateflow_models.BusinessObject.objects.create(
            name='BO-2',
            process=self.process,
        )

        self.job1 = printing_models.PrintingJob.objects.create(
            printing_order=self.printing_order,
            product=self.product,
            quantity=10,
            unit='米',
            business_object=bo1,
        )
        self.job2 = printing_models.PrintingJob.objects.create(
            printing_order=self.printing_order,
            product=self.product,
            quantity=20,
            unit='米',
            business_object=bo2,
        )

    def test_preview_success_returns_next_state_and_parameters(self):
        resp = self.client.post(
            '/api/v2/printing-jobs/batch-advance/preview/',
            {'printing_job_ids': [self.job1.id, self.job2.id]},
            format='json'
        )
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.data['printing_order_id'], self.printing_order.id)
        self.assertEqual(set(resp.data['printing_job_ids']), {self.job1.id, self.job2.id})

        next_state = resp.data['next_state']
        self.assertEqual(next_state['id'], self.state1.id)
        self.assertEqual(next_state['order'], 0)
        self.assertTrue(any(p['key'] == 'temperature' and p['is_required'] for p in next_state['parameters']))

    def test_preview_fails_when_jobs_not_same_printing_order(self):
        other_order = printing_models.PrintingOrder.objects.create(
            customer=self.customer,
            fabric='麻',
            width='160cm',
            process=self.process,
        )
        bo3 = stateflow_models.BusinessObject.objects.create(name='BO-3', process=self.process)
        job3 = printing_models.PrintingJob.objects.create(
            printing_order=other_order,
            product=self.product,
            quantity=5,
            unit='米',
            business_object=bo3,
        )

        resp = self.client.post(
            '/api/v2/printing-jobs/batch-advance/preview/',
            {'printing_job_ids': [self.job1.id, job3.id]},
            format='json'
        )
        self.assertEqual(resp.status_code, 400)
        self.assertIn('printing_order', resp.data.get('detail', ''))

    def test_submit_success_advances_all_and_creates_batch_record(self):
        resp = self.client.post(
            '/api/v2/printing-jobs/batch-advance/',
            {
                'printing_job_ids': [self.job1.id, self.job2.id],
                'parameters': {'temperature': '25.5'}
            },
            format='json'
        )
        self.assertEqual(resp.status_code, 200)
        self.assertIn('batch_id', resp.data)

        # stateflow：两条 business_object 都应生成 1 条完成日志，且完成的是 state1
        self.job1.refresh_from_db()
        self.job2.refresh_from_db()
        self.assertEqual(self.job1.business_object.state_logs.filter(is_cancelled=False).count(), 1)
        self.assertEqual(self.job2.business_object.state_logs.filter(is_cancelled=False).count(), 1)
        self.assertEqual(self.job1.business_object.state_logs.first().state_id, self.state1.id)
        self.assertEqual(self.job2.business_object.state_logs.first().state_id, self.state1.id)

        # printing：批量记录应存在且关联 jobs
        record = printing_models.PrintingJobBatchAdvanceRecord.objects.get(id=resp.data['batch_id'])
        self.assertEqual(record.created_by_id, self.user.id)
        self.assertEqual(record.printing_order_id, self.printing_order.id)
        self.assertEqual(record.state_id, self.state1.id)
        self.assertEqual(record.parameters.get('temperature'), '25.5')
        self.assertEqual(set(record.printing_jobs.values_list('id', flat=True)), {self.job1.id, self.job2.id})

    def test_submit_fails_when_missing_required_parameter(self):
        resp = self.client.post(
            '/api/v2/printing-jobs/batch-advance/',
            {
                'printing_job_ids': [self.job1.id, self.job2.id],
                'parameters': {}  # 缺少 temperature
            },
            format='json'
        )
        self.assertEqual(resp.status_code, 400)
        self.assertIn('缺失必填参数', resp.data.get('detail', ''))

        # 未产生任何日志/批量记录
        self.assertEqual(self.job1.business_object.state_logs.count(), 0)
        self.assertEqual(self.job2.business_object.state_logs.count(), 0)
        self.assertEqual(printing_models.PrintingJobBatchAdvanceRecord.objects.count(), 0)


class BusinessObjectCloneV2APITest(TestCase):
    def setUp(self):
        self.client = APIClient()
        self.user = get_user_model().objects.create_user(username='u1', password='pass12345')
        self.client.force_authenticate(user=self.user)

        self.state1 = stateflow_models.State.objects.create(name='S1')
        self.state2 = stateflow_models.State.objects.create(name='S2')
        self.process = stateflow_models.Process.objects.create(name='P1')
        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)

        ct = ContentType.objects.get_for_model(stateflow_models.Process)
        self.bo = stateflow_models.BusinessObject.objects.create(
            name='BO',
            process=self.process,
            content_type=ct,
            object_id=111,
        )

        # 创建一条日志 + 参数记录，确保“克隆包含工艺参数”
        log = stateflow_models.StateFlowRecord.objects.create(
            business_object=self.bo,
            state=self.state1,
            completed_by=self.user,
        )
        stateflow_models.StateLogParameterRecord.objects.create(
            state_log=log,
            parameters={'temperature': '25.5'},
            remark='r1',
        )

    def test_clone_business_object_api_returns_new_id(self):
        new_object_id = 222
        resp = self.client.post(
            '/api/v2/stateflow/business-objects/clone/',
            {
                'business_object_id': self.bo.id,
                'content_type': self.bo.content_type_id,
                'object_id': new_object_id,
            },
            format='json'
        )
        self.assertEqual(resp.status_code, 200)
        self.assertIn('business_object_id', resp.data)

        new_id = resp.data['business_object_id']
        self.assertNotEqual(new_id, self.bo.id)

        cloned = stateflow_models.BusinessObject.objects.get(id=new_id)
        self.assertEqual(cloned.process_id, self.bo.process_id)
        self.assertEqual(cloned.state_logs.count(), self.bo.state_logs.count())
        self.assertEqual(cloned.content_type_id, self.bo.content_type_id)
        self.assertEqual(cloned.object_id, new_object_id)

    def test_clone_business_object_api_404(self):
        resp = self.client.post(
            '/api/v2/stateflow/business-objects/clone/',
            {
                'business_object_id': 999999,
                'content_type': self.bo.content_type_id,
                'object_id': 222,
            },
            format='json'
        )
        self.assertEqual(resp.status_code, 404)

    def test_clone_business_object_api_rejects_mismatched_content_type(self):
        # 用另一个 ContentType（比如 State）
        ct_state = ContentType.objects.get_for_model(stateflow_models.State)
        self.assertNotEqual(ct_state.id, self.bo.content_type_id)

        resp = self.client.post(
            '/api/v2/stateflow/business-objects/clone/',
            {
                'business_object_id': self.bo.id,
                'content_type': ct_state.id,
                'object_id': 222,
            },
            format='json'
        )
        self.assertEqual(resp.status_code, 400)
        self.assertIn('content_type', resp.data.get('detail', ''))

    def test_clone_business_object_api_unauthorized(self):
        client = APIClient()
        resp = client.post(
            '/api/v2/stateflow/business-objects/clone/',
            {
                'business_object_id': self.bo.id,
                'content_type': self.bo.content_type_id,
                'object_id': 222,
            },
            format='json'
        )
        self.assertEqual(resp.status_code, 401)


class PlateOrderByProcessNodeV2APITest(TestCase):
    def setUp(self):
        self.client = APIClient()

        # 工厂用户（满足 IsPrintingFactory）
        self.merchant = basic_models.Merchant.objects.create(
            name='开版工厂',
            type=basic_models.MerchantTypeEnum.FACTORY,
        )
        self.user = get_user_model().objects.create_user(username='plate_factory_user', password='pass12345')
        basic_models.Employee.objects.create(
            merchant=self.merchant,
            sys_user=self.user,
            name='开版员工',
        )
        self.client.force_authenticate(user=self.user)

        self.customer = basic_models.Customer.objects.create(
            merchant=self.merchant,
            name='客户P',
            created_by=None,
        )

        # stateflow：流程 + 3个节点
        self.state1 = stateflow_models.State.objects.create(name='节点1')
        self.state2 = stateflow_models.State.objects.create(name='节点2')
        self.state3 = stateflow_models.State.objects.create(name='节点3')
        self.param2 = stateflow_models.StateParameter.objects.create(key='temperature', value='25')
        self.state2.parameters.add(self.param2)

        self.process = stateflow_models.Process.objects.create(name='开版流程')
        self.node1 = stateflow_models.ProcessNode.objects.create(process=self.process, state=self.state1, order=0)
        self.node2 = stateflow_models.ProcessNode.objects.create(process=self.process, state=self.state2, order=1)
        self.node3 = stateflow_models.ProcessNode.objects.create(process=self.process, state=self.state3, order=2)

        # PlateOrder：构造不同“下一待执行节点”
        self.po_state1 = printing_models.PlateOrder.objects.create(
            customer=self.customer,
            process=self.process.id,
            design_code='PO-A',
            style_name='款式A',
        )

        self.po_state2_old = printing_models.PlateOrder.objects.create(
            customer=self.customer,
            process=self.process.id,
            design_code='CODE-X',  # 不包含数字，便于测试 search=id
            style_name='款式B',
        )
        stateflow_models.StateFlowRecord.objects.create(
            business_object=self.po_state2_old.business_object,
            state=self.state1,
            completed_by=self.user,
            is_cancelled=False,
        )
        # 订单维度参数：模拟该订单曾在 state2 提交过参数，但该状态记录已撤销（因此当前仍处于 state2 待执行）
        cancelled_log = stateflow_models.StateFlowRecord.objects.create(
            business_object=self.po_state2_old.business_object,
            state=self.state2,
            completed_by=self.user,
            is_cancelled=True,
        )
        stateflow_models.StateLogParameterRecord.objects.create(
            state_log=cancelled_log,
            parameters={'temperature': '30'},
        )

        self.po_state2_new = printing_models.PlateOrder.objects.create(
            customer=self.customer,
            process=self.process.id,
            design_code='ABC-999',
            style_name='款式C',
        )
        stateflow_models.StateFlowRecord.objects.create(
            business_object=self.po_state2_new.business_object,
            state=self.state1,
            completed_by=self.user,
            is_cancelled=False,
        )

        self.po_state3 = printing_models.PlateOrder.objects.create(
            customer=self.customer,
            process=self.process.id,
            design_code='PO-D',
            style_name='款式D',
        )
        stateflow_models.StateFlowRecord.objects.create(
            business_object=self.po_state3.business_object,
            state=self.state1,
            completed_by=self.user,
            is_cancelled=False,
        )
        stateflow_models.StateFlowRecord.objects.create(
            business_object=self.po_state3.business_object,
            state=self.state2,
            completed_by=self.user,
            is_cancelled=False,
        )

        # 固定 created_at 用于排序断言
        tz = timezone.get_default_timezone()
        t_old = timezone.make_aware(datetime.datetime(2025, 12, 1, 10, 0, 0), tz)
        t_new = timezone.make_aware(datetime.datetime(2025, 12, 2, 10, 0, 0), tz)
        printing_models.PlateOrder.objects.filter(id=self.po_state2_old.id).update(created_at=t_old)
        printing_models.PlateOrder.objects.filter(id=self.po_state2_new.id).update(created_at=t_new)

        self.url = '/api/v2/plate-orders/by-process-node/'

    def test_filter_by_process_node_returns_only_matching_next_pending(self):
        resp = self.client.get(self.url, {'process_node_id': self.node2.id})
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.data['process_node']['id'], self.node2.id)
        self.assertEqual(resp.data['process_node']['state_id'], self.state2.id)
        self.assertTrue(any(p['key'] == 'temperature' and p['value'] == '25' for p in resp.data['parameters']))

        ids = [item['id'] for item in resp.data['results']]
        self.assertEqual(set(ids), {self.po_state2_old.id, self.po_state2_new.id})

        # results 必须包含“订单维度”的参数值（同一节点下不同订单可不同）
        by_id = {item['id']: item for item in resp.data['results']}
        self.assertIn('process_parameters', by_id[self.po_state2_old.id])
        self.assertIn('process_parameters', by_id[self.po_state2_new.id])

        # po_state2_old：来自已撤销的 state2 提交记录
        self.assertTrue(
            any(p['key'] == 'temperature' and p['value'] == '30' for p in by_id[self.po_state2_old.id]['process_parameters'])
        )
        # po_state2_new：从未提交过 state2 参数，value 应为 null
        self.assertTrue(
            any(p['key'] == 'temperature' and p['value'] is None for p in by_id[self.po_state2_new.id]['process_parameters'])
        )

    def test_process_parameters_schema_and_keys_align_with_template(self):
        resp = self.client.get(self.url, {'process_node_id': self.node2.id})
        self.assertEqual(resp.status_code, 200)

        template_keys = [p['key'] for p in resp.data['parameters']]
        self.assertGreater(len(template_keys), 0)

        for item in resp.data['results']:
            self.assertIn('process_parameters', item)
            self.assertIsInstance(item['process_parameters'], list)

            keys = [p.get('key') for p in item['process_parameters']]
            self.assertEqual(keys, template_keys)

            # 严格 schema：每项只能有 key/value 两个字段（便于前端做稳定类型定义）
            for p in item['process_parameters']:
                self.assertEqual(set(p.keys()), {'key', 'value'})

    def test_when_state_has_no_parameters_returns_empty_process_parameters(self):
        # node1 对应 state1：该测试 setUp 中未配置任何参数
        resp = self.client.get(self.url, {'process_node_id': self.node1.id})
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.data['parameters'], [])
        self.assertEqual(len(resp.data['results']), 1)
        self.assertEqual(resp.data['results'][0]['id'], self.po_state1.id)
        self.assertEqual(resp.data['results'][0]['process_parameters'], [])

    def test_default_ordering_is_minus_created_at(self):
        resp = self.client.get(self.url, {'process_node_id': self.node2.id})
        self.assertEqual(resp.status_code, 200)
        ids = [item['id'] for item in resp.data['results']]
        self.assertEqual(ids[0], self.po_state2_new.id)
        self.assertEqual(ids[1], self.po_state2_old.id)

    def test_ordering_param_created_at_asc(self):
        resp = self.client.get(self.url, {'process_node_id': self.node2.id, 'ordering': 'created_at'})
        self.assertEqual(resp.status_code, 200)
        ids = [item['id'] for item in resp.data['results']]
        self.assertEqual(ids[0], self.po_state2_old.id)
        self.assertEqual(ids[1], self.po_state2_new.id)

    def test_search_supports_design_code_icontains(self):
        resp = self.client.get(self.url, {'process_node_id': self.node2.id, 'search': 'abc'})
        self.assertEqual(resp.status_code, 200)
        ids = [item['id'] for item in resp.data['results']]
        self.assertEqual(ids, [self.po_state2_new.id])

    def test_search_supports_pk_without_extra_param(self):
        resp = self.client.get(self.url, {'process_node_id': self.node2.id, 'search': str(self.po_state2_old.id)})
        self.assertEqual(resp.status_code, 200)
        ids = [item['id'] for item in resp.data['results']]
        self.assertEqual(ids, [self.po_state2_old.id])

    def test_pagination_limit_offset(self):
        resp = self.client.get(self.url, {'process_node_id': self.node2.id, 'limit': 1, 'offset': 0})
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.data['count'], 2)
        self.assertEqual(len(resp.data['results']), 1)
