Projet

Général

Profil

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

Serghei Mihai, 21 août 2014 17:58

Télécharger (21,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                        |  33 ++-
 calebasse/static/js/calebasse.dialog.js            |   5 +-
 6 files changed, 373 insertions(+), 3 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
11 11
from django.views.generic.edit import DeleteView
12 12
from django.contrib import messages
13 13
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
14
from django.core.urlresolvers import reverse
14 15
from django.core.files import File
15 16
from django.forms import Form
16 17
from django.utils import formats
......
32 33
from calebasse.ressources.models import (Service,
33 34
    SocialisationDuration, MDPHRequest, MDPHResponse)
34 35
from calebasse.facturation.list_acts import list_acts_for_billing_CMPP_per_patient
36
from calebasse.facturation.invoice_header import render_to_pdf_file
35 37

  
36 38
from calebasse.decorators import validator_only
37 39

  
......
262 264

  
263 265
patient_record = PatientRecordView.as_view()
264 266

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

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

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

  
294
patient_record_print = PatientRecordPrint.as_view()
295

  
265 296
class PatientRecordGeneralView(cbv.UpdateView):
266 297
    model = PatientRecord
267 298
    form_class = forms.GeneralForm
......
338 369
        ctx['status'], ctx['hc_status'] = get_status(ctx, self.request.user)
339 370
        if ctx['object'].service.slug == "cmpp":
340 371
            (acts_not_locked, days_not_locked, acts_not_valide,
341
            acts_not_billable, acts_pause, acts_per_hc, acts_losts) = \
372
            acts_not_biPllable, acts_pause, acts_per_hc, acts_losts) = \
342 373
                list_acts_for_billing_CMPP_per_patient(self.object,
343 374
                    datetime.today(), self.service)
344 375
            ctx['acts_losts'] = acts_losts
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
-