Project

General

Profile

Download (28.4 KB) Statistics
| Branch: | Tag: | Revision:

calebasse / calebasse / dossiers / models.py @ d72af982

1
# -*- coding: utf-8 -*-
2

    
3
import logging
4
import os
5

    
6
from datetime import datetime, date
7
from dateutil.relativedelta import relativedelta
8

    
9
from django import forms
10
from django.conf import settings
11
from django.db import models
12
from django.contrib.auth.models import User
13

    
14
import reversion
15

    
16
from calebasse.choices import LARGE_REGIME_CHOICES
17
from calebasse.models import PhoneNumberField, ZipCodeField
18
from calebasse.personnes.models import People
19
from calebasse.ressources.models import (ServiceLinkedAbstractModel,
20
        NamedAbstractModel, Service)
21
from calebasse.actes.validation import are_all_acts_of_the_day_locked
22

    
23
DEFAULT_ACT_NUMBER_DIAGNOSTIC = 6
24
DEFAULT_ACT_NUMBER_TREATMENT = 30
25
DEFAULT_ACT_NUMBER_PROLONGATION = 10
26
VALIDITY_PERIOD_TREATMENT_HEALTHCARE_DAYS = 0
27
VALIDITY_PERIOD_TREATMENT_HEALTHCARE_MONTHS = 0
28
VALIDITY_PERIOD_TREATMENT_HEALTHCARE_YEARS = 1
29

    
30
logger = logging.getLogger('calebasse.dossiers')
31

    
32

    
33
class HealthCare(models.Model):
34

    
35
    class Meta:
36
        app_label = 'dossiers'
37

    
38
    start_date = models.DateField(verbose_name=u"Date de début")
39
    request_date = models.DateField(verbose_name=u"Date de Demande",
40
        blank=True, null=True)
41
    agree_date = models.DateField(verbose_name=u"Date de d'accord",
42
        blank=True, null=True)
43
    insist_date = models.DateField(verbose_name=u"Date de relance",
44
        blank=True, null=True)
45
    patient = models.ForeignKey('dossiers.PatientRecord',
46
        verbose_name=u'Dossier patient')
47
    created = models.DateTimeField(u'Création', auto_now_add=True)
48
    author = \
49
        models.ForeignKey(User,
50
        verbose_name=u'Auteur', blank=True, null=True)
51
    comment = models.TextField(max_length=3000, blank=True, null=True, verbose_name=u"Commentaire")
52

    
53
    def get_nb_acts_cared(self):
54
        return len(self.act_set.all())
55

    
56

    
57
class CmppHealthCareDiagnostic(HealthCare):
58

    
59
    class Meta:
60
        app_label = 'dossiers'
61

    
62
    act_number = models.IntegerField(default=DEFAULT_ACT_NUMBER_DIAGNOSTIC, verbose_name=u"Nombre d'actes couverts")
63

    
64
    def get_act_number(self):
65
        return self.act_number
66

    
67
    def set_act_number(self, value):
68
        if value < self.get_nb_acts_cared():
69
            raise Exception("La valeur doit être supérieur au "
70
                "nombre d'actes déjà pris en charge")
71
        self.act_number = value
72
        self.save()
73

    
74
    def save(self, **kwargs):
75
        self.start_date = \
76
            datetime(self.start_date.year, self.start_date.month,
77
                self.start_date.day)
78
        super(CmppHealthCareDiagnostic, self).save(**kwargs)
79

    
80

    
81
class CmppHealthCareTreatment(HealthCare):
82

    
83
    class Meta:
84
        app_label = 'dossiers'
85

    
86
    act_number = models.IntegerField(default=DEFAULT_ACT_NUMBER_TREATMENT,
87
            verbose_name=u"Nombre d'actes couverts")
88
    end_date = models.DateField(verbose_name=u"Date de fin")
89
    prolongation = models.IntegerField(default=0,
90
            verbose_name=u'Prolongation')
91

    
92
    def get_act_number(self):
93
        if self.is_extended():
94
            return self.act_number + self.prolongation
95
        return self.act_number
96

    
97
    def set_act_number(self, value):
98
        if value < self.get_nb_acts_cared():
99
            raise Exception("La valeur doit être supérieur au "
100
                "nombre d'actes déjà pris en charge")
101
        self.act_number = value
102
        self.save()
103

    
104
    def is_extended(self):
105
        if self.prolongation > 0:
106
            return True
