Project

General

Profile

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

calebasse / calebasse / dossiers / models.py @ 10294684

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

    
3
import logging
4

    
5
from datetime import datetime
6
from datetime import timedelta
7

    
8
from django.db import models
9
from django.contrib.auth.models import User
10

    
11
from calebasse.personnes.models import People
12
from calebasse.ressources.models import ServiceLinkedAbstractModel
13
from calebasse.dossiers.states import STATES, STATE_ACCUEIL
14
from calebasse.actes.validation import are_all_acts_of_the_day_locked
15

    
16
DEFAULT_ACT_NUMBER_DIAGNOSTIC = 6
17
DEFAULT_ACT_NUMBER_TREATMENT = 30
18
DEFAULT_ACT_NUMBER_PROLONGATION = 10
19
VALIDITY_PERIOD_TREATMENT_HEALTHCARE = 365
20

    
21
logger = logging.getLogger('calebasse.dossiers')
22

    
23

    
24
class HealthCare(models.Model):
25

    
26
    class Meta:
27
        app_label = 'dossiers'
28

    
29
    patient = models.ForeignKey('dossiers.PatientRecord',
30
        verbose_name=u'Dossier patient', editable=False)
31
    created = models.DateTimeField(u'Création', auto_now_add=True)
32
    author = \
33
        models.ForeignKey(User,
34
        verbose_name=u'Auteur', editable=False)
35
    comment = models.TextField(max_length=3000, blank=True, null=True)
36
    start_date = models.DateTimeField()
37

    
38

    
39
class CmppHealthCareDiagnostic(HealthCare):
40

    
41
    class Meta:
42
        app_label = 'dossiers'
43

    
44
    _act_number = models.IntegerField(default=DEFAULT_ACT_NUMBER_DIAGNOSTIC)
45

    
46
    def get_act_number(self):
47
        return self._act_number
48

    
49
    def save(self, **kwargs):
50
        self.start_date = \
51
            datetime(self.start_date.year, self.start_date.month,
52
                self.start_date.day)
53
        super(CmppHealthCareDiagnostic, self).save(**kwargs)
54

    
55

    
56
class CmppHealthCareTreatment(HealthCare):
57

    
58
    class Meta:
59
        app_label = 'dossiers'
60

    
61
    _act_number = models.IntegerField(default=DEFAULT_ACT_NUMBER_TREATMENT)
62
    end_date = models.DateTimeField()
63
    prolongation = models.IntegerField(default=0,
64
            verbose_name=u'Prolongation')
65

    
66
    def get_act_number(self):
67
        if self.is_extended():
68
            return self._act_number + self.prolongation
69
        return self._act_number
70

    
71
    def is_extended(self):
72
        if self.prolongation > 0:
73
            return True
74
        return False
75

    
76
    def add_prolongation(self, value=None):
77
        if not value:
78
            value = DEFAULT_ACT_NUMBER_PROLONGATION
79
        if self.is_extended():
80
            raise Exception(u'Prise en charge déja prolongée')
81
        self.prolongation = value
82
        self.save()
83

    
84
    def save(self, **kwargs):
85
        self.start_date = \
86
            datetime(self.start_date.year, self.start_date.month,
87
                self.start_date.day)
88
        self.end_date = self.start_date + \
89
            timedelta(days=VALIDITY_PERIOD_TREATMENT_HEALTHCARE)
90

    
91
        super(CmppHealthCareTreatment, self).save(**kwargs)
92

    
93

    
94
class SessadHealthCareNotification(HealthCare):
95

    
96
    class Meta:
97
        app_label = 'dossiers'
98

    
99
    end_date = models.DateTimeField()
100

    
101
    def save(self, **kwargs):
102
        self.start_date = \
103
            datetime(self.start_date.year, self.start_date.month,
104
                self.start_date.day)
105
        self.end_date = \
106
            datetime(self.end_date.year, self.end_date.month,
107
                self.end_date.day)
108
        super(SessadHealthCareNotification, self).save(**kwargs)
109

    
110

    
111
class FileState(models.Model):
112

    
113
    class Meta:
114
        app_label = 'dossiers'
115

    
116
    patient = models.ForeignKey('dossiers.PatientRecord',
117
        verbose_name=u'Dossier patient', editable=False)
118
    state_name = models.CharField(max_length=150)
119
    created = models.DateTimeField(u'Création', auto_now_add=True)
120
    date_selected = models.DateTimeField()
