Codifarticle AJAX with fetch ¶
Contents
frontend.js.utils.js ¶
1// utils.js
2// Fonctions utilitaires Javascript
3//
4// - https://flaviocopes.com/javascript-let-const/
5// - https://gdevops.gitlab.io/tuto_javascript/reference/instructions/const/const.html
6// - https://gdevops.gitlab.io/tuto_javascript/reference/promise/flaviocopes.com/flaviocopes.com.html
7// - https://gdevops.gitlab.io/tuto_web/html/apis/document/methods/getElementById/getElementById.html
8// - https://gdevops.gitlab.io/tuto_web/html/apis/fetch/fetch.html
9//
10export function id3_toggle_classes(element) {
11 if (element.title === "Write") {
12 element.title = "Preview";
13 element.classList.remove("fa-pencil");
14 element.classList.add("fa-eye");
15 } else {
16 element.title = "Write";
17 element.classList.remove("fa-eye");
18 element.classList.add("fa-pencil");
19 }
20}
21
22export function increment_update() {
23 const id_ajax_call = document.getElementById("id_nb_ajax_call");
24 if (id_ajax_call === null) {
25 return;
26 }
27
28 let a = Number(id_ajax_call.innerText);
29 a = a + 1;
30 id_ajax_call.innerText = a;
31}
32
33export function build_url_with_parameters(i_url, parameters) {
34 //
35 // let parameters = {'id': codifnomenclature_id,'demande_codification': demande_codification};
36 //
37 // Exemple d'url: "/articles/ajax/codif_nomenclature_update?id=398&besoin_reel=51";
38 //
39 let base_url = new URL("http://bidon");
40 Object.keys(parameters).forEach((key) =>
41 base_url.searchParams.append(key, parameters[key])
42 );
43
44 let url = i_url + base_url.search;
45 return url;
46}
47
48export function display_parameters(parameters) {
49 //
50 // let parameters = {'id': 6,'demande_codification': 78};
51 //
52 Object.keys(parameters).forEach((key) =>
53 console.log(`key=${key} parameter=${parameters[key]}`)
54 );
55}
56
57
58export function update_demande(url) {
59 const etat_demande = document.getElementById('id_etat_demande').value;
60 const id_demande_article = document.getElementById('id_demande_article').textContent;
61 const widget = document.getElementById('id_send_email');
62 const send_email = widget.checked;
63 const parameters = { 'id_demande_article': id_demande_article, 'etat_demande': etat_demande, 'send_email': send_email};
64 const url_param = build_url_with_parameters(url, parameters);
65 try {
66 fetch(url_param);
67 increment_update();
68 } catch (error) {
69 console.error(error);
70 }
71}
72
73export function update_iframe_description_demande(url, libelles_description)
74{
75 const iframe_description_demande = document.getElementById('id_description_iframe');
76 // Le texte HTML issu du iframe id_description_iframe
77 const editables = iframe_description_demande.contentDocument.getElementsByClassName('note-editable');
78 if (editables.length > 0) {
79 const editable = editables[0];
80 const description = editable.innerHTML;
81 const id_demande_article = document.getElementById('id_demande_article').textContent;
82 console.log(`id_demande_article=${id_demande_article} description=${description}`);
83 const widget = document.getElementById('id_send_email');
84 const send_email = widget.checked;
85
86 const parameters = {'id_demande_article': id_demande_article,'description': description,'send_email': send_email};
87 const url_param = build_url_with_parameters(url, parameters);
88 fetch(url_param).then(response => response.json()).then(json => {
89 increment_update();
90 libelles_description.forEach(function(libelle, index, array) {
91 libelle.textContent = json.libelle_description;
92 });
93 });
94 }
95}
96
97export function update_summernote(url, editables, map_parameters, key_data) {
98 if (editables.length > 0) {
99 const editable = editables[0];
100 const new_data = editable.innerHTML;
101 map_parameters.set(key_data, new_data);
102 const parameters = Object.fromEntries(map_parameters);
103 const url_param = build_url_with_parameters(url, parameters);
104 fetch(url_param).then(response => response.json()).then(json => {
105 increment_update();
106 });
107 };
108}
109
110
111export function id3_fetch(url, parameters) {
112 // https://gdevops.gitlab.io/tuto_javascript/reference/promise/flaviocopes.com/flaviocopes.com.html
113 // chaining of promises
114 const url_param = build_url_with_parameters(url, parameters);
115 const promise = fetch(url_param)
116 .then(response => response.json())
117 .then(json => {
118 increment_update();
119 return Promise.resolve(json);
120 });
121 return promise;
122}
123
124export function get_temps_impute(temps_impute) {
125 // Par defaut un intervalle est de type HH:MM:SS => on concatene ':00'
126 let nb_tokens = temps_impute.split(':').length;
127 if (nb_tokens === 1) {
128 temps_impute = temps_impute.concat(':00:00');
129 }
130 if (nb_tokens === 2) {
131 temps_impute = temps_impute.concat(':00');
132 }
133 // Cas de l'emploi de la virgule
134 nb_tokens = temps_impute.split(',').length
135 if (nb_tokens === 2) {
136 // de cette façon on a le meme comportement qu'avec le "." ce qui est très bien
137 temps_impute = tokens[0] + '.' + tokens[1];
138 }
139
140 console.log(`temps_impute=${temps_impute}`);
141 return temps_impute;
142}
articles.templates.articles.demande.achat_service.articles_update.html ¶
1{% extends "base.html" %}
2{% load static %}
3{% load article %}
4{% load markdown_extras %}
5
6{% block stylesheet %}
7 <link rel="stylesheet" href="{% static 'css/couleurs_demande_article.css' %}">
8 <!-- CSS pour datetime picker -->
9 <link rel="stylesheet" href="{% static 'js/jquery.datetimepicker.min.css' %}">
10
11 <!-- CSS pour autocomplete_light -->
12 <link rel="stylesheet" href="{% static 'select2/css/select2.css' %}">
13 <link rel="stylesheet" href="{% static 'autocomplete_light/select2.css' %}">
14
15 <!-- Bordure des tables -->
16 <link rel="stylesheet" href="{% static 'css/table.css' %}">
17{% endblock %}
18
19
20{% block javascript %}
21 {# a employer dans les templates fils->{{ block.super }} #}
22 {{ block.super }}
23
24 <!-- datetime picker jQuery script -->
25 <script src="{% static 'js/jquery.datetimepicker.full.js' %}"></script>
26
27 <!-- Javascript for autocomplete_light -->
28 <script src="{% static 'autocomplete_light/jquery.init.js' %}"></script>
29 <script src="{% static 'autocomplete_light/autocomplete.init.js' %}"></script>
30 <script src="{% static 'select2/js/select2.full.js' %}"></script>
31 <script src="{% static 'autocomplete_light/forward.js' %}"></script>
32 <script src="{% static 'autocomplete_light/select2.js' %}"></script>
33
34 <script type="module">
35 import { increment_update, build_url_with_parameters, update_demande } from '{% static 'js/utils.js' %}';
36 import { update_iframe_description_demande, update_summernote, id3_fetch } from '{% static 'js/utils.js' %}';
37
38 window.increment_update = increment_update;
39 window.build_url_with_parameters = build_url_with_parameters;
40 window.update_demande = update_demande;
41 window.update_iframe_description_demande = update_iframe_description_demande;
42 window.update_summernote = update_summernote;
43 window.id3_fetch = id3_fetch;
44 </script>
45
46{% endblock javascript %}
47
48{% block extra_js %}
49{# Code composé de Javascript et de Django Template Language #}
50{# ========================================================= #}
51
52<script type="module">
53
54function trt_date_butoir() {
55 // langue française
56 $.datetimepicker.setLocale('fr');
57
58 {% for form_codif_article in formset_codif_articles %}
59 {# Choix de la livraison souhaitée #}
60 $('#id_codifarticle_related-{{ forloop.counter0 }}-date_butoir').datetimepicker(
61 {
62 // http://marcocecchetti.it/Post/Articolo/608
63 weeks: true,
64 rtl: false,
65 // formatTime:'H:i',
66 // formatDate:'d/m/Y',
67 format: 'd/m/Y H:i',
68 // date
69 datepicker: true,
70 opened: false,
71 todayButton: true, // Show button "Go To Today"
72 defaultSelect: true, // Highlight the current date even if the input is empty
73 dayOfWeekStart : 1, // Start week DatePicker. Default Sunday=0.
74 defaultDate: false,
75 // https://secure.php.net/manual/fr/function.date.php
76 minDate:0, // today
77 weekends : [],
78 disabledDates : [],
79 // time
80 timepicker:true,
81 timepickerScrollbar:true,
82 step: 60,
83 defaultTime:'10:00',
84 allowTimes:[
85 '8:00', '9:00', '10:00', '11:00', '12:00',
86 '13:00', '14:00', '15:00', '16:00', '17:00',
87 '18:00', '19:00'
88 ]
89 }
90 );
91
92 {% endfor %}
93
94}
95
96document.addEventListener('DOMContentLoaded', (event) => {
97 // https://gdevops.gitlab.io/tuto_web/html/apis/document/events/DOMContentLoaded_event/DOMContentLoaded_event.html
98 console.log('DOM is loaded');
99 console.log(`document.readyState = ${document.readyState}`);
100
101 trt_date_butoir();
102});
103
104function trt_widgets() {
105 console.log(`trt_widgets() document.readyState = ${document.readyState}`);
106 document.getElementById('id_etat_demande').onchange = function() {
107 const url = '{% url "articles:ajax_update_demande_article" %}';
108 update_demande(url);
109 }
110 const url = '{% url "articles:ajax_update_codif_article" %}';
111 let codifarticle_id = 0;
112 {% for form_codif_article in formset_codif_articles %}
113 codifarticle_id = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-id').value;
114 const parameters_{{ forloop.counter0 }} = {'id': codifarticle_id};
115 try {
116 document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-etat_poste').onchange = function() {
117 parameters_{{ forloop.counter0 }}.etat_poste = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-etat_poste').value;
118 id3_fetch(url, parameters_{{ forloop.counter0 }});
119 }
120 } catch (error) {
121 ;
122 }
123 try {
124 document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-ofda').onchange = function() {
125 parameters_{{ forloop.counter0 }}.ofda = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-ofda').value;
126 id3_fetch(url, parameters_{{ forloop.counter0 }});
127 }
128 } catch (error) {
129 ;
130 }
131 document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-article').onchange = function() {
132 parameters_{{ forloop.counter0 }}.article_id =document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-article').value;
133 id3_fetch(url, parameters_{{ forloop.counter0 }}).then(json => { document.getElementById('libelle_article_{{ forloop.counter0 }}').textContent = json.libelle_article;});
134 }
135 document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-projet').onchange = function() {
136 parameters_{{ forloop.counter0 }}.projet_id = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-projet').value;
137 id3_fetch(url, parameters_{{ forloop.counter0 }}).then(json => { document.getElementById('libelle_projet_{{ forloop.counter0 }}').textContent = json.libelle_projet});
138 }
139 document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-fabricant').onchange = function() {
140 parameters_{{ forloop.counter0 }}.fabricant_id = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-fabricant').value;
141 id3_fetch(url, parameters_{{ forloop.counter0 }}); ;
142 }
143 document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-ref_fabricant').onchange = function() {
144 parameters_{{ forloop.counter0 }}.ref_fabricant = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-ref_fabricant').value;
145 id3_fetch(url, parameters_{{ forloop.counter0 }});
146 }
147 document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-fournisseur').onchange = function() {
148 parameters_{{ forloop.counter0 }}.fournisseur_id = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-fournisseur').value;
149 id3_fetch(url, parameters_{{ forloop.counter0 }});
150 }
151 document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-ref_fournisseur').onchange = function() {
152 parameters_{{ forloop.counter0 }}.ref_fournisseur = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-ref_fournisseur').value;
153 id3_fetch(url, parameters_{{ forloop.counter0 }});
154 }
155 document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-date_butoir').onchange = function() {
156 parameters_{{ forloop.counter0 }}.date_butoir = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-date_butoir').value;
157 id3_fetch(url, parameters_{{ forloop.counter0 }});
158 }
159 document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-demande_codification').onchange = function() {
160 parameters_{{ forloop.counter0 }}.demande_codification = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-demande_codification').checked;
161 id3_fetch(url, parameters_{{ forloop.counter0 }});
162 }
163 document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-besoin_reel').onchange = function() {
164 parameters_{{ forloop.counter0 }}.besoin_reel = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-besoin_reel').value;
165 id3_fetch(url, parameters_{{ forloop.counter0 }});
166 }
167 document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-besoin_potentiel').onchange = function() {
168 parameters_{{ forloop.counter0 }}.besoin_potentiel = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-besoin_potentiel').value;
169 id3_fetch(url, parameters_{{ forloop.counter0 }});
170 }
171 document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-sortie_stock').onchange = function() {
172 parameters_{{ forloop.counter0 }}.sortie_stock = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-sortie_stock').value;
173 id3_fetch(url, parameters_{{ forloop.counter0 }});
174 }
175 document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-cotation_par').onchange = function() {
176 parameters_{{ forloop.counter0 }}.cotation_par = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-cotation_par').value;
177 id3_fetch(url, parameters_{{ forloop.counter0 }});
178 }
179
180 {% endfor %}
181}
182
183
184function trt_iframe_description_demande()
185{
186 console.log(`trt_description_demande() document.readyState = ${document.readyState}`);
187
188 const url = '{% url "articles:ajax_update_demande_article" %}';
189 const iframe_description_demande = document.getElementById('id_description_iframe');
190 iframe_description_demande.contentDocument.activeElement.onblur = function() {
191 try {
192 let libelles_description = [];
193 let libelle_description = "";
194 {% for form_codif_article in formset_codif_articles %}
195 {% if forloop.counter >= 2 %}
196 libelle_description = document.getElementById('libelle_description_{{ forloop.counter0 }}');
197 libelles_description.push(libelle_description);
198 {% endif %}
199 {% endfor %}
200 update_iframe_description_demande(url, libelles_description);
201 } catch (error) {
202 console.error(error);
203 }
204 }
205}
206
207
208function trt_iframes_responses()
209{
210 console.log(`trt_iframes_reponses() document.readyState = ${document.readyState}`);
211 const url = '{% url "articles:ajax_update_codif_article" %}';
212 {% for form_codif_article in formset_codif_articles %}
213 try
214 {
215 {# le champ reponse n'est pas toujours present #}
216 const iframe_reponse_{{ forloop.counter0 }} = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-reponse_iframe');
217 iframe_reponse_{{ forloop.counter0 }}.contentDocument.activeElement.onblur = function() {
218 const editables = iframe_reponse_{{ forloop.counter0 }}.contentDocument.getElementsByClassName('note-editable');
219 const codifarticle_id = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-id').value;
220 const map_parameters = new Map([['id',codifarticle_id],['reponse', ""]]);
221 update_summernote(url, editables, map_parameters, 'reponse');
222 }
223 } catch (error) {
224 ; // console.error(error);
225 }
226
227 {% endfor %}
228}
229
230function trt_iframes_designations()
231{
232 console.log(`trt_iframes_designations() document.readyState = ${document.readyState}`);
233
234 const url = '{% url "articles:ajax_update_codif_article" %}';
235 {% for form_codif_article in formset_codif_articles %}
236 const iframe_designation_{{ forloop.counter0 }} = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-designation_iframe');
237 iframe_designation_{{ forloop.counter0 }}.contentDocument.activeElement.onblur = function() {
238 const editables = iframe_designation_{{ forloop.counter0 }}.contentDocument.getElementsByClassName('note-editable');
239 const codifarticle_id = document.getElementById('id_codifarticle_related-{{ forloop.counter0 }}-id').value;
240 const map_parameters = new Map([['id',codifarticle_id],['designation', ""]]);
241 update_summernote(url, editables, map_parameters, 'designation');
242 }
243 {% endfor %}
244}
245
246window.addEventListener('load', (event) => {
247 console.log('window page is fully loaded');
248
249 {% comment %}
250 On ne traite les iframes que lorsque tout est chargé
251 voir:
252 - https://javascript.info/onload-ondomcontentloaded#readystate
253 - https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
254 {% endcomment %}
255
256 trt_widgets();
257 trt_iframe_description_demande();
258 trt_iframes_responses();
259 trt_iframes_designations();
260});
261
262
263
264</script>
265{% endblock extra_js %}
266
267
268{% block content %}
269
270
271<a class="btn btn-success" href="{% url 'articles:demande_article_non_cloturee_list' %}">Liste des demandes non clôturées</a>
272<a class="btn btn-success" href="{% url 'articles:demande_article_list' %}">Liste de toutes les demandes</a>
273
274
275{% url 'articles:demande_codif_article_update' demande_article.pk as url_demande_codif_article_update %}
276
277
278{# https://getbootstrap.com/components/#labels #}
279
280{% if demande_article.demande_non_transmise %}
281<h4 class="couleur_demande_non_transmise">
282{% elif demande_article.demande_transmise %}
283<h4 class="couleur_demande_transmise">
284{% elif demande_article.demande_en_cours %}
285<h4 class="couleur_demande_en_cours">
286{% elif demande_article.demande_traitee %}
287<h4 class="couleur_demande_traitee">
288{% elif demande_article.demande_cloturee %}
289<h4 class="couleur_demande_cloturee">
290{% endif %}
291 Demande N° <span id="id_demande_article"> {{ demande_article.id }}</span> Update:<span id="id_nb_ajax_call"> 0</span>
292</h4>
293
294
295{% if messages %}
296 <ul class="messages">
297 {% comment %} https://getbootstrap.com/components/#alerts {% endcomment %}
298 {% for message in messages %}
299 <!--li{% if message.tags %} class="{{ message.tags }}"{% endif %} -->
300 {% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
301 <div class="alert alert-danger" role="alert">{{ message }}</div>
302 {% elif message.level == DEFAULT_MESSAGE_LEVELS.SUCCESS %}
303 <div class="alert alert-success" role="alert">{{ message }}</div>
304 {% else %}
305 <div class="alert alert-info" role="alert">{{ message }}</div>
306 {% endif %}
307 <!-- /li -->
308 {% endfor %}
309 </ul>
310{% endif %}
311
312{{ form.description }}
313{{ form.etat_demande }}
314<tr>
315 <th><label for="id_send_email">Envoi courriel :</label></th>
316 <td><input type="checkbox" name="send_email" id="id_send_email"></td>
317</tr>
318
319{% url 'tiers:create' as url_tiers_create %}
320
321<form id="codif_articles" method="post" action=".">
322 {% csrf_token %}
323 <input type="hidden" name="demande_article" value="{{ demande_article }}">
324 <div class="table-responsive">
325 <table id="id_list_table" class="table table-condensed">
326 <tbody>
327 {{ formset_codif_articles.management_form }}
328 {# rajout des erreurs #}
329 {% if formset_codif_articles.errors %}
330 {% for error in formset_codif_articles.non_field_errors %}
331 <div class="alert alert-error">
332 <strong>{{ error|escape }}</strong>
333 </div>
334 {% endfor %}
335 {% endif %}
336 {# Parcours des formulaires et des instances initiales associées #}
337 {% for form_codif_article, codif_article in formset_instances %}
338 {{ form_codif_article.id }}
339 <tr>
340 <td>
341 <table id="id_table_in_table" class="table table-hover table-bordered table-condensed
342 {% if forloop.counter|divisibleby:"2" %}
343 table-pair
344 {% else %}
345 table-impair
346 {% endif %}
347 ">
348 {# un element de formulaire => un tableau dans un tableau #}
349 <tbody>
350 <tr>
351 {% url 'articles:codif_article_delete' form_codif_article.id.value as url_codif_article_delete %}
352 {% url 'articles:codif_article_clone' form_codif_article.id.value as url_codif_article_clone %}
353 {% if forloop.counter <= nb_articles %}
354 <td colspan=2 id={{ forloop.counter }}>
355 {% comment %}
356 Mise en place des liens internes à une page HTML (href)
357 https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_a_href_anchor
358 {% endcomment %}
359 {% for num_article in list_articles %}
360 {% if num_article != forloop.parentloop.counter %}
361 <a href="#{{ num_article }}">Codif {{ num_article }}</a>
362 {% else %}
363 Codif {{ forloop.parentloop.counter }} N°{{codif_article.id }}
364 {% endif %}
365 {% endfor %}
366 {% if demande_article.demande_non_cloturee %}
367 <a href="{{ url_codif_article_clone }}"> | Ajouter un article</a>
368 <a href="{{ url_codif_article_delete }}">| Supprimer un article</a>
369 {% if forloop.counter >= 2 %}
370 <ul class=list-group>
371 <li class="alert alert-success list-group-item">
372 <a href="#id_demande_article">Demande article N°{{ demande_article.id }}</a>
373 <span id="libelle_description_{{ forloop.counter0 }}"> {{ demande_article.description | markdown | safe }}</span>
374 </li>
375 </ul>
376 {% endif %}
377 {% endif %}
378 </td>
379 {% else %}
380 <td colspan=2>
381 </td>
382 {% endif %}
383 </tr>
384 {% if demande_article.reponse_affichable %}
385 <tr>
386 {% comment %} Affichage en vert quand l'état du poste est dans l'état "Traité" {% endcomment %}
387 <td {% if codif_article.is_poste_traite %} class="text-right poste_traite" {% else %} class="text-right" {% endif %}>
388 Etat du poste {{ form_codif_article.etat_poste }}
389 </td>
390 <td {% if codif_article.is_poste_traite %} {% else %} class="info" {% endif %}>
391 Réponse {{ form_codif_article.reponse }}
392 </td>
393 </tr>
394 <tr>
395 <td class="text-right">N°OFDA</td>
396 <td class="info">{{ form_codif_article.ofda }}
397 </td>
398 </tr>
399 {% endif %}
400 <tr>
401 <td class="text-right">Code article</td>
402 <td class="danger">
403 {% if demande_article.demande_non_cloturee %}
404 {{ form_codif_article.article }}
405 {% endif %}
406 <span id="libelle_article_{{ forloop.counter0 }}"> {{ codif_article.get_libelle_article }}</span>
407 </td>
408 </tr>
409 <tr>
410 <td class="text-right">Projet</td>
411 <td>
412 {% if demande_article.demande_non_cloturee %}
413 {{ form_codif_article.projet }}
414 {% endif %}
415 <span id="libelle_projet_{{ forloop.counter0 }}"> {{ codif_article.get_libelle_projet }}</span>
416 </td>
417 </tr>
418 <tr>
419 <td class="text-right">Désignation</td>
420 <td>{{ form_codif_article.designation }}</td>
421 </tr>
422 {% if codif_article.demande_cloturee_and_no_documents %}
423 {% else %}
424 <tr>
425 {% url 'articles:codif_article_doc_list' codif_article.id as url_list_documents %}
426 <td class="text-right">
427 {% if demande_article.demande_non_cloturee %}
428 {% if forloop.counter <= nb_articles %}
429 <a href="{{ url_list_documents }}">Documents associés</a>
430 {% endif %}
431 {% else %}
432 Documents associés
433 {% endif %}
434 </td>
435 <td>
436 {% if forloop.counter <= nb_articles %}
437 {% for document in codif_article.contents.all %}
438 {% with media=document.item %}
439 <p> {{ media.render }} </p>
440 {% endwith %}
441 {% endfor %}
442 {% endif %}
443 </td>
444 </tr>
445 {% endif %}
446 <tr>
447 <td class="text-right">Fabricant</td>
448 <td>
449 {{ form_codif_article.fabricant }}
450 Réf Fab {{ form_codif_article.ref_fabricant }}
451 </td>
452 </tr>
453 <tr>
454 <td class="text-right">Fournisseur</td>
455 <td>
456 {{ form_codif_article.fournisseur }}
457 Réf Fourn {{ form_codif_article.ref_fournisseur }}
458 </td>
459 </tr>
460 <tr>
461 <td class="text-right">Livraison souhaitée</td>
462 <td class="danger">{{ form_codif_article.date_butoir }}</td>
463 </tr>
464 <tr>
465 <td class="text-right">Demande de codification: {{ form_codif_article.demande_codification }} </td>
466 <td></td>
467 </tr>
468 <tr>
469 <td class="text-right">Demande d'approvisionnement <input id="id_codifarticle_related-{{ forloop.counter0 }}-demande_approvisionnement"
470 name="codifarticle_set-{{ forloop.counter0 }}-demande_approvisionnement"
471 {% if form_codif_article.demande_approvisionnement.value %}
472 checked="checked"
473 {% else %}
474 {% endif %}
475 data-toggle="collapse"
476 data-target="#demande_approvisionnement_{{ forloop.counter0 }}"
477 type="checkbox"
478 />
479 <td>
480 <div id="demande_approvisionnement_{{ forloop.counter0 }}"
481 {% if form_codif_article.demande_approvisionnement.value %}
482 class="collapse in"
483 {% else %}
484 class="collapse"
485 {% endif %}
486 >
487 <p>Besoin réel: {{ form_codif_article.besoin_reel }} Besoin potentiel: {{ form_codif_article.besoin_potentiel }}</p>
488 </div>
489 </td>
490 </tr>
491 <tr>
492 <td class="text-right">Demande de sortie du stock <input id="id_codifarticle_related-{{ forloop.counter0 }}-demande_sortie_stock"
493 name="codifarticle_set-{{ forloop.counter0 }}-demande_sortie_stock"
494 {% if form_codif_article.demande_sortie_stock.value %}
495 checked="checked"
496 {% else %}
497 {% endif %}
498 data-toggle="collapse"
499 data-target="#demande_sortie_stock_{{ forloop.counter0 }}"
500 type="checkbox"
501 />
502 </td>
503 <td>
504 <div id="demande_sortie_stock_{{ forloop.counter0 }}"
505 {% if form_codif_article.demande_sortie_stock.value %}
506 class="collapse in"
507 {% else %}
508 class="collapse"
509 {% endif %}
510 >
511 Quantité à sortir: {{ form_codif_article.sortie_stock }}
512 </div>
513 </td>
514 </tr>
515 <tr>
516 <td class="text-right">Demande de cotation <input id="id_codifarticle_related-{{ forloop.counter0 }}-demande_cotation"
517 name="codifarticle_set-{{ forloop.counter0 }}-demande_cotation"
518 {% if form_codif_article.demande_cotation.value %}
519 checked="checked"
520 {% else %}
521 {% endif %}
522 data-toggle="collapse"
523 data-target="#demande_cotation_{{ forloop.counter0 }}"
524 type="checkbox"
525 />
526 </td>
527 <td>
528
529 <div id="demande_cotation_{{ forloop.counter0 }}"
530 {% if form_codif_article.demande_cotation.value %}
531 class="collapse in"
532 {% else %}
533 class="collapse"
534 {% endif %}
535 >
536 Cotation par: {{ form_codif_article.cotation_par }}
537 </div>
538 </td>
539 </tr>
540 <tr>
541 <td colspan=2>
542 {% if demande_article.demande_non_cloturee %}
543 {% endif %}
544 </td>
545 </tr>
546 </tbody>
547 {# table imbriquee = 1 enregistrement #}
548 </table>
549 </td>
550 </tr>
551 {% endfor %}
552 </tbody>
553 </table>
554 </div>
555</form>
556
557
558
559{% endblock %}
560
561
562{% block footer %}
563
564{% endblock footer %}