107
        return False
108

    
109
    def add_prolongation(self, value=None):
110
        if not value:
111
            value = DEFAULT_ACT_NUMBER_PROLONGATION
112
        if self.is_extended():
113
            raise Exception(u'Prise en charge déja prolongée')
114
        self.prolongation = value
115
        self.save()
116

    
117
    def save(self, **kwargs):
118
        self.start_date = \
119
            datetime(self.start_date.year, self.start_date.month,
120
                self.start_date.day)
121
        self.end_date = self.start_date + \
122
            relativedelta(years=VALIDITY_PERIOD_TREATMENT_HEALTHCARE_YEARS) + \
123
            relativedelta(months=VALIDITY_PERIOD_TREATMENT_HEALTHCARE_MONTHS) + \
124
            relativedelta(days=VALIDITY_PERIOD_TREATMENT_HEALTHCARE_DAYS)
125
        super(CmppHealthCareTreatment, self).save(**kwargs)
126

    
127

    
128
class SessadHealthCareNotification(HealthCare):
129

    
130
    class Meta:
131
        app_label = 'dossiers'
132

    
133
    end_date = models.DateField()
134

    
135
    def save(self, **kwargs):
136
        self.start_date = \
137
            datetime(self.start_date.year, self.start_date.month,
138
                self.start_date.day)
139
        self.end_date = \
140
            datetime(self.end_date.year, self.end_date.month,
141
                self.end_date.day)
142
        super(SessadHealthCareNotification, self).save(**kwargs)
143

    
144
reversion.register(CmppHealthCareDiagnostic, follow=['healthcare_ptr'])
145
reversion.register(CmppHealthCareTreatment, follow=['healthcare_ptr'])
146
reversion.register(SessadHealthCareNotification, follow=['healthcare_ptr'])
147

    
148
class Status(NamedAbstractModel):
149

    
150
    class Meta:
151
        app_label = 'dossiers'
152
        verbose_name = u"Statut d'un état"
153
        verbose_name_plural = u"Statuts d'un état"
154

    
155
    type = models.CharField(max_length=80)
156
    services = models.ManyToManyField('ressources.Service')
157

    
158

    
159
class FileState(models.Model):
160

    
161
    class Meta:
162
        app_label = 'dossiers'
163
        verbose_name = u'Etat du dossier patient'
164
        verbose_name_plural = u'Etats du dossier patient'
165

    
166
    patient = models.ForeignKey('dossiers.PatientRecord',
167
        verbose_name=u'Dossier patient')
168
    status = models.ForeignKey('dossiers.Status', verbose_name=u'Statut')
169
    created = models.DateTimeField(u'Création', auto_now_add=True)
170
    date_selected = models.DateTimeField()
171
    author = \
172
        models.ForeignKey(User,
173
        verbose_name=u'Auteur')
174
    comment = models.TextField(max_length=3000, blank=True, null=True)
175
    previous_state = models.ForeignKey('FileState',
176
        verbose_name=u'Etat précédent', blank=True, null=True)
177

    
178
    def get_next_state(self):
179
        try:
180
            return FileState.objects.get(previous_state=self)
181
        except:
182
            return None
183

    
184
    def save(self, **kwargs):
185
        self.date_selected = \
186
                datetime(self.date_selected.year,
187
                        self.date_selected.month, self.date_selected.day)
188
        super(FileState, self).save(**kwargs)
189

    
190
    def __unicode__(self):
191
        return self.status.name + ' ' + str(self.date_selected)
192

    
193
    def delete(self, *args, **kwargs):
194
        next_state = self.get_next_state()
195
        if next_state and self.previous_state:
196
            next_state.previous_state = self.previous_state
197
            next_state.save()
198
        if self.patient.last_state == self:
199
            self.patient.last_state = self.previous_state
200
            self.patient.save()
201
        super(FileState, self).delete(*args, **kwargs)
202

    
203
class PatientAddress(models.Model):
204

    
205
    display_name = models.CharField(max_length=276,
206
            verbose_name=u'Adresse complète', editable=False)
207
    phone = PhoneNumberField(verbose_name=u"Téléphone", blank=True, null=True)
208
    fax = PhoneNumberField(verbose_name=u"Fax", blank=True, null=True)
209
    place_of_life = models.BooleanField(verbose_name=u"Lieu de vie")
210
    number = models.CharField(max_length=12,
211
            verbose_name=u"Numéro", blank=True, null=True)
