feat: add external destination badges and indigo styling to stock and production order templates

This commit is contained in:
kdeterme 2026-10-05 09:09:43 +02:00
parent 9764b525bb
commit 1d212194ad
12 changed files with 93 additions and 20 deletions

View file

@ -572,3 +572,12 @@ label,
.text-status-invoiced { color: #738f7a !important; }
.text-status-closed { color: #09425f !important; }
.text-status-canceled { color: #cfd8dc !important; }
/* Badge & utilitaire Indigo (destinations externes, tiers, partenaires) */
.badge-indigo {
background-color: #6610f2 !important;
color: #ffffff !important;
}
.bg-indigo {
background-color: #6610f2 !important;
}

View file

@ -19,6 +19,13 @@
:root {
--brand-color: #0f172a;
}
.badge-indigo {
background-color: #6610f2 !important;
color: #ffffff !important;
}
.bg-indigo {
background-color: #6610f2 !important;
}
body {
padding-top: 4.5rem;
padding-bottom: 3.5rem;

View file

@ -2441,6 +2441,11 @@ class ProductionOrder(models.Model):
verbose_name = _("Bon de confection")
verbose_name_plural = _("Bons de confection")
@property
def is_external(self):
"""Retourne True si le bon de confection est destiné à l'usage externe."""
return self.destination == self.DESTINATION_EXTERNAL
@property
def is_reopened(self):
"""Retourne True si le bon a été réouvert et est actuellement en cours ou à traiter."""

View file

@ -365,8 +365,13 @@
{% if item_data.production_order %}
<div class="mt-2">
<a href="{% url 'mobile:stock_production_order_detail_mobile' item_data.production_order.pk %}"
class="btn btn-sm btn-outline-secondary py-0 px-2" style="font-size:0.78rem;">
class="btn btn-sm btn-outline-secondary py-0 px-2 d-inline-flex align-items-center" style="font-size:0.78rem;">
<i class="bi bi-tools me-1"></i>{{ item_data.production_order.code }}
{% if item_data.production_order.destination == 'external' %}
<span class="badge text-white ms-1" style="background-color: #6610f2; font-size:0.65rem;" title="{% translate 'Destination externe' %}">
<i class="bi bi-truck me-1"></i>{% translate "Externe" %}
</span>
{% endif %}
<span class="badge bg-light text-dark ms-1" style="font-size:0.7rem;">{{ item_data.production_order.get_status_display }}</span>
</a>
</div>
@ -406,8 +411,13 @@
{% if oi_data.production_order %}
<div class="mt-2">
<a href="{% url 'mobile:stock_production_order_detail_mobile' oi_data.production_order.pk %}"
class="btn btn-sm btn-outline-secondary py-0 px-2" style="font-size:0.78rem;">
class="btn btn-sm btn-outline-secondary py-0 px-2 d-inline-flex align-items-center" style="font-size:0.78rem;">
<i class="bi bi-tools me-1"></i>{{ oi_data.production_order.code }}
{% if oi_data.production_order.destination == 'external' %}
<span class="badge text-white ms-1" style="background-color: #6610f2; font-size:0.65rem;" title="{% translate 'Destination externe' %}">
<i class="bi bi-truck me-1"></i>{% translate "Externe" %}
</span>
{% endif %}
<span class="badge bg-light text-dark ms-1" style="font-size:0.7rem;">{{ oi_data.production_order.get_status_display }}</span>
</a>
</div>

View file

@ -47,7 +47,14 @@
<!-- En-tête statut -->
<div class="d-flex justify-content-between align-items-center mb-3">
<div>
<h5 class="mb-0 fw-bold">{{ order.code }}</h5>
<h5 class="mb-0 fw-bold d-flex align-items-center gap-2 flex-wrap">
{{ order.code }}
{% if order.destination == 'external' %}
<span class="badge text-white shadow-sm" style="background-color: #6610f2; font-size: 0.75rem;">
<i class="bi bi-truck me-1"></i>{% translate "Externe" %}
</span>
{% endif %}
</h5>
<small class="text-muted"><i class="bi bi-calendar3 me-1"></i>{{ order.created_at|date:"d/m/Y H:i" }}</small>
</div>
<div class="d-flex align-items-center gap-1">
@ -94,9 +101,9 @@
<span class="info-label"><i class="bi bi-arrow-left-right me-1"></i>{% translate "Destination" %}</span>
<span>
{% if order.destination == 'internal' %}
<span class="badge bg-info text-dark"><i class="bi bi-building me-1"></i>{% translate "Interne" %}</span>
<span class="badge bg-light text-secondary border"><i class="bi bi-house me-1"></i>{% translate "Interne" %}</span>
{% else %}
<span class="badge bg-warning text-dark"><i class="bi bi-truck me-1"></i>{% translate "Externe" %}</span>
<span class="badge text-white shadow-sm" style="background-color: #6610f2;"><i class="bi bi-truck me-1"></i>{% translate "Externe" %}</span>
{% endif %}
</span>
</div>

View file

@ -144,8 +144,13 @@
<a href="{% url 'mobile:stock_production_order_detail_mobile' order.pk %}" class="list-card"
style="border-left: 4px solid {% if order.status == 'to_process' %}#dc3545{% elif order.status == 'in_production' %}#0d6efd{% elif order.status == 'completed' %}#198754{% elif order.status == 'cancelled' %}#6c757d{% else %}#6c757d{% endif %} !important;">
<div class="d-flex justify-content-between align-items-start">
<div class="list-card-title text-primary">
<div class="list-card-title text-primary d-flex align-items-center gap-1 flex-wrap">
{{ order.code|default:order.id }}
{% if order.destination == 'external' %}
<span class="badge text-white shadow-sm" style="background-color: #6610f2; font-size: 0.72rem;">
<i class="bi bi-truck me-1"></i>{% translate "Externe" %}
</span>
{% endif %}
</div>
<div class="d-flex flex-column align-items-end gap-1">
<span class="badge {{ order.status_badge_class }}">
@ -155,10 +160,6 @@
<span class="badge bg-light text-secondary border" style="font-size: 0.7rem;">
<i class="bi bi-house me-1"></i>{% translate "Interne" %}
</span>
{% else %}
<span class="badge bg-light text-info border" style="font-size: 0.7rem;">
<i class="bi bi-box-arrow-up-right me-1"></i>{% translate "Externe" %}
</span>
{% endif %}
</div>
</div>

View file

@ -436,6 +436,11 @@
class="btn btn-sm {% if item_data.production_order.status == 'completed' %}btn-outline-success{% elif item_data.production_order.status == 'in_production' %}btn-outline-primary{% elif item_data.production_order.status == 'cancelled' %}btn-outline-danger{% elif item_data.production_order.status == 'draft' %}btn-outline-secondary{% else %}btn-outline-warning{% endif %}"
title="{{ item_data.production_order.get_status_display }}">
<i class="bi {% if item_data.production_order.status == 'completed' %}bi-check-circle{% elif item_data.production_order.status == 'in_production' %}bi-gear{% elif item_data.production_order.status == 'cancelled' %}bi-x-circle{% else %}bi-eye{% endif %}"></i> {{ item_data.production_order.code }}
{% if item_data.production_order.destination == 'external' %}
<span class="badge text-white ms-1" style="background-color: #6610f2; font-size: 0.65rem;" title="{% translate 'Destination externe' %}">
<i class="bi bi-truck"></i>
</span>
{% endif %}
</a>
{% elif can_manage and preparation_order.status != 'processed' and preparation_order.status != 'cancelled' %}
<a href="{% url 'stock:production_order_create' %}?preparation_order={{ preparation_order.pk }}&prep_item={{ item_data.item.pk }}" class="btn btn-sm btn-outline-success" title="{% translate 'Créer un bon de confection' %}">
@ -560,6 +565,11 @@
class="btn btn-sm {% if oi_data.production_order.status == 'completed' %}btn-outline-success{% elif oi_data.production_order.status == 'in_production' %}btn-outline-primary{% elif oi_data.production_order.status == 'cancelled' %}btn-outline-danger{% elif oi_data.production_order.status == 'draft' %}btn-outline-secondary{% else %}btn-outline-warning{% endif %}"
title="{{ oi_data.production_order.get_status_display }}">
<i class="bi {% if oi_data.production_order.status == 'completed' %}bi-check-circle{% elif oi_data.production_order.status == 'in_production' %}bi-gear{% elif oi_data.production_order.status == 'cancelled' %}bi-x-circle{% else %}bi-eye{% endif %}"></i> {{ oi_data.production_order.code }}
{% if oi_data.production_order.destination == 'external' %}
<span class="badge text-white ms-1" style="background-color: #6610f2; font-size: 0.65rem;" title="{% translate 'Destination externe' %}">
<i class="bi bi-truck"></i>
</span>
{% endif %}
</a>
{% else %}
<a href="{% url 'stock:production_order_create' %}?other_item={{ oi_data.item.pk }}&preparation_order={{ preparation_order.pk }}"

View file

@ -66,6 +66,11 @@
<a href="{% url 'stock:production_order_detail' order.pk %}">
<strong>{{ order.code }}</strong>
</a>
{% if order.destination == 'external' %}
<span class="badge text-white ms-1 shadow-sm" style="background-color: #6610f2; font-size: 0.72rem;">
<i class="bi bi-truck me-1"></i>{% translate "Externe" %}
</span>
{% endif %}
</td>
<td>{{ order.warehouse.name }}</td>
<td class="text-center">{{ order.quantity }}</td>

View file

@ -10,9 +10,13 @@
<!-- En-tête -->
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h3>
<i class="bi bi-tools"></i>
{% translate "Bon de confection" %} {{ order.code }}
<h3 class="d-flex align-items-center gap-2 flex-wrap">
<span><i class="bi bi-tools"></i> {% translate "Bon de confection" %} {{ order.code }}</span>
{% if order.destination == 'external' %}
<span class="badge text-white fs-6 shadow-sm" style="background-color: #6610f2;">
<i class="bi bi-truck me-1"></i>{% translate "Externe" %}
</span>
{% endif %}
</h3>
<p class="text-muted mb-0">
<i class="bi bi-calendar"></i> {{ order.created_at|date:"d/m/Y H:i" }}
@ -123,11 +127,11 @@
<th>{% translate "Destination" %}</th>
<td>
{% if order.destination == 'internal' %}
<span class="badge bg-info text-dark">
<i class="bi bi-building me-1"></i>{% translate "Interne" %}
<span class="badge bg-light text-secondary border">
<i class="bi bi-house me-1"></i>{% translate "Interne" %}
</span>
{% else %}
<span class="badge bg-warning text-dark">
<span class="badge text-white shadow-sm" style="background-color: #6610f2;">
<i class="bi bi-truck me-1"></i>{% translate "Externe" %}
</span>
{% endif %}

View file

@ -1,4 +1,4 @@
{% extends "base.html" %}
{% extends "base.html" %}
{% load static %}
{% load i18n %}
@ -69,6 +69,11 @@
<a href="{% url 'stock:production_order_detail' order.pk %}">
<strong>{{ order.code }}</strong>
</a>
{% if order.destination == 'external' %}
<span class="badge text-white ms-1 shadow-sm" style="background-color: #6610f2; font-size: 0.72rem;">
<i class="bi bi-truck me-1"></i>{% translate "Externe" %}
</span>
{% endif %}
</td>
<td>
<a href="{% url 'stock:product_design_detail' order.product_design.pk %}">

View file

@ -374,14 +374,18 @@
{{ order.code|default:order.pk }}
</a>
{% if order.destination == 'external' %}
<span class="badge text-white shadow-sm" style="background-color: #6610f2; font-size: 0.8rem; letter-spacing: 0.3px;">
<i class="bi bi-truck me-1"></i>{% translate "Externe" %}
</span>
{% endif %}
<span class="badge {{ order.status_badge_class }}">
<i class="bi {{ order.status_icon }} me-1"></i>{{ order.get_status_display }}
</span>
{% if order.destination == 'internal' %}
<span class="badge bg-light text-secondary border"><i class="bi bi-house me-1"></i>{% translate "Interne" %}</span>
{% else %}
<span class="badge bg-light text-info border"><i class="bi bi-box-arrow-up-right me-1"></i>{% translate "Externe" %}</span>
{% endif %}
{% if order.preparation_order %}

View file

@ -530,11 +530,17 @@ class PreparationOrderPriorityTests(TestCase):
self.assertIn(order1, list(response.context["production_orders"]))
self.assertNotIn(order2, list(response.context["production_orders"]))
# Property is_external
self.assertTrue(order2.is_external)
self.assertFalse(order1.is_external)
# Search filter
response = self.client.get(reverse("mobile:stock_production_orders_mobile") + "?q=Potelet")
self.assertEqual(response.status_code, 200)
self.assertIn(order2, list(response.context["production_orders"]))
self.assertNotIn(order1, list(response.context["production_orders"]))
self.assertContains(response, "#6610f2")
self.assertContains(response, "bi-truck")
def test_production_order_display_output_product_name(self):
from .models import ProductionOrder, Warehouse, Product