Project

General

Profile

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

calebasse / calebasse / actes / models.py @ c0014064

1
# -*- coding: utf-8 -*-
2
from django.db import models
3
from django.contrib.auth.models import User
4

    
5
from calebasse.agenda.models import Event, EventType
6
from calebasse.agenda.managers import EventManager
7
from calebasse.dossiers.models import SessadHealthCareNotification, \
8
    CmppHealthCareDiagnostic, CmppHealthCareTreatment
9
from calebasse.actes.validation import are_all_acts_of_the_day_locked
10

    
11
from validation_states import VALIDATION_STATES
12

    
13

    
14
class ActValidationState(models.Model):
15

    
16
    class Meta:
17
        app_label = 'actes'
18

    
19
    act = models.ForeignKey('actes.Act',
20
        verbose_name=u'Acte', editable=False)
21
    state_name = models.CharField(max_length=150)
22
    created = models.DateTimeField(u'Création', auto_now_add=True)
23
    author = \
24
        models.ForeignKey(User,
25
        verbose_name=u'Auteur', editable=False)
26
    previous_state = models.ForeignKey('ActValidationState',
27
        verbose_name=u'Etat précédent',
28
        editable=False, blank=True, null=True)
29
    # To record if the validation has be done by the automated validation
30
    auto = models.BooleanField(default=False,
31
            verbose_name=u'Vérouillage')
32

    
33
    def __unicode__(self):
34
        return self.state_name + ' ' + str(self.created)
35

    
36

    
37
class Act(models.Model):
38
    patient = models.ForeignKey('dossiers.PatientRecord')
39
    date = models.DateTimeField()
40
    act_type = models.ForeignKey('ressources.ActType',
41
            verbose_name=u'Type d\'acte')
42
    validation_locked = models.BooleanField(default=False,
43
            verbose_name=u'Vérouillage')
44
    is_billed = models.BooleanField(default=False,
45
            verbose_name=u'Facturé')
46
    switch_billable = models.BooleanField(default=False,
47
            verbose_name=u'Inverser type facturable')
48
    healthcare = models.ForeignKey('dossiers.HealthCare',
49
            blank=True,
50
            null=True,
51
            verbose_name=u'Prise en charge utilisée pour facturée (CMPP)')
52
    transport_company = models.ForeignKey('ressources.TransportCompany',
53
            blank=True,
54
            null=True,
55
            verbose_name=u'Compagnie de transport')
56
    transport_type = models.ForeignKey('ressources.TransportType',
57
            blank=True,
58
            null=True,
59
            verbose_name=u'Type de transport')
60
    doctors = models.ManyToManyField('personnes.Worker',
61
            limit_choices_to={'type__intervene': True},
62
            verbose_name=u'Thérapeutes')
63
    histories = models.ManyToManyField('HistoryAct')
64

    
65
    def is_absent(self):
66
        if self.get_state() in ('ABS_NON_EXC', 'ABS_EXC', 'ANNUL_NOUS',
67
                'ANNUL_FAMILLE', 'ABS_ESS_PPS', 'ENF_HOSP'):
68
            return True
69

    
70
    def get_state(self):
71
        return self.actvalidationstate_set.latest('created')
72

    
73
    def is_state(self, state_name):
74
        state = self.get_state()
75
        if state and state.state_name == state_name:
76
            return True
77
        return False
78

    
79
    def set_state(self, state_name, author, auto=False,
80
            change_state_check=True):
81
        if not author:
82
            raise Exception('Missing author to set state')
83
        if not state_name in VALIDATION_STATES.keys():
84
            raise Exception("Etat d'acte non existant %s")
85
        current_state = self.get_state()
86
        ActValidationState(act=self, state_name=state_name,
87
            author=author, previous_state=current_state).save()
88

    
89
    def is_billable(self):
90
        if (self.act_type.billable and not self.switch_billable) or \
91
                (not self.act_type.billable and self.switch_billable):
92
            return True
93

    
94
    # START Specific to sessad healthcare
95
    def was_covered_by_notification(self):
96
        notifications = \
97
            SessadHealthCareNotification.objects.filter(patient=self.patient,
98
            start_date__lte=self.date, end_date__gte=self.date)
99
        if notifications:
100
            return True