212
    street = models.CharField(max_length=100,
213
            verbose_name=u"Rue", blank=True, null=True)
214
    address_complement = models.CharField(max_length=100,
215
            blank=True, null=True,
216
            verbose_name=u"Complément d'adresse")
217
    zip_code = ZipCodeField(verbose_name=u"Code postal", blank=True, null=True)
218
    city = models.CharField(max_length=60,
219
            verbose_name=u"Ville", blank=True, null=True)
220
    comment = models.TextField(verbose_name=u"Commentaire",
221
            null=True, blank=True)
222

    
223
    def __unicode__(self):
224
        return self.display_name
225

    
226
    def save(self, **kwargs):
227
        self.display_name = ''
228
        if self.number:
229
            self.display_name += self.number + ' '
230
        if self.street:
231
            self.display_name += self.street + ' '
232
        if self.address_complement:
233
            self.display_name += self.address_complement + ' '
234
        if self.zip_code:
235
            self.display_name += self.zip_code + ' '
236
        if self.city:
237
            self.display_name += self.city + ' '
238
        super(PatientAddress, self).save(**kwargs)
239

    
240

    
241
class PatientContact(People):
242
    class Meta:
243
        verbose_name = u'Contact patient'
244
        verbose_name_plural = u'Contacts patient'
245

    
246
    mobile = PhoneNumberField(verbose_name=u"Téléphone mobile", blank=True, null=True)
247
    # carte vitale
248
    social_security_id = models.CharField(max_length=13, verbose_name=u"NIR",
249
            null=True, blank=True)
250
    birthdate = models.DateField(verbose_name=u"Date de naissance",
251
            null=True, blank=True)
252
    birthplace = models.CharField(max_length=100, verbose_name=u"Lieu de naissance",
253
            null=True, blank=True)
254
    twinning_rank = models.IntegerField(verbose_name=u"Rang (gémellité)",
255
            null=True, blank=True)
256
    thirdparty_payer = models.BooleanField(verbose_name=u'Tiers-payant',
257
            default=False)
258
    begin_rights = models.DateField(verbose_name=u"Début de droits",
259
            null=True, blank=True)
260
    end_rights = models.DateField(verbose_name=u"Fin de droits",
261
            null=True, blank=True)
262
    health_center = models.ForeignKey('ressources.HealthCenter',
263
            verbose_name=u"Centre d'assurance maladie",
264
            null=True, blank=True)
265
    other_health_center = models.CharField(verbose_name=u"Centre spécifique",
266
            max_length=4,
267
            null=True, blank=True)
268
    job = models.ForeignKey('ressources.Job',
269
            related_name="job",
270
            verbose_name=u"Profession",
271
            null=True, blank=True, default=None)
272
    parente = models.ForeignKey('ressources.PatientRelatedLink',
273
            verbose_name=u"Lien avec le patient (Parenté)",
274
            null=True, blank=True, default=None)
275

    
276
    addresses = models.ManyToManyField('PatientAddress', verbose_name=u"Adresses")
277
    contact_comment = models.TextField(verbose_name=u"Commentaire",
278
            null=True, blank=True)
279

    
280
    old_contact_id = models.CharField(max_length=256,
281
            verbose_name=u'Ancien ID du contact', blank=True, null=True)
282

    
283
    def get_control_key(self):
284
        if self.social_security_id:
285
            nir = self.social_security_id
286
            try:
287
                # Corse dpt 2A et 2B
288
                minus = 0
289
                if nir[6] in ('A', 'a'):
290
                    nir = [c for c in nir]
291
                    nir[6] = '0'
292
                    nir = ''.join(nir)
293
                    minus = 1000000
294
                elif nir[6] in ('B', 'b'):
295
                    nir = [c for c in nir]
296
                    nir[6] = '0'
297
                    nir = ''.join(nir)
298
                    minus = 2000000
299
                nir = int(nir) - minus
300
                return (97 - (nir % 97))
301
            except Exception, e:
302
                print str(e)
303
                return None
304
        return None
305

    
306

    
307
class PatientRecordManager(models.Manager):
308
    def for_service(self, service):
309
        return self.filter(service=service)
310

    
311
class PatientRecord(ServiceLinkedAbstractModel, PatientContact):
312
    objects = PatientRecordManager()
313

    
314
    class Meta:
315
        verbose_name = u'Dossier'
316
        verbose_name_plural = u'Dossiers'