121
    author = \
122
        models.ForeignKey(User,
123
        verbose_name=u'Auteur', editable=False)
124
    comment = models.TextField(max_length=3000, blank=True, null=True)
125
    previous_state = models.ForeignKey('FileState',
126
        verbose_name=u'Etat précédent',
127
        editable=False, blank=True, null=True)
128

    
129
    def get_next_state(self):
130
        try:
131
            return FileState.objects.get(previous_state=self)
132
        except:
133
            return None
134

    
135
    def save(self, **kwargs):
136
        self.date_selected = \
137
            datetime(self.date_selected.year,
138
                self.date_selected.month, self.date_selected.day)
139
        super(FileState, self).save(**kwargs)
140

    
141
    def __unicode__(self):
142
        return self.state_name + ' ' + str(self.date_selected)
143

    
144

    
145
class PatientRecord(ServiceLinkedAbstractModel, People):
146
    class Meta:
147
        verbose_name = u'Dossier'
148
        verbose_name_plural = u'Dossiers'
149

    
150
    created = models.DateTimeField(u'création', auto_now_add=True)
151
    creator = \
152
        models.ForeignKey(User,
153
        verbose_name=u'Créateur dossier patient',
154
        editable=False)
155
    contacts = models.ManyToManyField('personnes.People',
156
            related_name='contact_of')
157
    birthdate = models.DateField(null=True, blank=True)
158
    paper_id = models.CharField(max_length=12,
159
            null=True, blank=True)
160

    
161
    def __init__(self, *args, **kwargs):
162
        super(PatientRecord, self).__init__(*args, **kwargs)
163
        if not hasattr(self, 'service'):
164
            raise Exception('The field service is mandatory.')
165

    
166
    def get_state(self):
167
        last_state = self.filestate_set.latest('date_selected')
168
        multiple = self.filestate_set.\
169
            filter(date_selected=last_state.date_selected)
170
        if len(multiple) > 1:
171
            last_state = multiple.latest('created')
172
        return last_state
173

    
174
    def get_state_at_day(self, date):
175
        state = self.get_state()
176
        while(state):
177
            if datetime(state.date_selected.year,
178
                    state.date_selected.month, state.date_selected.day) <= \
179
                    datetime(date.year, date.month, date.day):
180
                return state
181
            state = state.previous_state
182
        return None
183

    
184
    def was_in_state_at_day(self, date, state_name):
185
        state_at_day = self.get_state_at_day(date)
186
        if state_at_day and state_at_day.state_name == state_name:
187
            return True
188
        return False
189

    
190
    def get_states_history(self):
191
        return self.filestate_set.order_by('date_selected')
192

    
193
    def set_state(self, state_name, author, date_selected=None, comment=None):
194
        if not author:
195
            raise Exception('Missing author to set state')
196
        if not state_name in STATES[self.service.name].keys():
197
            raise Exception('Etat de dossier '
198
                'non existant dans le service %s.' % self.service.name)
199
        if not date_selected:
200
            date_selected = datetime.now()
201
        current_state = self.get_state()
202
        if not current_state:
203
            raise Exception('Invalid patient record. '
204
                'Missing current state.')
205
        if date_selected < current_state.date_selected:
206
            raise Exception('You cannot set a state starting the %s that '
207
                'is before the previous state starting at day %s.' % \
208
                (str(date_selected), str(current_state.date_selected)))
209
        FileState(patient=self, state_name=state_name,
210
            date_selected=date_selected, author=author, comment=comment,
211
            previous_state=current_state).save()
212

    
213
    def change_day_selected_of_state(self, state, new_date):
214
        if state.previous_state:
215
            if new_date < state.previous_state.date_selected:
216
                raise Exception('You cannot set a state starting the %s '
217
                    'before the previous state starting at day %s.' % \
218
                    (str(new_date), str(state.previous_state.date_selected)))
219
        next_state = state.get_next_state()
220
        if next_state:
221
            if new_date > next_state.date_selected:
222
                raise Exception('You cannot set a state starting the %s '
223
                    'after the following state starting at day %s.' % \
224
                    (str(new_date), str(next_state.date_selected)))
225
        state.date_selected = new_date
226
        state.save()
227

    
228
    def remove_state(self, state):
229
        if state.patient.id != self.id:
230
            raise Exception('The state given is not about this patient '
231
                'record but about %s' % state.patient)
232
        next_state = state.get_next_state()