101
    # END Specific to sessad healthcare
102

    
103
    # START Specific to cmpp healthcare
104
    def is_act_covered_by_diagnostic_healthcare(self):
105
        # L'acte est déja pointé par une prise en charge
106
        if self.is_billed:
107
            # Sinon ce peut une refacturation, donc ne pas tenir compte qu'il
108
            # y est une healthcare non vide
109
            if self.healthcare and isinstance(self.healthcare,
110
                    CmppHealthCareDiagnostic):
111
                return (False, self.healthcare)
112
            elif self.healthcare:
113
                return (False, None)
114
        # L'acte doit être facturable
115
        if not (are_all_acts_of_the_day_locked(self.date) and \
116
                self.is_state('VALIDE') and self.is_billable()):
117
            return (False, None)
118
        # On prend la dernière prise en charge diagnostic, l'acte ne sera pas
119
        # pris en charge sur une prise en charge précédente
120
        # Il peut arriver que l'on ait ajouté une prise en charge de
121
        # traitement alors que tous les actes pour le diag ne sont pas encore facturés
122
        try:
123
            hc = CmppHealthCareDiagnostic.objects.\
124
                filter(patient=self.patient).latest('start_date')
125
        except:
126
            return (False, None)
127
        if not hc:
128
            # On pourrait ici créer une prise en charge de diagnostic
129
            return (False, None)
130
        if self.date < hc.start_date:
131
            return (False, None)
132
        # Les acts facturés déja couvert par la prise en charge sont pointés
133
        # dans hc.act_set.all()
134
        nb_acts_billed = len(hc.act_set.all())
135
        if nb_acts_billed >= hc.get_act_number():
136
            return (False, None)
137
        # Il faut ajouter les actes facturables non encore facturés qui précède cet
138
        # acte
139
        acts_billable = [a for a in self.patient.act_set.\
140
            filter(is_billed=False).order_by('date') \
141
            if are_all_acts_of_the_day_locked(a.date) and \
142
            a.is_state('VALIDE') and a.is_billable()]
143
        count = 0
144
        for a in acts_billable:
145
            if nb_acts_billed + count >= hc.get_act_number():
146
                return (False, None)
147
            if a.date >= hc.start_date:
148
                if a.id == self.id:
149
                    return (True, hc)
150
                count = count + 1
151
        return (False, None)
152

    
153
    def is_act_covered_by_treatment_healthcare(self):
154
        # L'acte est déja pointé par une prise en charge
155
        if self.is_billed:
156
            # Sinon ce peut une refacturation, donc ne pas tenir compte qu'il
157
            # y est une healthcare non vide
158
            if self.healthcare and isinstance(self.healthcare,
159
                    CmppHealthCareTreatment):
160
                return (False, self.healthcare)
161
            elif self.healthcare:
162
                return (False, None)
163
        # L'acte doit être facturable
164
        if not (are_all_acts_of_the_day_locked(self.date) and \
165
                self.is_state('VALIDE') and self.is_billable()):
166
            return (False, None)
167
        # On prend la dernière prise en charge diagnostic, l'acte ne sera pas
168
        # pris en charge sur une prise en charge précédente
169
        # Il peut arriver que l'on ait ajouté une prise en charge de
170
        # traitement alors que tous les actes pour le diag ne sont pas encore facturés
171
        try:
172
            hc = CmppHealthCareTreatment.objects.\
173
                filter(patient=self.patient).latest('start_date')
174
        except:
175
            return (False, None)
176
        if not hc:
177
            return (False, None)
178
        if self.date < hc.start_date or self.date > hc.end_date:
179
            return (False, None)
180
        # Les acts facturés déja couvert par la prise en charge sont pointés
181
        # dans hc.act_set.all()
182
        nb_acts_billed = len(hc.act_set.all())
183
        if nb_acts_billed >= hc.get_act_number():
184
            return (False, None)
185
        # Il faut ajouter les actes facturables non encore facturés qui précède cet
186
        # acte
187
        acts_billable = [a for a in self.patient.act_set.\
188
            filter(is_billed=False).order_by('date') \
189
            if are_all_acts_of_the_day_locked(a.date) and \
190
            a.is_state('VALIDE') and a.is_billable()]
191
        count = 0
