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 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'], self.product.id) self.assertEqual(data['billed_quantity'], '20.00')