diff --git a/loko/interventions/templates/interventions/intervention_detail_mobile.html b/loko/interventions/templates/interventions/intervention_detail_mobile.html index 1eb9b52..691f8a2 100644 --- a/loko/interventions/templates/interventions/intervention_detail_mobile.html +++ b/loko/interventions/templates/interventions/intervention_detail_mobile.html @@ -1057,6 +1057,99 @@ {% endif %} + +{% if can_create_preparation_order or preparation_orders %} +
+
+ + {% translate "Stock" %} + +
+ {% if preparation_orders %} + + {{ preparation_orders|length }} + + {% endif %} + {% if can_create_preparation_order %} + + + + {% endif %} +
+
+
+ {% if preparation_orders %} +
+ {% for order in preparation_orders %} +
+
+
+
+ + #{{ order.order_number }} + + + {{ order.get_status_display }} + + + {{ order.get_priority_display }} + + {% if order.is_loan %} + + {% translate "Prêt" %} + + {% endif %} +
+
+ {{ order.date|date:"d/m/Y H:i" }} +
+ {% with items=order.preparationorderitem_set.all other_items=order.other_items.all %} + {% if items or other_items %} +
+ {% for item in items|slice:":3" %} + + {{ item.product.name }} × {{ item.quantity }} + + {% endfor %} + {% for item in other_items|slice:":2" %} + + {{ item.name }} × {{ item.quantity }} + + {% endfor %} + {% with total_count=items.count|add:other_items.count %} + {% if total_count > 3 %} + + +{{ total_count|add:"-3" }} + + {% endif %} + {% endwith %} +
+ {% else %} + {% translate "Aucun article" %} + {% endif %} + {% endwith %} +
+ + + +
+
+ {% endfor %} +
+ {% else %} +

+ {% translate "Aucun bon de préparation créé pour cette intervention." %} +

