Codifarticle AJAX with jQuery example

articles.urls.py

from .views_codif_article import view_update_codifarticle


path(
    "ajax/codif_article_update",
    view_update_codifarticle,
    name="ajax_update_codif_article",
),

views.view_update_codifarticle

  1 import logging
  2 from typing import Any, Dict
  3 from datetime import datetime
  4 from django.utils import timezone
  5
  6 from django.contrib import messages
  7
  8 from django.contrib.auth.mixins import LoginRequiredMixin
  9 from django.contrib.auth.decorators import login_required
 10
 11 from django.http.request import HttpRequest
 12 from django.http import HttpResponseRedirect, JsonResponse
 13 from django.apps import apps
 14 from django.forms.models import modelform_factory
 15 from django.http import HttpResponseRedirect
 16 from django.shortcuts import get_object_or_404, redirect
 17 from django.urls import reverse
 18 from django.views.generic.base import TemplateResponseMixin, View
 19 from django.views.generic.edit import DeleteView, UpdateView
 20
 21 from employes.models import Employe
 22
 23 from .forms_codif_article import CodifArticleFormSetExtra0, CodifArticleFormSetExtra1
 24 from .forms_demande_article import DemandeArticleUpdateFormInLine
 25 from .models_codif_article import CodifArticle, DocCodifArticle, ReponseCodifArticle
 26 from .models_demande_article import DemandeArticle
 27
 28 from projets.models import Projet
 29 from articles.models import Article
 30 from fabricants.models import Fabricant
 31 from fournisseurs.models import Fournisseur
 32
 33
 34 # Get an instance of a logger
 35 logger = logging.getLogger(__name__)
 36
 37
 38 def view_update_codifarticle(request: HttpRequest) -> JsonResponse:
 39     """Mise à jour des codifications article par requete AJAX.
 40     """
 41     logger.info("Enter view_update_codifarticle()")
 42
 43     codif_article_id = request.GET.get("id", None)
 44     logger.info(f"{codif_article_id=}")
 45
 46     try:
 47         codif_article = CodifArticle.objects.get(pk=codif_article_id)
 48         if codif_article.demande_cloturee():
 49             data = {}
 50             data["update"] = False
 51             logger.info(f"No change authorized")
 52             return JsonResponse(data)
 53         else:
 54             logger.info(f"Demande non cloturée {codif_article.demande_article}")
 55
 56     except:
 57         pass
 58
 59
 60     etat_poste = request.GET.get("etat_poste", None)
 61     reponse = request.GET.get("reponse", None)
 62     ofda = request.GET.get("ofda", None)
 63
 64     projet = request.GET.get("projet_id", None)
 65     if projet is not None:
 66         try:
 67             projet = Projet.objects.get(pk=projet)
 68         except Exception as error:
 69             logger.error(f"view_update_codifarticle {error=}")
 70
 71     article = request.GET.get("article_id", None)
 72     if article is not None:
 73         try:
 74             article = Article.objects.get(pk=article)
 75         except Exception as error:
 76             logger.error(f"view_update_sortie_stock {error=}")
 77
 78     designation = request.GET.get("designation", None)
 79     fabricant = request.GET.get("fabricant_id", None)
 80     if fabricant is not None:
 81         try:
 82             fabricant = Fabricant.objects.get(pk=fabricant)
 83         except Exception as error:
 84             logger.error(f"view_update_codifarticle {error=}")
 85
 86     ref_fabricant = request.GET.get("ref_fabricant", None)
 87     fournisseur = request.GET.get("fournisseur_id", None)
 88     if fournisseur is not None:
 89         try:
 90             fournisseur = Fournisseur.objects.get(pk=fournisseur)
 91         except Exception as error:
 92             logger.error(f"view_update_codifarticle {error=}")
 93
 94     ref_fournisseur = request.GET.get("ref_fournisseur", None)
 95     date_butoir = None
 96     try:
 97         date_butoir_str = request.GET.get("date_butoir", None)
 98         format_str = "%d/%m/%Y %H:%M"
 99         date_butoir_unaware = datetime.strptime(
100             date_butoir_str, format_str
101         )
102         date_butoir = timezone.make_aware(
103             date_butoir_unaware, timezone.get_current_timezone()
104         )
105         logger.info(f"{date_butoir_str=} {date_butoir=}")
106     except Exception as error:
107         # logger.error(f"view_update_sortie_stock {error=}")
108         pass
109
110
111     demande_codification = request.GET.get("demande_codification", None)
112     if demande_codification is not None:
113         logger.info(f"{demande_codification=}")
114         if demande_codification == "true":
115             demande_codification = True
116         else:
117             demande_codification = False
118
119     besoin_reel = request.GET.get("besoin_reel", None)
120     besoin_potentiel = request.GET.get("besoin_potentiel", None)
121     sortie_stock = request.GET.get("sortie_stock", None)
122     cotation_par = request.GET.get("cotation_par", None)
123
124     data = {}
125     data["update"] = False
126     try:
127         save = False
128         msg = ""
129         if etat_poste is not None:
130             logger.info(f"{etat_poste=}")
131             codif_article.etat_poste = etat_poste
132             msg = f"new etat_poste:{etat_poste}"
133             save = True
134
135         if reponse is not None:
136             logger.info(f"{reponse=}")
137             codif_article.reponse = reponse
138             msg = f"new reponse:{reponse}"
139             save = True
140
141         if ofda is not None:
142             logger.info(f"{ofda=}")
143             codif_article.ofda = ofda
144             msg = f"new ofda:{ofda}"
145             save = True
146
147         if article is not None:
148             codif_article.article = article
149             msg = f"new article:{article}"
150             save = True
151
152         if projet is not None:
153             codif_article.projet = projet
154             msg = f"new projet:{projet}"
155             save = True
156
157         if designation is not None:
158             codif_article.designation = designation
159             msg = f"new designation:{designation}"
160             save = True
161
162         if fabricant is not None:
163             codif_article.fabricant = fabricant
164             msg = f"new fabricant:{fabricant}"
165             save = True
166
167         if ref_fabricant is not None:
168             codif_article.ref_fabricant = ref_fabricant
169             msg = f"new ref_fabricant:{ref_fabricant}"
170             save = True
171
172         if fournisseur is not None:
173             codif_article.fournisseur = fournisseur
174             msg = f"new fournisseur:{fournisseur}"
175             save = True
176
177         if ref_fournisseur is not None:
178             codif_article.ref_fournisseur = ref_fournisseur
179             msg = f"new ref_fournisseur:{ref_fournisseur}"
180             save = True
181
182         if date_butoir is not None:
183             codif_article.date_butoir = date_butoir
184             msg = f"new date_butoir:{date_butoir}"
185             save = True
186
187         if demande_codification is not None:
188             # logger.info(f"{demande_codification=}")
189             codif_article.demande_codification = demande_codification
190             msg = f"new demande_codification:{demande_codification}"
191             save = True
192
193         if besoin_reel is not None:
194             codif_article.besoin_reel = besoin_reel
195             msg = f"new besoin_reel:{besoin_reel}"
196             save = True
197
198         if besoin_potentiel is not None:
199             logger.info(f"{besoin_potentiel=}")
200             codif_article.besoin_potentiel = besoin_potentiel
201             msg = f"new besoin_potentiel:{besoin_potentiel}"
202             save = True
203
204         if sortie_stock is not None:
205             logger.info(f"{sortie_stock=}")
206             codif_article.sortie_stock = sortie_stock
207             msg = f"new sortie_stock:{sortie_stock}"
208             save = True
209
210         if cotation_par is not None:
211             logger.info(f"{cotation_par=}")
212             codif_article.cotation_par = cotation_par
213             msg = f"new cotation_par:{cotation_par}"
214             save = True
215
216         if save:
217             codif_article.save()
218             data["update"] = msg
219             # retour data
220             if article is not None:
221                 data["libelle_article"] = article.get_libelle()
222             if projet is not None:
223                 data["libelle_projet"] = projet.get_libelle()
224
225     except Exception as error:
226         logger.error(f"view_update_codifarticle {error=}")
227
228     return JsonResponse(data)