192
        for a in acts_billable:
193
            if nb_acts_billed + count >= hc.get_act_number():
194
                return (False, None)
195
            if a.date >= hc.start_date and a.date <= hc.end_date:
196
                if a.id == self.id:
197
                    return (True, hc)
198
                count = count + 1
199
        return (False, None)
200
    # END Specific to cmpp healthcare
201

    
202
    def __unicode__(self):
203
        return '{0} le {1} pour {2} avec {3}'.format(
204
                self.act_type, self.date, self.patient,
205
                ', '.join(map(unicode, self.doctors.all())))
206

    
207
    def __repr__(self):
208
        return '<%s %r %r>' % (self.__class__.__name__, unicode(self), self.id)
209

    
210
    class Meta:
211
        verbose_name = u"Acte"
212
        verbose_name_plural = u"Actes"
213
        ordering = ['-date', 'patient']
214

    
215

    
216
class HistoryAct(models.Model):
217
    EVENT_CHOICES = (
218
            ('NR', u'Nouveau rendez-vous'),
219
            ('AV', u'Acte validé'),
220
            ('CF', u'En cours de facturation'),
221
            ('AF', u'Acte facturé'),
222
            )
223
    date = models.DateTimeField()
224
    event_type = models.CharField(max_length=2,
225
            choices=EVENT_CHOICES)
226
    description = models.TextField(default='')
227

    
228

    
229
class EventActManager(EventManager):
230

    
231
    def create_patient_appointment(self, creator, title, patient, participants,
232
            act_type, service, start_datetime, end_datetime, description='',
233
            room=None, note=None, **rrule_params):
234
        """
235
        This method allow you to create a new patient appointment quickly
236

    
237
        Args:
238
            title: patient appointment title (str)
239
            patient: Patient object
240
            participants: List of CalebasseUser (therapists)
241
            act_type: ActType object
242
            service: Service object. Use session service by defaut
243
            start_datetime: datetime with the start date and time
244
            end_datetime: datetime with the end date and time
245
            freq, count, until, byweekday, rrule_params:
246
            follow the ``dateutils`` API (see http://labix.org/python-dateutil)
247

    
248
        Example:
249
            Look at calebasse.agenda.tests.EventTest (test_create_appointments
250
            method)
251
        """
252

    
253
        event_type, created = EventType.objects.get_or_create(
254
                label=u"Rendez-vous patient"
255
                )
256

    
257
        history = HistoryAct.objects.create(
258
                date = datetime.now(),
259
                event_type = 'NR')
260
        act_event = EventAct.objects.create(
261
                title=title,
262
                event_type=event_type,
263
                patient=patient,
264
                act_type=act_type,
265
                date=start_datetime,
266
                histories = [history]
267
                )
268
        act_event.doctors = participants
269
        ActValidationState(act=act_event, state_name='NON_VALIDE',
270
            author=creator, previous_state=None).save()
271

    
272
        return self._set_event(act_event, participants, description,
273
                services=[service], start_datetime=start_datetime,
274
                end_datetime=end_datetime,
275
                room=room, note=note, **rrule_params)
276

    
277

    
278
class EventAct(Act, Event):
279
    objects = EventActManager()
280

    
281
    VALIDATION_CODE_CHOICES = (
282
            ('absent', u'Absent'),
283
            ('present', u'Présent'),
284
            )
285
    attendance = models.CharField(max_length=16,
286
            choices=VALIDATION_CODE_CHOICES,
287
            default='absent',
288
            verbose_name=u'Présence')
289
    convocation_sent = models.BooleanField(blank=True,
290
            verbose_name=u'Convoqué')
291

    
292
    def __unicode__(self):
293
        return 'Rdv le {0} de {1} avec {2} pour {3}'.format(
294
                self.occurrence_set.all()[0].start_time, self.patient,
295
                ', '.join(map(unicode, self.participants.all())),
296
                self.act_type)
297

    
298
    def __repr__(self):
299
        return '<%s %r %r>' % (self.__class__.__name__, unicode(self),
300
            self.id)
301

    
302
    class Meta:
303
        verbose_name = 'Rendez-vous patient'
304
        verbose_name_plural = 'Rendez-vous patient'
305
        ordering = ['-date', 'patient']
(4-4/9)