317

    
318
    created = models.DateTimeField(u'création', auto_now_add=True)
319
    creator = \
320
        models.ForeignKey(User,
321
        verbose_name=u'Créateur dossier patient',
322
        editable=True)
323
    policyholder = models.ForeignKey('PatientContact',
324
            null=True, blank=True,
325
            verbose_name="Assuré", related_name="+",
326
            on_delete=models.SET_NULL)
327
    contacts = models.ManyToManyField('PatientContact',
328
            related_name='contact_of')
329
    nationality = models.CharField(verbose_name=u"Nationalité",
330
            max_length=70, null=True, blank=True)
331
    paper_id = models.CharField(max_length=6,
332
            verbose_name=u"N° dossier papier",
333
            null=True, blank=True)
334
    last_state = models.ForeignKey(FileState, related_name='+',
335
            null=True, on_delete=models.SET_NULL)
336
    comment = models.TextField(verbose_name=u"Commentaire",
337
            null=True, blank=True, default=None)
338
    pause = models.BooleanField(verbose_name=u"Pause facturation",
339
            default=False)
340
    confidential = models.BooleanField(verbose_name=u"Confidentiel",
341
            default=False)
342
    socialisation_durations = models.ManyToManyField('ressources.SocialisationDuration',
343
            related_name='socialisation_duration_of')
344
    mdph_requests = models.ManyToManyField('ressources.MDPHRequest',
345
            related_name='mdph_requests_of')
346
    mdph_responses = models.ManyToManyField('ressources.MDPHResponse',
347
            related_name='mdph_responses_of')
348

    
349
    # Physiology and health data
350
    size = models.IntegerField(verbose_name=u"Taille (cm)",
351
            null=True, blank=True, default=None)
352
    weight = models.IntegerField(verbose_name=u"Poids (g)",
353
            null=True, blank=True, default=None)
354
    pregnancy_term = models.IntegerField(verbose_name=u"Terme en semaines",
355
            null=True, blank=True, default=None)
356
    cranium_perimeter = models.DecimalField(verbose_name=u"Périmètre cranien", max_digits=5, decimal_places=2,
357
            null=True, blank=True, default=None)
358
    chest_perimeter = models.DecimalField(verbose_name=u"Périmètre thoracique", max_digits=5, decimal_places=2,
359
            null=True, blank=True, default=None)
360
    apgar_score_one = models.IntegerField(verbose_name=u"Test d'Apgar (1)",
361
            null=True, blank=True, default=None)
362
    apgar_score_two = models.IntegerField(verbose_name=u"Test d'Apgar (5)",
363
            null=True, blank=True, default=None)
364
    mises_1 = models.ManyToManyField('ressources.CodeCFTMEA', related_name="mises1",
365
            verbose_name=u"Axe I : catégories cliniques",
366
            null=True, blank=True, default=None)
367
    mises_2 = models.ManyToManyField('ressources.CodeCFTMEA', related_name="mises2",
368
            verbose_name=u"Axe II : facteurs organiques",
369
            null=True, blank=True, default=None)
370
    mises_3 = models.ManyToManyField('ressources.CodeCFTMEA', related_name="mises3",
371
            verbose_name=u"Axe II : facteurs environnementaux",
372
            null=True, blank=True, default=None)
373

    
374
    # Inscription motive
375
    analysemotive = models.ForeignKey('ressources.AnalyseMotive',
376
            verbose_name=u"Motif (analysé)",
377
            null=True, blank=True, default=None)
378
    familymotive = models.ForeignKey('ressources.FamilyMotive',
379
            verbose_name=u"Motif (famille)",
380
            null=True, blank=True, default=None)
381
    provenance = models.ForeignKey('ressources.Provenance',
382
            verbose_name=u"Conseilleur",
383
            null=True, blank=True, default=None)
384
    advicegiver = models.ForeignKey('ressources.AdviceGiver',
385
            verbose_name=u"Demandeur",
386
            null=True, blank=True, default=None)
387

    
388
    # Out motive
389
    outmotive = models.ForeignKey('ressources.OutMotive',
390
            verbose_name=u"Motif de sortie",
391
            null=True, blank=True, default=None)
392
    outto = models.ForeignKey('ressources.OutTo',
393
            verbose_name=u"Orientation",
394
            null=True, blank=True, default=None)
395

    
396
    # Family
397
    sibship_place = models.IntegerField(verbose_name=u"Place dans la fratrie",
398
            null=True, blank=True, default=None)