+ {% endif %} +
+
+{% endif %} + + {% if intervention.status != 'in_preparation' %} diff --git a/loko/interventions/views/mobile.py b/loko/interventions/views/mobile.py index 4bc9599..81d9b88 100644 --- a/loko/interventions/views/mobile.py +++ b/loko/interventions/views/mobile.py @@ -1073,10 +1073,25 @@ def intervention_detail_mobile(request, intervention_id): except Exception: pass + can_create_preparation_order = bool( + user_config and ( + user_config.has_role('admin') + or (can_edit_mobile and user_config.can_manage_preparation_orders_any()) + ) + ) + preparation_orders = ( + intervention.preparation_orders.all() + .prefetch_related('preparationorderitem_set__product', 'other_items') + .order_by('-date') + if hasattr(intervention, 'preparation_orders') else [] + ) + sequenced_data = get_sequenced_intervention_documents(intervention, notes_qs=notes) context = { 'intervention': intervention, + 'can_create_preparation_order': can_create_preparation_order, + 'preparation_orders': preparation_orders, 'sequenced_blocks': sequenced_data['blocks'], 'document_blocks': sequenced_data['blocks'], 'all_sequenced_documents': sequenced_data['all_documents'], diff --git a/loko/mobile/tests.py b/loko/mobile/tests.py index 127e2ae..8fd6267 100644 --- a/loko/mobile/tests.py +++ b/loko/mobile/tests.py @@ -103,3 +103,73 @@ class MobileStockPermissionTests(TestCase): stock_response = self.client.get(reverse("mobile:stock_index_mobile")) self.assertEqual(stock_response.status_code, 200) + +class MobileInterventionDetailStockTests(TestCase): + def setUp(self): + from stock.models import PreparationOrder, PreparationOrderItem, Product, ProductCategory + from interventions.models import Intervention + + self.user = User.objects.create_user(username="detailstockuser", password="password") + self.client.login(username="detailstockuser", password="password") + self.user_config = UserConfig.objects.create(user=self.user, is_intern=True) + self.admin_role, _ = Role.objects.get_or_create(name="admin") + self.user_config.roles.add(self.admin_role) + + self.thematic, _ = Thematic.objects.get_or_create(code="trafficlights", defaults={"name_fr": "Feux", "name_nl": "Verkeerslichten"}) + self.user_config.default_thematic = self.thematic + self.user_config.save() + + self.intervention = Intervention.objects.create( + title="Intervention Test Stock", + status="in_progress", + thematic=self.thematic, + ) + + self.category, _ = ProductCategory.objects.get_or_create(code="SIG", defaults={"name_fr": "Signalisation"}) + self.product = Product.objects.create( + name="Poteau feux", + code="POT-01", + category=self.category, + ) + + self.prep_order = PreparationOrder.objects.create( + order_number="BP-TEST-001", + intervention=self.intervention, + status="to_process", + priority="2", + ) + PreparationOrderItem.objects.create( + preparation_order=self.prep_order, + product=self.product, + quantity=3, + ) + + def test_stock_section_in_mobile_intervention_detail(self): + url = reverse("mobile:intervention_detail_mobile", args=[self.intervention.id]) + response = self.client.get(url) + + self.assertEqual(response.status_code, 200) + self.assertIn("can_create_preparation_order", response.context) + self.assertTrue(response.context["can_create_preparation_order"]) + self.assertIn("preparation_orders", response.context) + self.assertEqual(len(response.context["preparation_orders"]), 1) + + content = response.content.decode("utf-8") + self.assertIn("BP-TEST-001", content) + self.assertIn("Poteau feux", content) + self.assertIn("section-stock", content) + + def test_stock_section_without_create_rights(self): + # Non-admin user without preparation order management rights + self.user_config.roles.remove(self.admin_role) + observer_role, _ = Role.objects.get_or_create(name="observer") + self.user_config.roles.add(observer_role) + + url = reverse("mobile:intervention_detail_mobile", args=[self.intervention.id]) + response = self.client.get(url) + + self.assertEqual(response.status_code, 200) + self.assertFalse(response.context["can_create_preparation_order"]) + self.assertEqual(len(response.context["preparation_orders"]), 1) + + diff --git a/loko/stock/templates/stock/preparation_order_add.html b/loko/stock/templates/stock/preparation_order_add.html index 98c3a92..a006d68 100644 --- a/loko/stock/templates/stock/preparation_order_add.html +++ b/loko/stock/templates/stock/preparation_order_add.html @@ -11,6 +11,7 @@
{% csrf_token %} + {% if variant %}{% endif %}
{{ form.non_field_errors }} @@ -262,9 +263,15 @@
{% if from_intervention %} - - {% translate "Retour à l'intervention" %} - + {% if variant == 'mobile' %} + + {% translate "Retour à l'intervention" %} + + {% else %} + + {% translate "Retour à l'intervention" %} + + {% endif %} {% else %} {% translate "Retour" %} diff --git a/loko/stock/views.py b/loko/stock/views.py index d0c910c..8f6b063 100644 --- a/loko/stock/views.py +++ b/loko/stock/views.py @@ -3562,12 +3562,15 @@ def new_preparation_order_from_intervention(request, intervention_id): from interventions.permissions import can_edit_intervention from common.models import UserConfig + variant = request.GET.get('v') or request.POST.get('v') + redirect_target = "mobile:intervention_detail_mobile" if variant == 'mobile' else "interventions:intervention_detail" + # Vérifier les permissions try: user_config = request.user.config except UserConfig.DoesNotExist: messages.error(request, _("Configuration utilisateur non trouvée.")) - return redirect("interventions:intervention_detail", intervention_id=intervention_id) + return redirect(redirect_target, intervention_id=intervention_id) intervention = get_object_or_404(Intervention, pk=intervention_id) @@ -3581,7 +3584,7 @@ def new_preparation_order_from_intervention(request, intervention_id): if not can_create_from_intervention: messages.error(request, _("Vous n'avez pas la permission de créer des bons de préparation.")) - return redirect("interventions:intervention_detail", intervention_id=intervention_id) + return redirect(redirect_target, intervention_id=intervention_id) preparation_order_item_formset = inlineformset_factory( PreparationOrder, PreparationOrderItem, form=PreparationOrderItemForm, extra=3, can_delete=True @@ -3609,7 +3612,7 @@ def new_preparation_order_from_intervention(request, intervention_id): ) messages.success(request, _("Bon de préparation créé avec succès.")) - return redirect("interventions:intervention_detail", intervention_id=intervention_id) + return redirect(redirect_target, intervention_id=intervention_id) else: # Générer un numéro de bon automatique import datetime @@ -3637,6 +3640,7 @@ def new_preparation_order_from_intervention(request, intervention_id): "from_intervention": True, "categories": categories, "signalisation_category_ids": signalisation_ids, + "variant": variant, }, )