Projet

Général

Profil

0001-dossiers-printing-the-whole-patient-record-in-pdf-fo.patch

Serghei Mihai, 21 août 2014 18:54

Télécharger (20,1 ko)

Voir les différences:

Subject: [PATCH 1/2] dossiers: printing the whole patient record in pdf format

Closes #3109
 .../templates/dossiers/patientrecord_print.html    | 325 +++++++++++++++++++++
 .../dossiers/patientrecord_print_coordinators.html |   9 +
 .../templates/dossiers/patientrecord_update.html   |   3 +
 calebasse/dossiers/urls.py                         |   1 +
 calebasse/dossiers/views.py                        |  30 ++
 calebasse/static/js/calebasse.dialog.js            |   5 +-
 6 files changed, 371 insertions(+), 2 deletions(-)
 create mode 100644 calebasse/dossiers/templates/dossiers/patientrecord_print.html
 create mode 100644 calebasse/dossiers/templates/dossiers/patientrecord_print_coordinators.html
calebasse/dossiers/templates/dossiers/patientrecord_print.html
1
{% load dossiers %}
2
<html>
3
  <style type="text/css">
4
    @page {
5
    size: a4 landscape;
6
    @frame {
7
    top: 2cm;
8
    left: 1cm;
9
    width: 27.7cm;
10
    background-color:black;
11
    height: 18cm;
12
    }
13
    @frame header_frame {
14
    -pdf-frame-content: header_frame;
15
    top: 1cm;
16
    margin-top: 0;
17
    margin-left: 1cm;
18
    margin-right: 1cm;
19
    height: 1cm;
20
    }
21
    }
22
    body {font-size: 0.4cm;}
23
    table {margin-top:5pt;font-weight: normal}