233
        if not next_state:
234
            self.remove_last_state()
235
        else:
236
            next_state.previous_state = state.previous_state
237
            next_state.save()
238
            state.delete()
239

    
240
    def remove_last_state(self):
241
        try:
242
            self.get_state().delete()
243
        except:
244
            pass
245

    
246
    # START Specific to sessad healthcare
247
    def get_last_notification(self):
248
        return SessadHealthCareNotification.objects.filter(patient=self, ).\
249
            latest('end_date')
250

    
251
    def days_before_notification_expiration(self):
252
        today = datetime.today()
253
        notification = self.get_last_notification(self)
254
        if not notification:
255
            return 0
256
        if notification.end_date < today:
257
            return 0
258
        else:
259
            return notification.end_date - today
260
    # END Specific to sessad healthcare
261

    
262
    # START Specific to cmpp healthcare
263
    def create_diag_healthcare(self, modifier):
264
        """
265
            Gestion de l'inscription automatique.
266

    
267
            Si un premier acte est validé alors une prise en charge
268
            diagnostique est ajoutée. Cela fera basculer le dossier dans l'état
269
            en diagnostic.
270

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

    
277
        """
278
        acts = self.act_set.order_by('date')
279
        hcs = self.healthcare_set.order_by('-start_date')
280
        if not hcs:
281
            # Pas de prise en charge, on recherche l'acte facturable le plus
282
            # ancien, on crée une pc diag à la même date.
283
            for act in acts:
284
                if are_all_acts_of_the_day_locked(act.date) and \
285
                        act.is_state('VALIDE') and act.is_billable():
286
                    CmppHealthCareDiagnostic(patient=self, author=modifier,
287
                        start_date=act.date).save()
288
                    break
289
        else:
290
            # On recherche l'acte facturable non facturé le plus ancien et
291
            # l'on regarde s'il a plus d'un an
292
            try:
293
                last_billed_act = self.act_set.filter(is_billed=True).\
294
                    latest('date')
295
                if last_billed_act:
296
                    for act in acts:
297
                        if are_all_acts_of_the_day_locked(act.date) and \
298
                                act.is_state('VALIDE') and \
299
                                act.is_billable() and \
300
                                (act.date - last_billed_act.date).days >= 365:
301
                            CmppHealthCareDiagnostic(patient=self,
302
                                author=modifier, start_date=act.date).save()
303
                            break
304
            except:
305
                pass
306

    
307
    def automated_switch_state(self, modifier):
308
        # Quel est le dernier acte facturable.
309
        acts = self.act_set.order_by('-date')
310
        # Si cet acte peut-être pris en charge en diagnostic c'est un acte de
311
        # diagnostic, sinon c'est un acte de traitement.
312
        for act in acts:
313
            if are_all_acts_of_the_day_locked(act.date) and \
314
                    act.is_state('VALIDE') and act.is_billable():
315
                cared, hc = act.is_act_covered_by_diagnostic_healthcare()
316
                if hc:
317
                    if self.get_state().state_name == 'CMPP_STATE_ACCUEIL' \
318
                            or self.get_state().state_name == \
319
                                'CMPP_STATE_TRAITEMENT':
320
                        self.set_state('CMPP_STATE_DIAGNOSTIC', modifier,
321
                            date_selected=act.date)
322
                # Sinon, si le dossier est en diag, s'il ne peut être couvert
323
                # en diag, il est en traitement.
324
                elif self.get_state().state_name == 'CMPP_STATE_DIAGNOSTIC':
325
                    self.set_state('CMPP_STATE_TRAITEMENT', modifier,
326
                        date_selected=act.date)
327
                break
328
    # END Specific to cmpp healthcare
329

    
330

    
331
def create_patient(first_name, last_name, service, creator,
332
        date_selected=None):
333
    logger.debug('create_patient: creation for patient %s %s in service %s '
334
        'by %s' % (first_name, last_name, service, creator))
335
    if not (first_name and last_name and service and creator):
336
        raise Exception('Missing parameter to create a patient record.')
337
    patient = PatientRecord(first_name=first_name, last_name=last_name,
338
        service=service, creator=creator)
339
    patient.save()
340
    if not date_selected:
341
        date_selected = patient.created
342
    FileState(patient=patient, state_name=STATE_ACCUEIL[service.name],
343
        date_selected=date_selected, author=creator,
344
        previous_state=None).save()
345
    return patient
(4-4/8)