articles.templates.articles.demande.achat_service.articles_update.html

  1{% extends "base.html" %}
  2{% load static %}
  3{% load djmoney %}
  4{% load article %}
  5
  6{% block stylesheet %}
  7    <link rel="stylesheet" href="{% static 'css/couleurs_demande_article.css' %}">
  8
  9    <!-- CSS pour datetime picker -->
 10    <link rel="stylesheet" href="{% static 'js/jquery.datetimepicker.min.css' %}">
 11
 12    <!-- CSS pour autocomplete_light -->
 13    <link rel="stylesheet" href="{% static 'select2/css/select2.css' %}">
 14    <link rel="stylesheet" href="{% static 'autocomplete_light/select2.css' %}">
 15
 16    <!-- Bordure des tables -->
 17    <link rel="stylesheet" href="{% static 'css/table.css' %}">
 18{% endblock  %}
 19
 20
 21{% block javascript %}
 22
 23    {# a employer dans les templates fils->{{ block.super }} #}
 24    {{ block.super }}
 25    <script src="{% static 'js/jquery.datetimepicker.full.js' %}"></script>
 26
 27    <script src="{% static 'autocomplete_light/jquery.init.js' %}"></script>
 28    <script src="{% static 'autocomplete_light/autocomplete.init.js' %}"></script>
 29    <script src="{% static 'select2/js/select2.full.js' %}"></script>
 30    <script src="{% static 'autocomplete_light/forward.js' %}"></script>
 31    <script src="{% static 'autocomplete_light/select2.js' %}"></script>
 32
 33
 34{% endblock javascript %}
 35
 36
 37
 38{% block extra_js %}
 39{# Code composé de Javascript et de Django Template Language #}
 40{# ========================================================= #}
 41
 42<script type="text/javascript">
 43
 44{% comment %}
 45https://learn.jquery.com/using-jquery-core/document-ready/
 46
 47Experienced developers sometimes use the shorthand $() for $( document ).ready().
 48If you are writing code that people who aren't experienced with jQuery may see,
 49it's best to use the long form.
 50
 51{% endcomment %}
 52
 53$(document).ready(function() {
 54
 55    // langue française pour les datetime pickers
 56    $.datetimepicker.setLocale('fr');
 57
 58    {% for form_achat in formset_achats %}
 59        $('#id_achatservice_related-{{ forloop.counter0 }}-etat_poste').change(function () {
 60            let etat_poste = $(this).val()
 61            let achatservice_id = $('#id_achatservice_related-{{ forloop.counter0 }}-id').val();
 62            let url = '{% url "articles:ajax_update_achat_service" %}';
 63            $.ajax(
 64                    {
 65                        url: url,
 66                        data: {
 67                            'id': achatservice_id,
 68                            'etat_poste': etat_poste,
 69                        },
 70                        dataType: 'json',
 71                        success: function (data) {
 72                            // alert("Retour:" + data.update);
 73                        }
 74                }
 75            );
 76        });
 77        $('#id_achatservice_related-{{ forloop.counter0 }}-reponse').change(function () {
 78            let reponse = $(this).val()
 79            let achatservice_id = $('#id_achatservice_related-{{ forloop.counter0 }}-id').val();
 80            let url = '{% url "articles:ajax_update_achat_service" %}';
 81            $.ajax(
 82                    {
 83                        url: url,
 84                        data: {
 85                            'id': achatservice_id,
 86                            'reponse': reponse,
 87                        },
 88                        dataType: 'json',
 89                        success: function (data) {
 90                            // alert("Retour:" + data.update);
 91                        }
 92                }
 93            );
 94        });
 95        $('#id_achatservice_related-{{ forloop.counter0 }}-article').change(function () {
 96            let article_id = $(this).val()
 97            let achatservice_id = $('#id_achatservice_related-{{ forloop.counter0 }}-id').val();
 98            let libelle_article = document.getElementById('libelle_article_{{ forloop.counter0 }}');
 99
100            // alert("achatservice_id=" + achatservice_id + " article_id=" + article_id + + " libelle=" + libelle_article.textContent);
101            let url = '{% url "articles:ajax_update_achat_service" %}';
102
103            $.ajax(
104                    {
105                        url: url,
106                        data: {
107                            'id': achatservice_id,
108                            'article_id': article_id,
109                        },
110                        dataType: 'json',
111                        success: function (data) {
112                            // alert("Retour:" + data.update + " libelle article:" + data.libelle_article);
113                            libelle_article.textContent = data.libelle_article
114                        }
115                }
116            );
117        });
118        $('#id_achatservice_related-{{ forloop.counter0 }}-projet').change(function () {
119            let projet_id = $(this).val()
120            let achatservice_id = $('#id_achatservice_related-{{ forloop.counter0 }}-id').val();
121            let libelle_projet = document.getElementById('libelle_projet_{{ forloop.counter0 }}');
122
123            // alert("achatservice_id=" + achatservice_id + " projet_id=" + projet_id + " libelle=" + libelle_projet.textContent);
124            let url = '{% url "articles:ajax_update_achat_service" %}';
125            $.ajax(
126                    {
127                        url: url,
128                        data: {
129                            'id': achatservice_id,
130                            'projet_id': projet_id,
131                        },
132                        dataType: 'json',
133                        success: function (data) {
134                            // alert("Retour:" + data.update);
135                            libelle_projet.textContent = data.libelle_projet
136                        }
137                }
138            );
139        });
140        $('#id_achatservice_related-{{ forloop.counter0 }}-prestataire').change(function () {
141            {# un prestataire est un tiers (classe Tiers et Prestataire proxy sur Tiers #}
142            let prestataire_id = $(this).val()
143            let achatservice_id = $('#id_achatservice_related-{{ forloop.counter0 }}-id').val();
144            let libelle_prestataire = document.getElementById('libelle_prestataire_{{ forloop.counter0 }}');
145
146            // alert("achatservice_id=" + achatservice_id + " prestataire_id=" + prestataire_id + " libelle=" + libelle_prestataire.textContent);
147            let url = '{% url "articles:ajax_update_achat_service" %}';
148            $.ajax(
149                    {
150                        url: url,
151                        data: {
152                            'id': achatservice_id,
153                            'prestataire_id': prestataire_id,
154                        },
155                        dataType: 'json',
156                        success: function (data) {
157                            // alert("Retour:" + data.update);
158                            libelle_prestataire.textContent = data.libelle_prestataire
159                        }
160                }
161            );
162        });
163        $('#id_achatservice_related-{{ forloop.counter0 }}-description').change(function () {
164            let description = $(this).val()
165            let achatservice_id = $('#id_achatservice_related-{{ forloop.counter0 }}-id').val();
166            let url = '{% url "articles:ajax_update_achat_service" %}';
167            $.ajax(
168                    {
169                        url: url,
170                        data: {
171                            'id': achatservice_id,
172                            'description': description,
173                        },
174                        dataType: 'json',
175                        success: function (data) {
176                            // alert("Retour:" + data.update);
177                        }
178                }
179            );
180        });
181        $('#id_achatservice_related-{{ forloop.counter0 }}-quantite').change(function () {
182            let quantite = $(this).val()
183            let achatservice_id = $('#id_achatservice_related-{{ forloop.counter0 }}-id').val();
184            let url = '{% url "articles:ajax_update_achat_service" %}';
185            // alert("achatservice_id=" + achatservice_id + " quantite=" + quantite);
186            $.ajax(
187                    {
188                        url: url,
189                        data: {
190                            'id': achatservice_id,
191                            'quantite': quantite,
192                        },
193                        dataType: 'json',
194                        success: function (data) {
195                            // alert("Retour:" + data.update);
196                        }
197                }
198            );
199        });
200        $('#id_achatservice_related-{{ forloop.counter0 }}-prix_unitaire_0').change(function () {
201            let prix_unitaire = $(this).val()
202            let achatservice_id = $('#id_achatservice_related-{{ forloop.counter0 }}-id').val();
203            let url = '{% url "articles:ajax_update_achat_service" %}';
204            // alert("achatservice_id=" + achatservice_id + " prix unitaire=" + prix_unitaire);
205            $.ajax(
206                    {
207                        url: url,
208                        data: {
209                            'id': achatservice_id,
210                            'prix_unitaire': prix_unitaire,
211                        },
212                        dataType: 'json',
213                        success: function (data) {
214                            // alert("Retour:" + data.update);
215                        }
216                }
217            );
218        });
219
220        $('#id_achatservice_related-{{ forloop.counter0 }}-prix_unitaire_1').change(function () {
221            let currency = $(this).val()
222            let achatservice_id = $('#id_achatservice_related-{{ forloop.counter0 }}-id').val();
223            let url = '{% url "articles:ajax_update_achat_service" %}';
224            // alert("achatservice_id=" + achatservice_id + " currency=" + currency);
225            $.ajax(
226                    {
227                        url: url,
228                        data: {
229                            'id': achatservice_id,
230                            'currency': currency,
231                        },
232                        dataType: 'json',
233                        success: function (data) {
234                            // alert("Retour:" + data.update);
235                        }
236                }
237            );
238
239        });
240
241
242        $('#id_achatservice_related-{{ forloop.counter0 }}-date_butoir').change(function () {
243            let date_butoir = $(this).val()
244            let achatservice_id = $('#id_achatservice_related-{{ forloop.counter0 }}-id').val();
245            let url = '{% url "articles:ajax_update_achat_service" %}';
246            $.ajax(
247                    {
248                        url: url,
249                        data: {
250                            'id': achatservice_id,
251                            'datetime_livraison': date_butoir,
252                        },
253                        dataType: 'json',
254                        success: function (data) {
255                        }
256                }
257            );
258        });
259
260
261        {# Choix de la livraison souhaitée #}
262        $('#id_achatservice_related-{{ forloop.counter0 }}-date_butoir').datetimepicker(
263            {
264                // http://marcocecchetti.it/Post/Articolo/608
265                weeks: true,
266                rtl: false,
267                // formatTime:'H:i',
268                // formatDate:'d/m/Y',
269                format: 'd/m/Y H:i',
270                // date
271                datepicker: true,
272                opened: false,
273                todayButton: true,     // Show button "Go To Today"
274                defaultSelect:  true,  // Highlight the current date even if the input is empty
275                dayOfWeekStart : 1, // Start week DatePicker. Default Sunday=0.
276                defaultDate: false,
277                // https://secure.php.net/manual/fr/function.date.php
278                minDate:0,    // today
279                weekends : [],
280                disabledDates : [],
281                // time
282                timepicker:true,
283                timepickerScrollbar:true,
284                step: 60,
285                defaultTime:'10:00',
286                allowTimes:[
287                  '8:00', '9:00', '10:00', '11:00', '12:00',
288                  '13:00', '14:00', '15:00', '16:00', '17:00',
289                  '18:00', '19:00'
290                ]
291            }
292        );
293
294    {% endfor %}
295
296});
297
298</script>
299{% endblock extra_js %}
300
301
302{% block content %}
303
304
305<a class="btn btn-success" href="{% url 'articles:demande_article_non_cloturee_list' %}">Liste des demandes non clôturées</a>
306<a class="btn btn-success" href="{% url 'articles:demande_article_list' %}">Liste de toutes les demandes</a>
307
308
309{% url 'articles:demande_achat_service_update' demande_article.pk  as url_demande_achat_service_update %}
310
311
312{# https://getbootstrap.com/components/#labels #}
313
314{% if demande_article.demande_non_transmise %}
315<h4 class="couleur_demande_non_transmise">
316{% elif demande_article.demande_transmise %}
317<h4 class="couleur_demande_transmise">
318{% elif demande_article.demande_en_cours %}
319<h4 class="couleur_demande_en_cours">
320{% elif demande_article.demande_traitee %}
321<h4 class="couleur_demande_traitee">
322{% elif demande_article.demande_cloturee %}
323<h4 class="couleur_demande_cloturee">
324{% endif %}
325    <a href="{{ url_demande_achat_service_update }}">
326        Demande N°{{ demande_article.id }}
327    </a>
328    {{ demande_article.get_description_without_crlf}}
329</h4>
330
331
332{% if messages %}
333    <ul class="messages">
334        {% comment %} https://getbootstrap.com/components/#alerts {% endcomment %}
335        {% for message in messages %}
336        <!--li{% if message.tags %} class="{{ message.tags }}"{% endif %} -->
337            {% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
338                <div class="alert alert-danger" role="alert">{{ message }}</div>
339            {% elif message.level == DEFAULT_MESSAGE_LEVELS.SUCCESS %}
340                <div class="alert alert-success" role="alert">{{ message }}</div>
341            {% else %}
342                <div class="alert alert-info" role="alert">{{ message }}</div>
343            {% endif %}
344        <!-- /li -->
345        {% endfor %}
346    </ul>
347{% endif %}
348
349{% url 'tiers:create'  as url_tiers_create %}
350
351<form id="articles_achats" method="post" action=".">
352    {% csrf_token %}
353    <input type="hidden" name="demande_article" value="{{ demande_article }}">
354    <div class="table-responsive">
355        <table id="id_list_table" class="table table-condensed">
356            <thead>
357            <tbody>
358                {{ formset_achats.management_form }}
359                {# rajout des erreurs #}
360                {% if formset_achats.errors %}
361                    {% for error in formset_achats.non_field_errors %}
362                        <div class="alert alert-error">
363                            <strong>{{ error|escape }}</strong>
364                        </div>
365                    {% endfor %}
366                {% endif %}
367                {# Parcours des formulaires et des instances initiales associées #}
368                {% for form_achat, achat_service in formset_instances %}
369                    {{ form_achat.id }}
370                    <tr>
371                       <td>
372                           <table id="id_table_in_table" class="table table-hover table-condensed
373                                {% if forloop.counter|divisibleby:"2" %}
374                                   table-pair
375                                {% else %}
376                                    table-impair
377                                {% endif %}
378                               ">
379                               {# un element de formulaire => un tableau dans un tableau #}
380                                <tbody>
381                                    <tr>
382                                        {% url 'articles:achat_service_delete' form_achat.id.value  as url_achat_service_delete %}
383                                        {% url 'articles:achat_service_clone' form_achat.id.value  as url_achat_service_clone %}
384                                        {% if forloop.counter <= nb_articles %}
385                                            <td colspan=2 id={{ forloop.counter }}>
386                                               {% for num_article in list_articles %}
387                                                  {% if num_article != forloop.parentloop.counter  %}
388                                                      <a href="#{{ num_article }}">Achat {{ num_article }}</a>
389                                                  {% else %}
390                                                      Achat {{ forloop.parentloop.counter }}{{achat_service.id }}
391                                                  {% endif %}
392                                               {% endfor %}
393                                               {% if demande_article.demande_non_cloturee %}
394                                                   <a href="{{ url_achat_service_clone }}">| Ajouter un article</a>
395                                                   <a href="{{ url_achat_service_delete }}">| Supprimer un article</a
396                                                   {% if forloop.counter >= 2 %}
397                                                        <ul class=list-group>
398                                                          <li class="alert alert-success list-group-item">
399                                                            <a href="{{ url_demande_achat_service_update }}">Demande article N°{{ demande_article.id }}</a>
400                                                               {{ demande_article.get_description_without_crlf }}
401                                                          </li>
402                                                       </ul>
403                                                   {% endif %}
404                                               {% endif %}
405                                            </td>
406                                        {% else %}
407                                            <td colspan=2>
408                                            </td>
409                                        {% endif %}
410                                    </tr>
411                                    {% if demande_article.reponse_affichable %}
412                                        <tr>
413                                            {% comment %} Affichage en vert quand l'état du poste est dans l'état "Traité" {% endcomment %}
414                                            <td {% if achat_service.is_poste_traite %} class="text-right poste_traite" {% else %} class="text-right" {% endif %}>
415                                                Etat du poste {{ form_achat.etat_poste }}
416                                            </td>
417                                            <td {% if achat_service.is_poste_traite %} {% else %} class="info" {% endif %}>
418                                                Réponse {{ form_achat.reponse }}
419                                            </td>
420                                        </tr>
421                                        {% if achat_service.demande_cloturee_and_no_responses %}
422                                        {% else %}
423                                            <tr>
424                                                {% url 'articles:achat_service_reponse_list'  achat_service.id  as url_list_reponses %}
425                                                <td class="text-right">
426                                                    {% if demande_article.demande_non_cloturee %}
427                                                        <a href="{{ url_list_reponses }}">Documents réponse</a>
428                                                    {% else %}
429                                                        Documents réponse
430                                                    {% endif %}
431                                                </td>
432                                                <td>
433                                                    {% if forloop.counter <= nb_articles %}
434                                                        {% for document in achat_service.responses.all %}
435                                                            {% with media=document.item %}
436                                                                {# https://getbootstrap.com/css/#tables-example #}
437                                                                <p>{{ media.render }} </p>
438                                                            {% endwith %}
439                                                        {% endfor %}
440                                                    {% endif %}
441                                                </td>
442                                            </tr>
443                                        {% endif %}
444                                    {% endif %}
445                                    <tr>
446                                        <td class="text-right">Code article</td>
447                                        <td class="danger">
448                                        {% if demande_article.demande_non_cloturee %}
449                                            {{ form_achat.article }}
450                                        {% endif %}
451                                        <span id="libelle_article_{{ forloop.counter0 }}"> {{ achat_service.get_libelle_article }}</span>
452                                        </td>
453                                    </tr>
454                                    <tr>
455                                        <td class="text-right">Projet</td>
456                                        <td>
457                                            {% if demande_article.demande_non_cloturee %}
458                                                {{ form_achat.projet }}
459                                            {% endif %}
460                                            <span id="libelle_projet_{{ forloop.counter0 }}" {{ achat_service.get_libelle_projet }} </span>
461                                        </td>
462                                    </tr>
463                                    <tr>
464                                        <td class="text-right">Description</td>
465                                        <td>{{ form_achat.description }}</td>
466                                    </tr>
467                                    <tr>
468                                        <td class="text-right">Prestataire</td>
469                                        <td>
470                                            {% if demande_article.demande_non_cloturee %}
471                                                {{ form_achat.prestataire }}
472                                                <a href="{{ url_tiers_create }}"> <img src="{% static "tiers/icon-addlink.svg" %}" alt="Ajouter"/> </a>
473                                            {% endif %}
474                                            <span id="libelle_prestataire_{{ forloop.counter0 }}" {{ achat_service.get_libelle_prestataire }} </span>
475                                        </td>
476                                    </tr>
477                                    <tr>
478                                        <td class="text-right">Quantite</td>
479                                        <td>{{ form_achat.quantite }} Prix {{ form_achat.prix_unitaire }} </td>
480                                    </tr>
481                                    <tr>
482                                        <td class="text-right">Livraison souhaitée</td>
483                                        <td class="danger">{{ form_achat.date_butoir }}</td>
484                                    </tr>
485                                    {% if achat_service.demande_cloturee_and_no_documents %}
486                                    {% else %}
487                                        <tr>
488                                            {% url 'articles:achat_service_doc_list'  achat_service.id  as url_list_documents %}
489                                            <td class="text-right">
490                                                {% if demande_article.demande_non_cloturee %}
491                                                    {% if forloop.counter <= nb_articles %}
492                                                        <a href="{{ url_list_documents }}">Documents associés</a>
493                                                    {% endif %}
494                                                {% else %}
495                                                    Documents associés
496                                                {% endif %}
497                                            </td>
498                                            <td>
499                                                {% if forloop.counter <= nb_articles %}
500                                                    {% for document in achat_service.contents.all %}
501                                                        {% with media=document.item %}
502                                                            <p>{{ media.render }} </p>
503                                                        {% endwith %}
504                                                    {% endfor %}
505                                                {% endif %}
506                                            </td>
507                                        </tr>
508                                    {% endif %}
509                                    <tr>
510                                        <td colspan=2>
511                                        </td>
512                                    </tr>
513                                </tbody>
514                            {# table imbriquee #}
515                            </table>
516                       </td>
517                    </tr>
518                {% endfor %}
519            </tbody>
520        </table>
521    </div>
522</form>
523
524
525
526{% endblock %}
527
528
529{% block footer %}
530{% endblock footer %}