399
    nb_children_family = models.IntegerField(verbose_name=u"Nombre d'enfants dans la fratrie",
400
            null=True, blank=True, default=None)
401
    parental_authority = models.ForeignKey('ressources.ParentalAuthorityType',
402
            verbose_name=u"Autorité parentale",
403
            null=True, blank=True, default=None)
404
    family_situation = models.ForeignKey('ressources.FamilySituationType',
405
            verbose_name=u"Situation familiale",
406
            null=True, blank=True, default=None)
407
    child_custody = models.ForeignKey('ressources.ParentalCustodyType',
408
            verbose_name=u"Garde parentale",
409
            null=True, blank=True, default=None)
410
    job_mother = models.ForeignKey('ressources.Job',
411
            related_name="job_mother",
412
            verbose_name=u"Profession de la mère",
413
            null=True, blank=True, default=None)
414
    job_father = models.ForeignKey('ressources.Job',
415
            related_name="job_father",
416
            verbose_name=u"Profession du père",
417
            null=True, blank=True, default=None)
418
    rm_mother = models.ForeignKey('ressources.MaritalStatusType',
419
            related_name="rm_mother",
420
            verbose_name=u"Régime matrimonial de la mère",
421
            null=True, blank=True, default=None)
422
    rm_father = models.ForeignKey('ressources.MaritalStatusType',
423
            related_name="rm_father",
424
            verbose_name=u"Régime matrimonial du père",
425
            null=True, blank=True, default=None)
426
    family_comment = models.TextField(verbose_name=u"Commentaire",
427
            null=True, blank=True, default=None)
428

    
429
    # Transport
430
    transporttype = models.ForeignKey('ressources.TransportType',
431
            verbose_name=u"Type de transport",
432
            null=True, blank=True, default=None)
433
    transportcompany = models.ForeignKey('ressources.TransportCompany',
434
            verbose_name=u"Compagnie de transport",
435
            null=True, blank=True, default=None)
436

    
437
    # FollowUp
438
    coordinators = models.ManyToManyField('personnes.Worker',
439
            verbose_name=u"Coordinateurs",
440
            null=True, blank=True, default=None)
441
    externaldoctor = models.ForeignKey('personnes.ExternalTherapist',
442
            verbose_name=u"Médecin extérieur",
443
            null=True, blank=True, default=None)
444
    externalintervener = models.ForeignKey('personnes.ExternalWorker',
445
            verbose_name=u"Intervenant extérieur",
446
            null=True, blank=True, default=None)
447

    
448
    old_id = models.CharField(max_length=256,
449
            verbose_name=u'Ancien ID', blank=True, null=True)
450
    old_old_id = models.CharField(max_length=256,
451
            verbose_name=u'Ancien ancien ID', blank=True, null=True)
452

    
453
    def save(self, *args, **kwargs):
454
        if not getattr(self, 'service', None):
455
            raise Exception('The field service is mandatory.')
456
        super(PatientRecord, self).save(*args, **kwargs)
457

    
458
    def get_state(self):
459
        return self.last_state
460

    
461
    def get_initial_state(self):
462
        return self.filestate_set.order_by('date_selected')[0]
463

    
464
    def get_current_state(self):
465
        today = date.today()
466
        return self.get_state_at_day(today)
467

    
468
    def get_state_at_day(self, date):
469
        state = self.get_state()
470
        while(state):
471
            if datetime(state.date_selected.year,
472
                    state.date_selected.month, state.date_selected.day) <= \
473
                    datetime(date.year, date.month, date.day):
474
                return state
475
            state = state.previous_state
476
        return self.get_state()
477

    
478
    def was_in_state_at_day(self, date, status_type):
479
        state_at_day = self.get_state_at_day(date)
480
        if state_at_day and state_at_day.status.type == status_type:
481
            return True
482
        return False
483

    
484
    def get_states_history(self):
485
        return self.filestate_set.order_by('date_selected')
486

    
487
    def can_be_deleted(self):
488
        for act in self.act_set.all():
489
            if act.is_state('VALIDE'):
490
                return False
491
        return True
492

    
493
    def delete(self, *args, **kwargs):
494
        if self.can_be_deleted():
495
            super(PatientRecord, self).delete(*args, **kwargs)
496

    
497
    def get_ondisk_directory(self, service):
498
        if not settings.PATIENT_FILES_BASE_DIRECTORY:
