From 4dc6d98abf86bf1ea6da1b63b45cf99d7b6fa130 Mon Sep 17 00:00:00 2001 From: javad Date: Fri, 9 Oct 2026 11:05:10 +0330 Subject: [PATCH] fix order --- apps/jwt_auth/test_regressions.py | 33 +++++++++++++++++++++++++++++ apps/shop/selectors/product.py | 7 +++--- apps/shop/views/product_category.py | 3 ++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/apps/jwt_auth/test_regressions.py b/apps/jwt_auth/test_regressions.py index 9398ba4..b68ad05 100644 --- a/apps/jwt_auth/test_regressions.py +++ b/apps/jwt_auth/test_regressions.py @@ -418,6 +418,39 @@ class OrderingRegressionTests(RegressionFixtures): self.assertIsNone(response.data['category_img']) self.assertEqual([row['name'] for row in response.data['products']], ['B', 'A']) + def test_catalog_order_changes_follow_database_and_zero_precedes_null(self): + Product.objects.create(name='Unordered product', category=self.unordered, sys_ws=self.workspace, price=1) + self.use_role() + ProductCategory.objects.filter(pk=self.second.pk).update(order_cat=0) + response = self.client.get('/shop/v2/product-category/list/') + self.assertEqual([row['name'] for row in response.data], ['Second', 'First', 'Unordered']) + Product.objects.filter(pk=self.a.pk).update(order_prd=0) + Product.objects.filter(pk=self.b.pk).update(order_prd=None) + response = self.client.get(f'/shop/product/list/{self.first.pk}/') + self.assertEqual([row['name'] for row in response.data['products']], ['A', 'B']) + Product.objects.create(name='Custom later', category=self.first, sys_ws=self.workspace, price=1, view_only=True, order_prd=None) + Product.objects.create(name='Custom first', category=self.first, sys_ws=self.workspace, price=1, view_only=True, order_prd=0) + response = self.client.get(f'/shop/product/list/{self.first.pk}/') + self.assertEqual([row['name'] for row in response.data['view_only_products']], ['Custom first', 'Custom later']) + + def test_order_excel_uses_current_database_order_independently_of_insertion(self): + order = Order.objects.create(customer=self.customer, total_price=60, factor_type=1, sys_ws=self.workspace) + for product in [self.c, self.b, self.a]: + OrderItem.objects.create(order=order, product=product, product_name=product.name, price=product.price, amount=1) + self.use_role(self.operator) + ProductCategory.objects.filter(pk=self.first.pk).update(excel_order=0) + Product.objects.filter(pk=self.b.pk).update(excel_order=0) + response = self.client.get(f'/shop/order/{order.pk}/operator/excel/') + self.assertEqual(response.status_code, 200) + sheet = load_workbook(BytesIO(response.content)).active + self.assertEqual([row[0] for row in list(sheet.values)[1:]], ['FirstB', 'FirstA', 'SecondC']) + ProductCategory.objects.update(excel_order=None) + Product.objects.update(excel_order=None) + ProductCategory.objects.filter(pk=self.second.pk).update(order_cat=0) + response = self.client.get(f'/shop/order/{order.pk}/operator/excel/') + sheet = load_workbook(BytesIO(response.content)).active + self.assertEqual([row[0] for row in list(sheet.values)[1:]], ['SecondC', 'FirstB', 'FirstA']) + def test_order_excel_matches_independent_order_and_handles_empty_order(self): order = Order.objects.create(customer=self.customer, total_price=60, factor_type=1, sys_ws=self.workspace) for product in [self.b, self.a, self.c]: diff --git a/apps/shop/selectors/product.py b/apps/shop/selectors/product.py index 1d560ca..23ab7c5 100644 --- a/apps/shop/selectors/product.py +++ b/apps/shop/selectors/product.py @@ -1,5 +1,6 @@ from apps.shop.models import Product as ProductModel from rest_framework import exceptions +from apps.shop.ordering import product_ordering def retrieve_product(product_id: int, workspace_uuid: str) -> ProductModel: @@ -23,7 +24,7 @@ def list_product(workspace_uuid: str) -> ProductModel: def list_product_by_category(workspace_uuid: str, category_id: int) -> ProductModel: try: product_category_obj = ProductModel.objects.filter(sys_ws__uuid=workspace_uuid, category_id=category_id, - view_only=False) + view_only=False).order_by(*product_ordering()) return product_category_obj except Exception as exp: message = f'Error Fetching List Product by category: {exp}' @@ -33,7 +34,7 @@ def list_product_by_category(workspace_uuid: str, category_id: int) -> ProductMo def list_view_only_product_by_category(workspace_uuid: str, category_id: int) -> ProductModel: try: view_only_product_category_obj = ProductModel.objects.filter(sys_ws__uuid=workspace_uuid, category_id=category_id, - view_only=True) + view_only=True).order_by(*product_ordering()) return view_only_product_category_obj except Exception as exp: message = f'Error Fetching View Only List Product by category: {exp}' @@ -46,4 +47,4 @@ def count_product_in_category(workspace_uuid: str, category_id: int) -> int: return count_product except Exception as exp: message = f'Error Couting Product in category: {exp}' - raise exceptions.ValidationError({'error': message}) \ No newline at end of file + raise exceptions.ValidationError({'error': message}) diff --git a/apps/shop/views/product_category.py b/apps/shop/views/product_category.py index bd91b70..a1bd6e9 100644 --- a/apps/shop/views/product_category.py +++ b/apps/shop/views/product_category.py @@ -9,6 +9,7 @@ from apps.shop.selectors import * from rest_framework import generics from rest_framework.permissions import IsAuthenticated from django.db.models import Count +from apps.shop.ordering import category_ordering from utils.tools import inline_serializer from utils import custom_permissions @@ -164,7 +165,7 @@ class ProductsCategoryApi(APIView): p_cate = ProductCategoryModel.objects.filter( sys_ws__uuid=get_user_workspace_uuid(request), - ).annotate(product_count=Count('product')).filter(product_count__gte=1) + ).annotate(product_count=Count('product')).filter(product_count__gte=1).order_by(*category_ordering()) output = self.OutputSerializer(p_cate, many=True) return Response(data=output.data, status=status.HTTP_200_OK)