24
    td, th {padding: 3pt 4pt; text-align:left; border: 1pt solid #aaaaaa}
25
    button {display: none; }
26
    li {list-style-type: none;}
27
    div.frame h3 {border-bottom: 1pt solid #555; padding: 2pt 3pt}
28
    .normal {font-weight: normal}
29
    .block h3 {background-color:#cccccc;padding: 2pt 5pt}
30
    label {font-weight: bold}
31
    .screen-only {display: none}
32

  
33

  
34
    div.block h2 { background-color: #EFEFEF; padding: 2pt 5pt}
35
    table th, table td {background-color:#aaaaaa;font-weight: normal}
36
  </style>
37

  
38
  <div id="header_frame">
39
    <h1><span class="lastname">{{ object.last_name }}</span> {{ object.first_name }} - Dossier {{ object.id }}</h1>
40
  </div>
41

  
42
  <div class="block">
43
    <h2>Général</h2>
44
    <ul>
45
      <li><label>N° dossier papier :</label> {{ object.paper_id|default_if_none:"Non renseigné" }}</li>
46
      <li><label>N° dossier informatique :</label> <span class="lightgray">{{ object.id }}</span></li>
47
      <li><label>Nom :</label> <span class="lastname">{{ object.last_name }}</span></li>
48
      <li><label>Prénom :</label> {{ object.first_name }}</li>
49
      <li><label>Genre :</label> {{ object.get_gender_display|default_if_none:"Non renseigné" }}</li>
50
      <li><label>Date de naissance :</label> {% if object.birthdate %}{{ object.birthdate|date:"d/m/Y" }} ({{ object.age }}){% else %}Non renseignée{% endif %}</li>
51
      <li>
52
        {% if nb_place_of_lifes == 1 %}
53
        <label>Lieux de vie :</label>
54
        {% elif nb_place_of_lifes > 1 %}
55
        <label class="highlight">{{ nb_place_of_lifes }} lieux de vie :</label>
56
        {% else %}
57
        <label class="highlight">Aucun lieu de vie d'indiqué</label>
58
        {% endif %}
59
        {% if object.contact_comment %}<pre>{{ object.contact_comment }}</pre>{% endif %}
60
        {% if object.addresses.all %}
61
        <ul>
62
          {% for address in object.addresses.all %}
63
          {% if address.place_of_life %}<li>{{ address.display_name }}</li>{% endif %}
64
          {% endfor %}
65
        </ul>
66
        {% endif %}
67
      </li>
68
      <li><label>Date de contact :</label> {{ initial_state.date_selected|date:"d/m/Y" }}</li>
69
      <li><label>Date de création :</label> {{ object.created|date:"d/m/Y" }}</li>
70
      <li><label>Lieu de socialisation :</label> {{ object.school|default_if_none:"Non renseigné" }}</li>
71
      {% include "dossiers/patientrecord_print_coordinators.html" %}
72
      <li><label>Commentaire </label><br/>
73
        {{ object.comment }}
74
      </li>
75
      <li><label>Dernier acte :</label>
76
        {% if last_rdv %}
77
        {% if last_rdv.is_absent %}<span style="font-weight: bold;">{% endif %}
78
          {{ last_rdv.start_datetime|date:"d/m/Y" }} -
79
          {% for participant in last_rdv.participants %}
80
          <span class="lastname">{{ participant.last_name }}</span> -
81
          {% endfor %}
82
          {{ last_rdv.act_type }}
83
          {% else %}
84
          Aucun
85
          {% endif %}
86
          {% if last_rdv.is_absent %} ({{ last_rdv.act_state }})</span>{% endif %}
87
      </li>
88
      <li><label>Prochain rendez-vous :</label>
89
        {% if next_rdv %}
90
        {% if next_rdv.is_absent %}<span style="font-weight: bold;">{% endif %}
91
          {{ next_rdv.start_datetime|date:"d/m/Y" }} -
92
          {% for participant in next_rdv.participants.all %}
93
          <span class="lastname">{{ participant.last_name }}</span> -
94
          {% endfor %}
95
          {{ next_rdv.act_type }}
96
          {% else %}
97
          Aucun
98
          {% endif %}
99
          {% if next_rdv.is_absent %} ({{ next_rdv.act.get_state }})</span>{% endif %}
100
      </li>
101
    </ul>
102
    {% if future_state %}
103
    <p><strong>État à venir du dossier:</strong>  {{ current_state.status.name.lower }} à partir du {{ current_state.date_selected|date:"d/m/Y" }}</p>
104
    {% else %}
105
    <p><strong>État courant du dossier:</strong> {{ current_state.status.name.lower }} depuis le {{ current_state.date_selected|date:"d/m/Y" }}</p>
106
    {% endif %}
107
    {% if object.pause_comment %}<p><label>Commentaire de la pause facturation:</label><br />{{ object.pause_comment }}</p>{% endif %}
108
  </div>
109

  
110
  <pdf:nextpage />
111

  
112
  <div class="block">
113
    <h2>Fiche administrative</h2>
114
    <h3>Inscription</h3>
115
    <ul>
116
      <li><label>Motif(analyse)</label> {{ object.analysemotive|default_if_none:'' }}</li>
117
      <li><label>Motif(famille)</label> {{ object.familymotive|default_if_none:'' }}</li>
118
      <li><label>Conseilleur</label> {{ object.provenance|default_if_none:'' }}</li>
119
      <li><label>Demandeur</label> {{ object.advicegiver|default_if_none:'' }}</li>
120
      <li><label>Lieu de provenance</label> {{ object.provenanceplace|default_if_none:'' }}</li>
121
    </ul>
122

  
123
    <h3>Sortie</h3>
124
    <ul>
125
      <li><label>Motif de sortie</label> {{ object.outmotive|default_if_none:'' }}</li>
126
      <li><label>Orientation</label> {{ object.outto|default_if_none:'' }}</li>
127
    </ul>
128

  
129
    <h3>Famille</h3>
130
    <ul>
131
      <li><label>Place dans la fratrie</label> {{ object.sibship_place|default_if_none:'' }}</li>
132
      <li><label>Nombre d'enfants dans la fratrie</label> {{ object.nb_children_family|default_if_none:'' }}</li>
133
      <li><label>Rang (gémellité)</label> {{ object.twinning_rank|default_if_none:'Aucun' }}</li>
134
      <li><label>Autorité parentale</label> {{ object.parental_authority|default_if_none:'' }}</li>
135
      <li><label>Situation familiale</label> {{ object.family_situation|default_if_none:'' }}</li>
136
      <li><label>Garde parentale</label> {{ object.child_custody|default_if_none:'' }}</li>
137
      <li><label>Profession de la mère</label> {{ object.job_mother|default_if_none:'' }}</li>
138
      <li><label>Profession du père</label> {{ object.job_father|default_if_none:'' }}</li>
139
      <li><label>Régime matrimonial de la mère</label> {{ object.rm_mother|default_if_none:'' }}</li>
140
      <li><label>Régime matrimonial du père</label> {{ object.rm_father|default_if_none:'' }}</li>
141
      <li><label>Commentaire</label> {{ object.family_comment|default_if_none:'' }}</li>
142
    </ul>
143

  
144
    <h3>Transport</h3>
145
    <ul>
146
      <li><label>Type de transport</label> {{ object.transporttype|default_if_none:'' }}</li>
147
      <li><label>Compagnie de transport</label> {{ object.transportcompany|default_if_none:'' }}</li>
148
      {% if last_prescription %}<li><label>Dernière prescription le</label> {{ last_prescription.created }}</li>{% endif %}
149
    </ul>
150

  
151
    <h3 style="background-color:#cccccc">Suivi du patient</h3>
152
    <ul>
153
      {% include "dossiers/patientrecord_print_coordinators.html" %}
154
      <li><label>Médecin extérieur</label> {{ object.externaldoctor|default_if_none:'' }}</li>
155
      <li><label>Intervenant extérieur</label> {{ object.externalintervener|default_if_none:'' }}</li>
156
    </ul>
157

  
158
    <h3>Mesures de protection</h3>
159
    <ul>
160
      {% for protection in object.protectionstate_set.all %}
161
      <li>
162
        <p>Depuis le {{ protection.start_date }} : {{ protection.status.name }}</p>
163
        <ul>
164
          {% if protection.end_date %}<li><label>Date de fin</label> : {{ protection.end_date }}</li>{% endif %}
165
          {% if protection.comment %}<li><label>Commentaire</label> : {{ protection.comment }}</li>{% endif %}
166
        </ul>
167
      </li>
168
      {% endfor %}
169
    </ul>
170
  </div>
171

  
172
  <pdf:nextpage />
173

  
174
  <div class="block">
175
    <h2>Adresses/contacts</h2>
176
    {% if object.policyholder.contact_comment %}
177
    <p>
178
      <label>Commentaire</label>
179
      {{ object.policyholder.contact_comment }}
180
    </p>
181
    {% endif %}
182
    <div>
183
      <table>
184
        <tr><td><h4 class="icon-user-space">Patient{% if object.policyholder.id == object.id %}<span class="normal">(Assuré)</span>{% endif %}</h4></td><td>{% include "dossiers/patientrecord_tab3_contact.html" with contact=object %}</td></tr>
185
        {% for contact in object.contacts.all %}
186
        {% if not contact.addresses.all %}
187
        <tr><td><h4>{% if contact.gender == 1 %}M.{% elif contact.gender == 2 %}Mme{% endif %}
188
              {{ contact.first_name }} <span class="lastname">{{ contact.last_name }}</span>{% if object.policyholder.id == contact.id %}<span class="normal">(Assuré)</span>{% endif %} {% if contact.id == object.id %} (PATIENT){% endif %}</h4></td><td>
189
            {% include "dossiers/patientrecord_tab3_contact.html" %}
190
        </td></tr>
191
        {% endif %}
192
        {% endfor %}
193
      </table>
194
    </div>
195

  
196
    <div>
197
      <table>
198
        {% for address in addresses %}
199
        <tr><td colspan="2">
200
            <h3>{{ address }}{% if address.place_of_life %}<span class="normal">(lieu de vie)</span>{% endif %}</h3>
201
            {% if address.phone %}<p><label>Téléphone</label> {{ address.phone|phone }}</span></p>{% endif %}
202
{% if address.comment %}<p><label>Commentaire :</label>{{ address.comment }}</p>{% endif %}</td></tr>
203
{% for contact in address.patientcontact_set.all  %}
204
{% if contact.id != object.id %}
205
<tr><td>
206
    <h4>{% if contact.gender == 1 %}M.{% elif contact.gender == 2 %}Mme{% endif %}{{ contact.first_name }} <span class="lastname">{{ contact.last_name }}</span>{% if object.policyholder.id == contact.id %}<span class="normal">(Assuré)</span>{% endif %}{% if contact.id == object.id %} (PATIENT){% endif %}</h4>
207
  </td><td>
208
    <div>
209
      {% include "dossiers/patientrecord_tab3_contact.html" %}
210
    </div>
211
</td></tr>
212
{% endif %}
213
{% endfor %}
214
</div>
215
</table>
216
</div>
217
{% endfor %}
218
</div>
219

  
220
<pdf:nextpage />
221

  
222
<div class="block">
223
  <h2>Prise en charge</h2>
224
  {% include "dossiers/patientrecord_tab4_notifs.html" %}
225
</div>
226

  
227
<pdf:nextpage />
228

  
229
<div class="block">
230
  <h2>Actes passés</h2>
231
  {% include "dossiers/patientrecord_tab5_actes_passes.html" %}
232
</div>
233

  
234
<pdf:nextpage />
235

  
236
<div class="block">
237
  <h2>Prochains rendez-vous</h2>
238
  {% include "dossiers/patientrecord_tab6_next_rdv.html" %}
239
</div>
240

  
241
<pdf:nextpage />
242

  
243
<div class="block">
244
  <h2>Socialisation</h2>
245
  {% include "dossiers/patientrecord_tab7_socialisation.html" %}
246
</div>
247

  
248
<pdf:nextpage />
249

  
250
<div class="block">
251
  <h2>Données à caractère médical</h2>
252
    <ul>
253
      <li><label>Taille (cm):</label> {{ object.size|default_if_none:'' }}</li>
254
      <li><label>Poids (gr):</label> {{ object.weight|default_if_none:'' }}</li>
255
      <li><label>Terme en semaines:</label> {{ object.pregnancy_term|default_if_none:'' }}</li>
256
      <li><label>Périmètre cranien:</label> {{ object.cranium_perimeter|default_if_none:'' }}</li>
257
      <li><label>Périmètre thoracique:</label> {{ object.chest_perimeter|default_if_none:'' }}</li>
258
      <li><label>Test d'Apgar (1):</label> {{ object.apgar_score_one|default_if_none:'' }}</li>
259
      <li><label>Test d'Apgar (5):</label> {{ object.apgar_score_two|default_if_none:'' }}</li>
260
      <li><label>Axe I : catégories cliniques</label>
261
        <ul>
262
        {% for m in object.mises_1.all %}
263
        <li>{{ m }}</li>
264
        {% endfor %}
265
        </ul>
266
      </li>
267

  
268
      <li><label>Axe II : facteurs organiques</label>
269
        <ul>
270
        {% for m in object.mises_2.all %}
271
        <li>{{ m }}</li>
272
        {% endfor %}
273
        </ul>
274
      </li>
275

  
276
      <li><label>Axe III : facteurs environnementaux</label>
277
        <ul>
278
        {% for m in object.mises_3.all %}
279
        <li>{{ m }}</li>
280
        {% endfor %}
281
        </ul>
282
      </li>
283
      {% if object.deficiency_intellectual %}
284
      <li><label>Déficiences intellectuelles: </label> {{ object.get_deficiency_intellectual_display }}</li>
285
      {% endif %}
286
      {% if object.deficiency_autism_and_other_ted %}
287
      <li><label>Autisme et autres TED:</label> {{ object.get_deficiency_autism_and_other_ted_display }}</li>
288
      {% endif %}
289
      {% if object.deficiency_mental_disorder %}
290
      <li><label>Troubles psychiques:</label> {{ object.get_deficiency_mental_disorder_display }}</li>
291
      {% endif %}
292
      {% if object.deficiency_learning_disorder %}
293
      <li><label>Troubles du langage et des apprentissages:</label> {{ object.get_deficiency_learning_disorder_display }}</li>
294
      {% endif %}
295
      {% if object.deficiency_auditory %}
296
      <li><label>Déficiences auditives:</label> {{ object.get_deficiency_auditory_display }}</li>
297
      {% endif %}
298
      {% if object.deficiency_visual %}
299
      <li><label>Déficiences visuelles:</label> {{ object.get_deficiency_visual_display }}</li>
300
      {% endif %}
301
      {% if object.deficiency_motor %}
302
      <li><label>Déficiences motrices:</label> {{ object.get_deficiency_motor_display }}</li>
303
      {% endif %}
304
      {% if object.deficiency_metabolic_disorder %}
305
      <li><label>Déficiences métaboliques:</label> {{ object.get_deficiency_metabolic_disorder_display }}</li>
306
      {% endif %}
307
      {% if object.deficiency_brain_damage %}
308
      <li><label>Cérébro-lésions:</label> {{ object.get_deficiency_brain_damage_display }}</li>
309
      {% endif %}
310
      {% if object.deficiency_polyhandicap %}
311
      <li><label>Polyhandicap</label></li>
312
      {% endif %}
313
      {% if object.deficiency_behavioral_disorder %}
314
      <li><label>Troubles de la conduite et du comportement:</label> {{ object.get_deficiency_brain_damage_display }}</li>
315
      {% endif %}
316
      {% if object.deficiency_in_diagnostic %}
317
      <li><label>En diagnostic</label></li>
318
      {% endif %}
319
      {% if object.deficiency_other_disorder %}
320
      <li><label>Autres types de déficience:</label> {{ object.get_deficiency_other_disorder_display }}</li>
321
      {% endif %}
322
    </ul>
323
</div>
324

  
325
</html>
calebasse/dossiers/templates/dossiers/patientrecord_print_coordinators.html
1
<li><label>Coordinateurs :</label>
2
  {% if object.coordinators.all %}
3
  <ul>
4
    {% for coordinator in object.coordinators.all %}
5
    <li>{{ coordinator.first_name }} <span class="lastname">{{ coordinator.last_name }}</span></li>
6
    {% endfor %}
7
  </ul>
8
  {% else %}Aucun{% endif %}
9
</li>
calebasse/dossiers/templates/dossiers/patientrecord_update.html
19 19
<h2><strong>{% if current_state.status.type == 'CLOS' %}<span class="highlight">{% endif %}<span class="lastname">{{ object.last_name }}</span> {{ object.first_name }}{% if object.paper_id %} - Dossier {{ object.paper_id}}{% endif %}{% if current_state.status.type == 'CLOS' %} clos</span>{% endif %}</strong></h2>
20 20
<span id="ajax-redirect" data-url="{{ object.id }}/view"/>
21 21
<a href="..">Retourner aux dossiers</a>
22
<form action="{% url "patientrecord_print" service object.id%}">
23
<button class="icon-print">{% trans "Imprimer tout le dossier" %}</button>
24
</form>
22 25
{% if 'validator' in role %}{% if object.can_be_deleted %}<button type="button" id="patientrecord-delete">Supprimer</button>{% endif %}{% endif %}
23 26
{% endblock %}
24 27

  
calebasse/dossiers/urls.py
11 11
        url(r'^waiting-queue$', 'patientrecord_waiting_queue'),
12 12
        url(r'^new$', 'new_patient_record'),
13 13
        url(r'^(?P<pk>\d+)/view$', 'patient_record'),
14
        url(r'^(?P<pk>\d+)/print$', 'patient_record_print', name='patientrecord_print'),
14 15
        url(r'^(?P<pk>\d+)/tab1$', 'tab1_general'),
15 16
        url(r'^(?P<pk>\d+)/tab2$', 'tab2_fiche_adm'),
16 17
        url(r'^(?P<pk>\d+)/tab3$', 'tab3_addresses'),
calebasse/dossiers/views.py
32 32
from calebasse.ressources.models import (Service,
33 33
    SocialisationDuration, MDPHRequest, MDPHResponse)
34 34
from calebasse.facturation.list_acts import list_acts_for_billing_CMPP_per_patient
35
from calebasse.facturation.invoice_header import render_to_pdf_file
35 36

  
36 37
from calebasse.decorators import validator_only
37 38

  
......
262 263

  
263 264
patient_record = PatientRecordView.as_view()
264 265

  
266
class PatientRecordPrint(cbv.DetailView):
267
    model = PatientRecord
268
    content_type = 'application/pdf'
269
    template_name = 'dossiers/patientrecord_print.html'
270

  
271
    def get_context_data(self, *args, **kwargs):
272
        context = super(PatientRecordPrint, self).get_context_data(*args, **kwargs)
273
        for view in (PatientRecordGeneralView, PatientRecordAdmView,
274
                     PatientRecordAddrView, PatientRecordNotifsView, PatientRecordOldActs,
275
                     PatientRecordNextAppointmentsView, PatientRecordSocialisationView):
276
            view_instance = view(request=self.request, object=self.object,
277
                                 service=self.service)
278
            context.update(view_instance.get_context_data(object=self.object))
279
        return context
280

  
281
    def get(self, request, *args, **kwargs):
282
        self.object = self.get_object()
283
        path = render_to_pdf_file([self.template_name],
284
                                  self.get_context_data(object = self.object))
285
        content = File(file(path))
286
        response = HttpResponse(content, self.content_type)
287
        response['Content-Length'] = content.size
288
        output = 'dossier_%s.pdf' % self.object.id
289
        response['Content-Disposition'] = \
290
            'attachment; filename="%s"' % output
291
        return response
292

  
293
patient_record_print = PatientRecordPrint.as_view()
294

  
265 295
class PatientRecordGeneralView(cbv.UpdateView):
266 296
    model = PatientRecord
267 297
    form_class = forms.GeneralForm
calebasse/static/js/calebasse.dialog.js
85 85
 * id: jQuery id where you want to replace form by ajaxForm
86 86
*/
87 87
function calebasse_ajax_form(id) {
88
  var selector = id + ' form';
88 89
  function onsuccess(response, status, xhr, form) {
89 90
    if ($('.errorlist', response).length != 0) {
90 91
      $(id).parent().html(response);
91
      $('form').ajaxForm({
92
      $(selector).ajaxForm({
92 93
        success: onsuccess,
93 94
      });
94 95
    }
......
96 97
      window.location.reload(true);
97 98
    }
98 99
  }
99
  $('form').ajaxForm({
100
  $(selector).ajaxForm({
100 101
    success: onsuccess,
101 102
  });
102 103
}
103
-