499
            return None
500

    
501
        dirnames = []
502
        dirname = self.last_name.upper()
503
        dirnames.append(dirname)
504
        if self.first_name:
505
            dirname = '%s %s' % (dirname, self.first_name)
506
            dirnames.append(dirname)
507
        if self.paper_id:
508
            dirname = '%s %s' % (dirname, self.paper_id)
509
            dirnames.append(dirname)
510

    
511
        for i, dirname in enumerate(dirnames):
512
            fullpath = os.path.join(settings.PATIENT_FILES_BASE_DIRECTORY, service, dirname)
513
            try:
514
                next_fullpath = os.path.join(settings.PATIENT_FILES_BASE_DIRECTORY, service, dirnames[i+1])
515
            except IndexError:
516
                pass
517
            else:
518
                 if os.path.exists(fullpath) and not os.path.exists(next_fullpath):
519
                     os.rename(fullpath, next_fullpath)
520
                 continue
521
            if not os.path.exists(fullpath):
522
                os.makedirs(fullpath)
523
            for subdir in settings.PATIENT_SUBDIRECTORIES:
524
                subdir_fullpath = os.path.join(fullpath, subdir)
525
                if not os.path.exists(subdir_fullpath):
526
                    os.makedirs(subdir_fullpath)
527
        return fullpath
528

    
529
    def get_client_side_directory(self, service):
530
        directory = self.get_ondisk_directory(service)
531
        if not directory:
532
            return None
533
        if not settings.CLIENT_SIDE_PATIENT_FILES_BASE_DIRECTORY:
534
            return None
535
        return os.path.join(settings.CLIENT_SIDE_PATIENT_FILES_BASE_DIRECTORY,
536
                            directory[len(settings.PATIENT_FILES_BASE_DIRECTORY)+1:])
537

    
538
    def set_state(self, status, author, date_selected=None, comment=None):
539
        if not author:
540
            raise Exception('Missing author to set state')
541
        if not date_selected:
542
            date_selected = datetime.now()
543
        current_state = self.get_state()
544
        if not current_state:
545
            raise Exception('Invalid patient record. '
546
                'Missing current state.')
547
        if date_selected < current_state.date_selected:
548
            raise Exception('You cannot set a state starting the %s that '
549
                'is before the previous state starting at day %s.' % \
550
                (str(date_selected), str(current_state.date_selected)))
551
        filestate = FileState.objects.create(patient=self, status=status,
552
            date_selected=date_selected, author=author, comment=comment,
553
            previous_state=current_state)
554
        self.last_state = filestate
555
        self.save()
556

    
557
    def change_day_selected_of_state(self, state, new_date):
558
        if state.previous_state:
559
            if new_date < state.previous_state.date_selected:
560
                raise Exception('You cannot set a state starting the %s '
561
                    'before the previous state starting at day %s.' % \
562
                    (str(new_date), str(state.previous_state.date_selected)))
563
        next_state = state.get_next_state()
564
        if next_state:
565
            if new_date > next_state.date_selected:
566
                raise Exception('You cannot set a state starting the %s '
567
                    'after the following state starting at day %s.' % \
568
                    (str(new_date), str(next_state.date_selected)))
569
        state.date_selected = new_date
570
        state.save()
571

    
572
    def remove_state(self, state):
573
        if state.patient.id != self.id:
574
            raise Exception('The state given is not about this patient '
575
                'record but about %s' % state.patient)
576
        next_state = state.get_next_state()
577
        if not next_state:
578
            self.remove_last_state()
579
        else:
580
            next_state.previous_state = state.previous_state
581
            next_state.save()
582
            state.delete()
583

    
584
    def remove_last_state(self):
585
        try:
586
            self.get_state().delete()
587
        except:
588
            pass
589

    
590
    # START Specific to sessad healthcare
591
    def get_last_notification(self):
592
        return SessadHealthCareNotification.objects.filter(patient=self, ).\
593
            latest('end_date')
594

    
595
    def days_before_notification_expiration(self):
596
        today = datetime.today()
597
        notification = self.get_last_notification(self)
598
        if not notification:
599
            return 0
600
        if notification.end_date < today:
601
            return 0
602
        else:
603
            return notification.end_date - today
604
    # END Specific to sessad healthcare
605

    
606
    # START Specific to cmpp healthcare
607
    def create_diag_healthcare(self, modifier):
