diff --git a/loko/mobile/views.py b/loko/mobile/views.py index 447328d..9190776 100644 --- a/loko/mobile/views.py +++ b/loko/mobile/views.py @@ -459,14 +459,22 @@ def stock_preparation_orders_mobile(request): q_filter |= models.Q(intervention__id=int(search_q)) preparation_orders = preparation_orders.filter(q_filter) - preparation_orders = preparation_orders.prefetch_related( - 'preparationorderitem_set__product' - ).order_by('date')[:200] + selected_order = request.GET.get('order', 'desc').strip() + if selected_order == 'asc': + preparation_orders = preparation_orders.prefetch_related( + 'preparationorderitem_set__product' + ).order_by('date')[:200] + else: + selected_order = 'desc' + preparation_orders = preparation_orders.prefetch_related( + 'preparationorderitem_set__product' + ).order_by('-date')[:200] return render(request, "stock/mobile/stock_preparation_orders_mobile.html", { 'preparation_orders': preparation_orders, 'selected_status': selected_status, 'selected_priority': selected_priority, 'search_q': search_q, + 'selected_order': selected_order, 'preparation_order_status_choices': [ ('active', _("À traiter & En attente")), ('to_process', _("A traiter")), @@ -544,7 +552,12 @@ def stock_production_orders_mobile(request): q_filter |= models.Q(id=int(search_q)) | models.Q(preparation_order__intervention__id=int(search_q)) production_orders = production_orders.filter(q_filter).distinct() - production_orders = production_orders.order_by('created_at')[:200] + selected_order = request.GET.get('order', 'desc').strip() + if selected_order == 'asc': + production_orders = production_orders.order_by('created_at')[:200] + else: + selected_order = 'desc' + production_orders = production_orders.order_by('-created_at')[:200] return render(request, "stock/mobile/stock_production_orders_mobile.html", { 'production_orders': production_orders, @@ -552,6 +565,7 @@ def stock_production_orders_mobile(request): 'selected_status': selected_status, 'selected_warehouse': selected_warehouse, 'selected_destination': selected_destination, + 'selected_order': selected_order, 'status_choices': [ ('active', _("À traiter & En confection")), ] + list(ProductionOrder.STATUS_CHOICES), diff --git a/loko/stock/migrations/0004_alter_preparationorder_options_and_more.py b/loko/stock/migrations/0004_alter_preparationorder_options_and_more.py index 81c7695..0cedbe5 100644 --- a/loko/stock/migrations/0004_alter_preparationorder_options_and_more.py +++ b/loko/stock/migrations/0004_alter_preparationorder_options_and_more.py @@ -15,11 +15,11 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( name='preparationorder', - options={'ordering': ('date',), 'verbose_name': 'Bon de préparation', 'verbose_name_plural': 'Bons de préparation'}, + options={'ordering': ('-date',), 'verbose_name': 'Bon de préparation', 'verbose_name_plural': 'Bons de préparation'}, ), migrations.AlterModelOptions( name='productionorder', - options={'ordering': ('created_at',), 'verbose_name': 'Bon de confection', 'verbose_name_plural': 'Bons de confection'}, + options={'ordering': ('-created_at',), 'verbose_name': 'Bon de confection', 'verbose_name_plural': 'Bons de confection'}, ), migrations.AddField( model_name='stockmovementbatch', diff --git a/loko/stock/models.py b/loko/stock/models.py index 7eaf694..71f70d3 100644 --- a/loko/stock/models.py +++ b/loko/stock/models.py @@ -1451,7 +1451,7 @@ class PreparationOrder(models.Model): } class Meta: - ordering = ("date",) + ordering = ("-date",) verbose_name = _("Bon de préparation") verbose_name_plural = _("Bons de préparation") @@ -2248,7 +2248,7 @@ class ProductionOrder(models.Model): ) class Meta: - ordering = ("created_at",) + ordering = ("-created_at",) verbose_name = _("Bon de confection") verbose_name_plural = _("Bons de confection") diff --git a/loko/stock/templates/stock/mobile/stock_preparation_orders_mobile.html b/loko/stock/templates/stock/mobile/stock_preparation_orders_mobile.html index 4ed6225..539d10c 100644 --- a/loko/stock/templates/stock/mobile/stock_preparation_orders_mobile.html +++ b/loko/stock/templates/stock/mobile/stock_preparation_orders_mobile.html @@ -47,23 +47,29 @@ -
+
-
+
- {% if selected_status or selected_priority or search_q %} +
+ +
+ {% if selected_status or selected_priority or search_q or selected_order == 'asc' %}
-
+
-
+
{% if warehouses|length > 1 %} {% else %} {% endif %}
- {% if selected_status or selected_warehouse or selected_destination or search_q %} +
+ +
+ {% if selected_status or selected_warehouse or selected_destination or search_q or selected_order == 'asc' %}
{% translate "Effacer les filtres" %} @@ -98,34 +104,34 @@
- {% translate "Tous" %} ({{ prod_counts.total|default:0 }}) - {% translate "À traiter & En confection" %} ({{ prod_counts.active|default:0 }}) - {% translate "À traiter" %} ({{ prod_counts.to_process|default:0 }}) - {% translate "En confection" %} ({{ prod_counts.in_production|default:0 }}) - {% translate "Terminé" %} ({{ prod_counts.completed|default:0 }}) {% if prod_counts.draft %} - {% translate "Brouillon" %} ({{ prod_counts.draft|default:0 }}) {% endif %} {% if prod_counts.cancelled %} - {% translate "Annulé" %} ({{ prod_counts.cancelled|default:0 }}) diff --git a/loko/stock/templates/stock/stock_movements.html b/loko/stock/templates/stock/stock_movements.html index eaf4e30..d9702b5 100644 --- a/loko/stock/templates/stock/stock_movements.html +++ b/loko/stock/templates/stock/stock_movements.html @@ -61,7 +61,7 @@ -
+
@@ -69,7 +69,7 @@
-
+
@@ -92,10 +92,20 @@
+ +
+
+ + +
+
- {% if selected_status or selected_priority or search_q %} + {% if selected_status or selected_priority or search_q or prep_order == 'asc' %} {% translate "Effacer" %} @@ -114,23 +124,23 @@
{% translate "Vue rapide :" %} - {% translate "Tous" %} {{ prep_counts.total|default:0 }} - {% translate "À traiter & En attente" %} {{ prep_counts.active|default:0 }} - {% translate "À traiter" %} {{ prep_counts.to_process|default:0 }} - {% translate "En attente" %} {{ prep_counts.pending|default:0 }} - {% translate "Traité" %} {{ prep_counts.processed|default:0 }} @@ -236,10 +246,10 @@ -
+
- +
@@ -270,7 +280,7 @@
- + + + + +
+
+ +
+ {% if prod_status or prod_warehouse or prod_destination or prod_search_q or prod_order == 'asc' %} {% translate "Effacer" %} {% endif %} {% if can_create_production_order %} - {% translate "Nouveau bon" %} + {% translate "Nouveau" %} {% endif %}
@@ -299,34 +319,34 @@
{% translate "Vue rapide :" %} - {% translate "Tous" %} {{ prod_counts.total|default:0 }} - {% translate "À traiter & En confection" %} {{ prod_counts.active|default:0 }} - {% translate "À traiter" %} {{ prod_counts.to_process|default:0 }} - {% translate "En confection" %} {{ prod_counts.in_production|default:0 }} - {% translate "Terminé" %} {{ prod_counts.completed|default:0 }} {% if prod_counts.draft %} - {% translate "Brouillon" %} {{ prod_counts.draft|default:0 }} {% endif %} {% if prod_counts.cancelled %} - {% translate "Annulé" %} {{ prod_counts.cancelled|default:0 }} diff --git a/loko/stock/tests.py b/loko/stock/tests.py index 6a46cc9..5e53e10 100644 --- a/loko/stock/tests.py +++ b/loko/stock/tests.py @@ -575,29 +575,51 @@ class PreparationOrderPriorityTests(TestCase): prod1.refresh_from_db() prod2.refresh_from_db() - # 1. stock_movements page: check chronological (FIFO) order + # 1. stock_movements page: default is most recent first (descending) resp = self.client.get(reverse("stock:stock_movements") + "?tab=preparation-orders") self.assertEqual(resp.status_code, 200) prep_orders = list(resp.context["preparation_orders"]) - self.assertLess(prep_orders.index(po1), prep_orders.index(po2)) + self.assertLess(prep_orders.index(po2), prep_orders.index(po1)) resp_prod = self.client.get(reverse("stock:stock_movements") + f"?tab=production-orders&prod_warehouse={wh.id}") self.assertEqual(resp_prod.status_code, 200) prod_orders = list(resp_prod.context["production_orders"]) - self.assertLess(prod_orders.index(prod1), prod_orders.index(prod2)) + self.assertLess(prod_orders.index(prod2), prod_orders.index(prod1)) - # 2. Mobile pages: check chronological order + # Inverted sort option (ascending / oldest first) + resp_inv = self.client.get(reverse("stock:stock_movements") + "?tab=preparation-orders&prep_order=asc") + self.assertEqual(resp_inv.status_code, 200) + prep_orders_inv = list(resp_inv.context["preparation_orders"]) + self.assertLess(prep_orders_inv.index(po1), prep_orders_inv.index(po2)) + + resp_prod_inv = self.client.get(reverse("stock:stock_movements") + f"?tab=production-orders&prod_warehouse={wh.id}&prod_order=asc") + self.assertEqual(resp_prod_inv.status_code, 200) + prod_orders_inv = list(resp_prod_inv.context["production_orders"]) + self.assertLess(prod_orders_inv.index(prod1), prod_orders_inv.index(prod2)) + + # 2. Mobile pages: default is most recent first (descending) resp_m_prep = self.client.get(reverse("mobile:stock_preparation_orders_mobile")) self.assertEqual(resp_m_prep.status_code, 200) m_prep_orders = list(resp_m_prep.context["preparation_orders"]) - self.assertLess(m_prep_orders.index(po1), m_prep_orders.index(po2)) + self.assertLess(m_prep_orders.index(po2), m_prep_orders.index(po1)) resp_m_prod = self.client.get(reverse("mobile:stock_production_orders_mobile")) self.assertEqual(resp_m_prod.status_code, 200) m_prod_orders = list(resp_m_prod.context["production_orders"]) - self.assertLess(m_prod_orders.index(prod1), m_prod_orders.index(prod2)) + self.assertLess(m_prod_orders.index(prod2), m_prod_orders.index(prod1)) - # 3. Home widget + # Mobile pages: inverted sort option (ascending / oldest first) + resp_m_prep_inv = self.client.get(reverse("mobile:stock_preparation_orders_mobile") + "?order=asc") + self.assertEqual(resp_m_prep_inv.status_code, 200) + m_prep_orders_inv = list(resp_m_prep_inv.context["preparation_orders"]) + self.assertLess(m_prep_orders_inv.index(po1), m_prep_orders_inv.index(po2)) + + resp_m_prod_inv = self.client.get(reverse("mobile:stock_production_orders_mobile") + "?order=asc") + self.assertEqual(resp_m_prod_inv.status_code, 200) + m_prod_orders_inv = list(resp_m_prod_inv.context["production_orders"]) + self.assertLess(m_prod_orders_inv.index(prod1), m_prod_orders_inv.index(prod2)) + + # 3. Home shortcut widgets: default is oldest first (FIFO) resp_home = self.client.get(reverse("home:index")) self.assertEqual(resp_home.status_code, 200) home_preps = list(resp_home.context["preparation_order_to_process_list"]) diff --git a/loko/stock/views.py b/loko/stock/views.py index 44836f0..68d4dda 100644 --- a/loko/stock/views.py +++ b/loko/stock/views.py @@ -594,6 +594,7 @@ def stock_movements(request): selected_status = request.GET.get('prep_status', '').strip() or (request.GET.get('status', '').strip() if tab != 'production-orders' else '') selected_priority = request.GET.get('priority', '').strip() search_q = request.GET.get('prep_q', '').strip() or (request.GET.get('q', '').strip() if tab != 'production-orders' else '') + prep_order = request.GET.get('prep_order', '').strip() or (request.GET.get('order', '').strip() if tab != 'production-orders' else '') prep_counts = PreparationOrder.objects.aggregate( total=models.Count('id'), @@ -622,7 +623,11 @@ def stock_movements(request): if search_q.isdigit(): q_filter |= models.Q(intervention__id=int(search_q)) preparation_orders = preparation_orders.filter(q_filter) - preparation_orders = preparation_orders.order_by("date")[:1000] + if prep_order == 'asc': + preparation_orders = preparation_orders.order_by("date")[:1000] + else: + prep_order = 'desc' + preparation_orders = preparation_orders.order_by("-date")[:1000] # Filtrer selon les entrepôts accessibles accessible_warehouses = get_user_accessible_warehouses(request.user) @@ -632,6 +637,7 @@ def stock_movements(request): prod_search_q = request.GET.get('prod_q', '').strip() or (request.GET.get('q', '').strip() if tab == 'production-orders' else '') prod_warehouse = request.GET.get('prod_warehouse', '').strip() or (request.GET.get('warehouse', '').strip() if tab == 'production-orders' else '') prod_destination = request.GET.get('prod_destination', '').strip() or (request.GET.get('destination', '').strip() if tab == 'production-orders' else '') + prod_order = request.GET.get('prod_order', '').strip() or (request.GET.get('order', '').strip() if tab == 'production-orders' else '') prod_base_qs = ProductionOrder.objects.filter(warehouse__in=accessible_warehouses) @@ -681,7 +687,11 @@ def stock_movements(request): prod_q_filter |= models.Q(id=int(prod_search_q)) | models.Q(preparation_order__intervention__id=int(prod_search_q)) production_orders = production_orders.filter(prod_q_filter).distinct() - production_orders = production_orders.order_by("created_at")[:1000] + if prod_order == 'asc': + production_orders = production_orders.order_by("created_at")[:1000] + else: + prod_order = 'desc' + production_orders = production_orders.order_by("-created_at")[:1000] movements = StockMovement.objects.filter( models.Q(source_location__warehouse__id__in=accessible_warehouses) | @@ -771,10 +781,12 @@ def stock_movements(request): "selected_status": selected_status, "selected_priority": selected_priority, "search_q": search_q, + "prep_order": prep_order, "prod_status": prod_status, "prod_search_q": prod_search_q, "prod_warehouse": prod_warehouse, "prod_destination": prod_destination, + "prod_order": prod_order, "prod_status_choices": [ ('active', _("À traiter & En confection")), ] + list(ProductionOrder.STATUS_CHOICES),