608
        """
609
            Gestion de l'inscription automatique.
610

    
611
            Si un premier acte est validé alors une prise en charge
612
            diagnostique est ajoutée. Cela fera basculer le dossier dans l'état
613
            en diagnostic.
614

    
615
            A voir si auto ou manuel :
616
            Si ce n'est pas le premier acte validé mais que l'acte précédement
617
            facturé a plus d'un an, on peut créer une prise en charge
618
            diagnostique. Même s'il y a une prise en charge de traitement
619
            expirée depuis moins d'un an donc renouvelable.
620

    
621
        """
622
        acts = self.act_set.order_by('date')
623
        hcds = CmppHealthCareDiagnostic.objects.filter(patient=self).order_by('-start_date')
624
        if not hcds:
625
            # Pas de prise en charge, on recherche l'acte facturable le plus
626
            # ancien, on crée une pc diag à la même date.
627
            for act in acts:
628
                if act.is_state('VALIDE') and act.is_billable():
629
                    CmppHealthCareDiagnostic(patient=self, author=modifier,
630
                        start_date=act.date).save()
631
                    break
632
        else:
633
            # On recherche l'acte facturable non facturé le plus ancien et
634
            # l'on regarde s'il a plus d'un an
635
            try:
636
                last_billed_act = self.act_set.filter(is_billed=True).\
637
                    latest('date')
638
                if last_billed_act:
639
                    for act in acts:
640
                        if act.is_state('VALIDE') and \
641
                                act.is_billable() and \
642
                                (act.date - last_billed_act.date).days >= 365:
643
                            return True
644
            except:
645
                pass
646
        return False
647

    
648
    def automated_switch_state(self, modifier):
649
        # Quel est le dernier acte facturable.
650
        acts = self.act_set.order_by('-date')
651
        # Si cet acte peut-être pris en charge en diagnostic c'est un acte de
652
        # diagnostic, sinon c'est un acte de traitement.
653
        last_state_services = self.last_state.status.\
654
                services.values_list('name', flat=True)
655
        cmpp = Service.objects.get(name='CMPP')
656
        for act in acts:
657
            if act.is_state('VALIDE') and act.is_billable() and \
658
                    act.date >= self.get_state().date_selected.date() and \
659
                    are_all_acts_of_the_day_locked(act.date):
660
                cared, hc = act.is_act_covered_by_diagnostic_healthcare()
661
                if hc:
662
                    if (self.last_state.status.type == "ACCUEIL" \
663
                            or self.last_state.status.type == "TRAITEMENT") \
664
                            and "CMPP" in last_state_services:
665
                        status = Status.objects.filter(type="DIAGNOSTIC").\
666
                                filter(services__name='CMPP')[0]
667
                        try:
668
                            self.set_state(status, modifier,
669
                                date_selected=act.date)
670
                        except:
671
                            pass
672
                # Sinon, si le dossier est en diag, s'il ne peut être couvert
673
                # en diag, il est en traitement.
674
                elif self.last_state.status.type == "DIAGNOSTIC" and \
675
                        "CMPP" in last_state_services:
676
                    status = Status.objects.filter(type="TRAITEMENT").\
677
                            filter(services__name='CMPP')[0]
678
                    try:
679
                        self.set_state(status, modifier,
680
                                date_selected=act.date)
681
                    except:
682
                        pass
683
                break
684
    # END Specific to cmpp healthcare
685

    
686
reversion.register(PatientRecord, follow=['people_ptr'])
687

    
688

    
689
def create_patient(first_name, last_name, service, creator,
690
        date_selected=None):
691
    logger.debug('create_patient: creation for patient %s %s in service %s '
692
        'by %s' % (first_name, last_name, service, creator))
693
    if not (first_name and last_name and service and creator):
694
        raise Exception('Missing parameter to create a patient record.')
695
    status = Status.objects.filter(type="ACCUEIL").filter(services=service)
696
    if not status:
697
        raise Exception('%s has no ACCEUIL status' % service.name)
698
    patient = PatientRecord.objects.create(first_name=first_name,
699
            last_name=last_name, service=service,
700
            creator=creator)
701
    fs = FileState(status=status[0], author=creator, previous_state=None)
702
    if not date_selected:
703
        date_selected = patient.created
704
    fs.patient = patient
705
    fs.date_selected = date_selected
706
    fs.save()
707
    patient.last_state = fs
708
    patient.save()
709
    return patient
(5-5/9)