Revision 76974b6f
Added by Benjamin Dauvergne almost 12 years ago
calebasse/actes/admin.py | ||
---|---|---|
2 | 2 |
|
3 | 3 |
import reversion |
4 | 4 |
|
5 |
from models import Act, ActValidationState, EventAct
|
|
5 |
from models import Act, ActValidationState |
|
6 | 6 |
|
7 | 7 |
admin.site.register(Act, reversion.VersionAdmin) |
8 | 8 |
admin.site.register(ActValidationState, reversion.VersionAdmin) |
9 |
admin.site.register(EventAct, reversion.VersionAdmin) |
calebasse/actes/models.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 |
from datetime import date |
|
3 |
|
|
2 | 4 |
from django.db import models |
3 | 5 |
from django.contrib.auth.models import User |
4 | 6 |
|
... | ... | |
40 | 42 |
return VALIDATION_STATES[self.state_name] |
41 | 43 |
|
42 | 44 |
|
45 |
class ActManager(models.Manager): |
|
46 |
def create_act(self, author=None, **kwargs): |
|
47 |
act = self.create(**kwargs) |
|
48 |
ActValidationState.objects.create(act=act,state_name='NON_VALIDE', |
|
49 |
author=author, previous_state=None) |
|
50 |
return act |
|
51 |
|
|
52 |
def next_acts(self, patient_record, today=None): |
|
53 |
today = today or date.today() |
|
54 |
return self.filter(date__gte=today) \ |
|
55 |
.filter(patient=patient_record) \ |
|
56 |
.order_by('date') |
|
57 |
|
|
58 |
def last_acts(self, patient_record, today=None): |
|
59 |
today = today or date.today() |
|
60 |
return self.filter(date__lte=today) \ |
|
61 |
.filter(patient=patient_record) \ |
|
62 |
.order_by('-date') |
|
63 |
|
|
64 |
|
|
43 | 65 |
class Act(models.Model): |
66 |
objects = ActManager() |
|
67 |
|
|
44 | 68 |
patient = models.ForeignKey('dossiers.PatientRecord') |
45 |
date = models.DateTimeField() |
|
69 |
date = models.DateField() |
|
70 |
_duration = models.IntegerField(u'Durée en minutes', default=0) |
|
46 | 71 |
act_type = models.ForeignKey('ressources.ActType', |
47 | 72 |
verbose_name=u'Type d\'acte') |
48 | 73 |
validation_locked = models.BooleanField(default=False, |
... | ... | |
68 | 93 |
verbose_name=u'Intervenants') |
69 | 94 |
pause = models.BooleanField(default=False, |
70 | 95 |
verbose_name=u'Pause facturation') |
96 |
parent_event = models.ForeignKey('agenda.Event', |
|
97 |
verbose_name=u'Rendez-vous lié', |
|
98 |
blank=True, null=True) |
|
99 |
VALIDATION_CODE_CHOICES = ( |
|
100 |
('absent', u'Absent'), |
|
101 |
('present', u'Présent'), |
|
102 |
) |
|
103 |
attendance = models.CharField(max_length=16, |
|
104 |
choices=VALIDATION_CODE_CHOICES, |
|
105 |
default='absent', |
|
106 |
verbose_name=u'Présence') |
|
107 |
convocation_sent = models.BooleanField(blank=True, |
|
108 |
verbose_name=u'Convoqué') |
|
109 |
|
|
110 |
@property |
|
111 |
def event(self): |
|
112 |
if self.parent_event: |
|
113 |
return self.parent_event.today_occurence(self.date) |
|
114 |
return None |
|
115 |
|
|
116 |
@property |
|
117 |
def start_time(self): |
|
118 |
event = self.event |
|
119 |
if event: |
|
120 |
return event.start_datetime.timetz() |
|
121 |
return None |
|
71 | 122 |
|
72 | 123 |
def get_hc_tag(self): |
73 | 124 |
if self.healthcare: |
... | ... | |
155 | 206 |
if not hc: |
156 | 207 |
# On pourrait ici créer une prise en charge de diagnostic |
157 | 208 |
return (False, None) |
158 |
if self.date.date() < hc.start_date:
|
|
209 |
if self.date < hc.start_date: |
|
159 | 210 |
return (False, None) |
160 | 211 |
# Les acts facturés déja couvert par la prise en charge sont pointés |
161 | 212 |
# dans hc.act_set.all() |
... | ... | |
172 | 223 |
for a in acts_billable: |
173 | 224 |
if nb_acts_billed + count >= hc.get_act_number(): |
174 | 225 |
return (False, None) |
175 |
if a.date.date() >= hc.start_date:
|
|
226 |
if a.date >= hc.start_date: |
|
176 | 227 |
if a.id == self.id: |
177 | 228 |
return (True, hc) |
178 | 229 |
count = count + 1 |
... | ... | |
225 | 276 |
# return (True, hc) |
226 | 277 |
# count = count + 1 |
227 | 278 |
# return (False, None) |
228 |
# END Specific to cmpp healthcare |
|
279 |
# END Specific to cmpp healthcare |
|
280 |
|
|
281 |
def duration(self): |
|
282 |
'''Return a displayable duration for this field.''' |
|
283 |
hours, remainder = divmod(self._duration, 60) |
|
284 |
return '%02d:%02d' % (hours, remainder) |
|
229 | 285 |
|
230 | 286 |
def __unicode__(self): |
231 | 287 |
return u'{0} le {1} pour {2} avec {3}'.format( |
... | ... | |
285 | 341 |
end_datetime=end_datetime, |
286 | 342 |
room=room, note=note, **rrule_params) |
287 | 343 |
|
288 |
def modify_patient_appointment(self, creator, title, patient, participants, |
|
289 |
act_type, service, start_datetime, end_datetime, description='', |
|
290 |
room=None, note=None, **rrule_params): |
|
291 |
""" |
|
292 |
This method allow you to create a new patient appointment quickly |
|
293 |
|
|
294 |
Args: |
|
295 |
creator: author of the modification |
|
296 |
title: patient appointment title (str) |
|
297 |
patient: Patient object |
|
298 |
participants: List of CalebasseUser (therapists) |
|
299 |
act_type: ActType object |
|
300 |
service: Service object. Use session service by defaut |
|
301 |
start_datetime: datetime with the start date and time |
|
302 |
end_datetime: datetime with the end date and time |
|
303 |
description: description of the event |
|
304 |
room: room where the event will take place |
|
305 |
freq, count, until, byweekday, rrule_params: |
|
306 |
follow the ``dateutils`` API (see http://labix.org/python-dateutil) |
|
307 |
|
|
308 |
Example: |
|
309 |
Look at calebasse.agenda.tests.EventTest (test_create_appointments |
|
310 |
method) |
|
311 |
""" |
|
312 |
|
|
313 |
event_type, created = EventType.objects.get_or_create( |
|
314 |
label=u"Rendez-vous patient" |
|
315 |
) |
|
316 |
|
|
317 |
act_event = EventAct.objects.create( |
|
318 |
title=title, |
|
319 |
event_type=event_type, |
|
320 |
patient=patient, |
|
321 |
act_type=act_type, |
|
322 |
date=start_datetime, |
|
323 |
) |
|
324 |
act_event.doctors = participants |
|
325 |
ActValidationState(act=act_event, state_name=NON_VALIDE, |
|
326 |
author=creator, previous_state=None).save() |
|
327 |
|
|
328 |
return self._set_event(act_event, participants, description, |
|
329 |
services=[service], start_datetime=start_datetime, |
|
330 |
end_datetime=end_datetime, |
|
331 |
room=room, note=note, **rrule_params) |
|
332 |
|
|
333 |
class EventAct(Event, Act): |
|
334 |
objects = EventActManager() |
|
335 |
|
|
336 |
VALIDATION_CODE_CHOICES = ( |
|
337 |
('absent', u'Absent'), |
|
338 |
('present', u'Présent'), |
|
339 |
) |
|
340 |
attendance = models.CharField(max_length=16, |
|
341 |
choices=VALIDATION_CODE_CHOICES, |
|
342 |
default='absent', |
|
343 |
verbose_name=u'Présence') |
|
344 |
convocation_sent = models.BooleanField(blank=True, |
|
345 |
verbose_name=u'Convoqué') |
|
346 |
|
|
347 |
def __unicode__(self): |
|
348 |
return u'Rdv le {0} de {1} avec {2} pour {3}'.format( |
|
349 |
self.occurrence_set.all()[0].start_time, self.patient, |
|
350 |
', '.join(map(unicode, self.participants.all())), |
|
351 |
self.act_type) |
|
352 |
|
|
353 |
def __repr__(self): |
|
354 |
return (u'<%s %r %r>' % (self.__class__.__name__, unicode(self), |
|
355 |
self.id)).encode('utf-8') |
|
356 |
|
|
357 |
def start_time(self): |
|
358 |
return self.occurrence_set.all()[0].start_time |
|
359 |
|
|
360 |
def duration(self): |
|
361 |
o = self.occurrence_set.all()[0] |
|
362 |
td = o.end_time - o.start_time |
|
363 |
hours, remainder = divmod(td.seconds, 3600) |
|
364 |
minutes, remainder = divmod(remainder, 60) |
|
365 |
return '%02d:%02d' % (hours, minutes) |
|
366 |
|
|
367 |
class Meta: |
|
368 |
verbose_name = 'Rendez-vous patient' |
|
369 |
verbose_name_plural = 'Rendez-vous patient' |
|
370 |
ordering = ['-date', 'patient'] |
|
371 |
|
|
372 |
reversion.register(EventAct, follow=['act_ptr', 'event_ptr']) |
|
373 | 344 |
|
374 | 345 |
class ValidationMessage(ServiceLinkedAbstractModel): |
375 | 346 |
validation_date = models.DateTimeField() |
calebasse/actes/templates/actes/act_listing.html | ||
---|---|---|
123 | 123 |
{% endif %} |
124 | 124 |
{% endfor %} |
125 | 125 |
</td> |
126 |
<td>{{ act.start_time|date:"H:i" }}</td> |
|
126 |
<td>{{ act.parent_event.start_time|date:"H:i" }}</td>
|
|
127 | 127 |
<td>{{ act.duration }}</td> |
128 | 128 |
</tr> |
129 | 129 |
{% endfor %} |
calebasse/actes/tests.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 |
from datetime import datetime |
|
3 |
from dateutil import rrule |
|
2 |
from datetime import datetime, date |
|
4 | 3 |
|
5 | 4 |
from django.test import TestCase |
6 | 5 |
from django.contrib.auth.models import User |
7 | 6 |
|
8 | 7 |
from validation import automated_validation, are_all_acts_of_the_day_locked, \ |
9 | 8 |
get_days_with_acts_not_locked |
10 |
from calebasse.actes.models import EventAct |
|
11 | 9 |
from calebasse.dossiers.models import create_patient |
10 |
from calebasse.agenda.models import EventWithAct |
|
12 | 11 |
from calebasse.ressources.models import ActType, Service, WorkerType |
13 | 12 |
from calebasse.personnes.models import Worker |
14 | 13 |
|
... | ... | |
28 | 27 |
patient2 = create_patient('Jimmy', 'Claff', service, creator) |
29 | 28 |
patient3 = create_patient('Bouba', 'Lourson', service, creator) |
30 | 29 |
|
31 |
act_event = EventAct.objects.create_patient_appointment(creator, 'RDV avec M X', patient, |
|
30 |
act_event = EventWithAct.objects.create_patient_appointment(creator, 'RDV avec M X', patient,
|
|
32 | 31 |
[therapist1, therapist2], act_type, service, |
33 | 32 |
start_datetime=datetime(2020, 10, 2, 7, 15), |
34 | 33 |
end_datetime=datetime(2020, 10, 2, 9, 20), |
35 |
freq=rrule.WEEKLY, byweekday=rrule.FR, until=datetime(2040, 10, 2))
|
|
36 |
act_event2 = EventAct.objects.create_patient_appointment(creator, 'RDV avec M Y', patient, [therapist3], |
|
34 |
periodicity=1, until=date(2020, 10, 2))
|
|
35 |
act_event2 = EventWithAct.objects.create_patient_appointment(creator, 'RDV avec M Y', patient, [therapist3],
|
|
37 | 36 |
act_type, service, start_datetime=datetime(2020, 10, 2, 10, 15), |
38 | 37 |
end_datetime=datetime(2020, 10, 2, 12, 20), |
39 |
freq=rrule.WEEKLY, byweekday=rrule.FR, until=datetime(2021, 10, 2))
|
|
40 |
act_event3 = EventAct.objects.create_patient_appointment(creator, 'RDV avec M X', patient2, |
|
38 |
periodicity=1, until=date(2020, 10, 2))
|
|
39 |
act_event3 = EventWithAct.objects.create_patient_appointment(creator, 'RDV avec M X', patient2,
|
|
41 | 40 |
[therapist1, therapist2], act_type, service, |
42 | 41 |
start_datetime=datetime(2020, 10, 2, 7, 15), |
43 | 42 |
end_datetime=datetime(2020, 10, 2, 9, 20), |
44 |
freq=rrule.WEEKLY, byweekday=rrule.FR, until=datetime(2040, 10, 2))
|
|
45 |
act_event4 = EventAct.objects.create_patient_appointment(creator, 'RDV avec M Y', patient3, [therapist3], |
|
43 |
periodicity=1, until=date(2020, 10, 2))
|
|
44 |
act_event4 = EventWithAct.objects.create_patient_appointment(creator, 'RDV avec M Y', patient3, [therapist3],
|
|
46 | 45 |
act_type, service, start_datetime=datetime(2020, 10, 2, 10, 15), |
47 | 46 |
end_datetime=datetime(2020, 10, 2, 12, 20), |
48 |
freq=rrule.WEEKLY, byweekday=rrule.FR, until=datetime(2021, 10, 2))
|
|
49 |
act_event5 = EventAct.objects.create_patient_appointment(creator, 'RDV avec M Y', patient3, [therapist3], |
|
47 |
periodicity=1, until=date(2020, 10, 2))
|
|
48 |
act_event5 = EventWithAct.objects.create_patient_appointment(creator, 'RDV avec M Y', patient3, [therapist3],
|
|
50 | 49 |
act_type, service, start_datetime=datetime(2020, 10, 3, 10, 15), |
51 | 50 |
end_datetime=datetime(2020, 10, 3, 12, 20), |
52 |
freq=rrule.WEEKLY, byweekday=rrule.FR, until=datetime(2021, 10, 2))
|
|
53 |
act_event6 = EventAct.objects.create_patient_appointment(creator, 'RDV avec M Z', patient, [therapist3], |
|
51 |
periodicity=1, until=date(2020, 10, 2))
|
|
52 |
act_event6 = EventWithAct.objects.create_patient_appointment(creator, 'RDV avec M Z', patient, [therapist3],
|
|
54 | 53 |
act_type, service, start_datetime=datetime(2020, 10, 2, 10, 15), |
55 | 54 |
end_datetime=datetime(2020, 10, 2, 12, 20), |
56 |
freq=rrule.WEEKLY, byweekday=rrule.FR, until=datetime(2021, 10, 2))
|
|
57 |
act_event7 = EventAct.objects.create_patient_appointment(creator, 'RDV avec M Z', patient, [therapist3], |
|
55 |
periodicity=1, until=date(2020, 10, 2))
|
|
56 |
act_event7 = EventWithAct.objects.create_patient_appointment(creator, 'RDV avec M Z', patient, [therapist3],
|
|
58 | 57 |
act_type, service, start_datetime=datetime(2020, 10, 4, 10, 15), |
59 | 58 |
end_datetime=datetime(2020, 10, 4, 12, 20), |
60 |
freq=rrule.WEEKLY, byweekday=rrule.FR, until=datetime(2021, 10, 2))
|
|
59 |
periodicity=1, until=date(2020, 10, 4))
|
|
61 | 60 |
|
62 |
act_event3.set_state('ABS_EXC', creator) |
|
63 |
act_event6.set_state('VALIDE', creator) |
|
61 |
act_event3.act.set_state('ABS_EXC', creator)
|
|
62 |
act_event6.act.set_state('VALIDE', creator)
|
|
64 | 63 |
|
65 |
result = automated_validation(datetime(2020, 10, 2, 12, 20), service, creator, commit=False)
|
|
64 |
result = automated_validation(date(2020, 10, 2), service, creator, commit=False)
|
|
66 | 65 |
self.assertEqual(result, (5,2,2,0,1,0,0,0,0,0)) |
67 |
self.assertTrue(act_event.is_state('NON_VALIDE')) |
|
68 |
self.assertTrue(act_event2.is_state('NON_VALIDE')) |
|
69 |
self.assertTrue(act_event3.is_state('ABS_EXC')) |
|
70 |
self.assertTrue(act_event4.is_state('NON_VALIDE')) |
|
71 |
self.assertTrue(act_event5.is_state('NON_VALIDE')) |
|
72 |
self.assertTrue(act_event6.is_state('VALIDE')) |
|
66 |
self.assertTrue(act_event.act.is_state('NON_VALIDE'))
|
|
67 |
self.assertTrue(act_event2.act.is_state('NON_VALIDE'))
|
|
68 |
self.assertTrue(act_event3.act.is_state('ABS_EXC'))
|
|
69 |
self.assertTrue(act_event4.act.is_state('NON_VALIDE'))
|
|
70 |
self.assertTrue(act_event5.act.is_state('NON_VALIDE'))
|
|
71 |
self.assertTrue(act_event6.act.is_state('VALIDE'))
|
|
73 | 72 |
|
74 |
result = automated_validation(datetime(2020, 10, 2, 12, 20), service, creator)
|
|
73 |
result = automated_validation(date(2020, 10, 2), service, creator)
|
|
75 | 74 |
self.assertEqual(result, (5,2,2,0,1,0,0,0,0,0)) |
76 | 75 |
|
77 |
self.assertTrue(act_event.is_state('VALIDE')) |
|
78 |
self.assertTrue(act_event2.is_state('ACT_DOUBLE')) |
|
79 |
self.assertTrue(act_event3.is_state('ABS_EXC')) |
|
80 |
self.assertTrue(act_event4.is_state('VALIDE')) |
|
81 |
self.assertTrue(act_event5.is_state('NON_VALIDE')) |
|
82 |
self.assertTrue(act_event6.is_state('ACT_DOUBLE')) |
|
76 |
self.assertTrue(act_event.act.is_state('VALIDE'))
|
|
77 |
self.assertTrue(act_event2.act.is_state('ACT_DOUBLE'))
|
|
78 |
self.assertTrue(act_event3.act.is_state('ABS_EXC'))
|
|
79 |
self.assertTrue(act_event4.act.is_state('VALIDE'))
|
|
80 |
self.assertTrue(act_event5.act.is_state('NON_VALIDE'))
|
|
81 |
self.assertTrue(act_event6.act.is_state('ACT_DOUBLE'))
|
|
83 | 82 |
|
84 | 83 |
self.assertTrue(are_all_acts_of_the_day_locked(datetime(2020, 10, 2, 12, 20))) |
85 | 84 |
self.assertFalse(are_all_acts_of_the_day_locked(datetime(2020, 10, 3, 12, 20))) |
86 | 85 |
self.assertFalse(are_all_acts_of_the_day_locked(datetime(2020, 10, 4, 12, 20))) |
87 | 86 |
self.assertEqual(get_days_with_acts_not_locked(datetime(2020, 10, 2), datetime(2020, 10, 4)), |
88 |
[datetime(2020, 10, 3, 0, 0), datetime(2020, 10, 4, 0, 0)])
|
|
87 |
[date(2020, 10, 3), date(2020, 10, 4)])
|
|
89 | 88 |
|
90 | 89 |
result = automated_validation(datetime(2020, 10, 2, 12, 20), service, creator, commit=False) |
91 | 90 |
self.assertEqual(result, (5,2,2,0,1,0,0,0,0,0)) |
92 |
self.assertTrue(act_event.is_state('VALIDE')) |
|
93 |
self.assertTrue(act_event2.is_state('ACT_DOUBLE')) |
|
94 |
self.assertTrue(act_event3.is_state('ABS_EXC')) |
|
95 |
self.assertTrue(act_event4.is_state('VALIDE')) |
|
96 |
self.assertTrue(act_event5.is_state('NON_VALIDE')) |
|
97 |
self.assertTrue(act_event6.is_state('ACT_DOUBLE')) |
|
91 |
self.assertTrue(act_event.act.is_state('VALIDE'))
|
|
92 |
self.assertTrue(act_event2.act.is_state('ACT_DOUBLE'))
|
|
93 |
self.assertTrue(act_event3.act.is_state('ABS_EXC'))
|
|
94 |
self.assertTrue(act_event4.act.is_state('VALIDE'))
|
|
95 |
self.assertTrue(act_event5.act.is_state('NON_VALIDE'))
|
|
96 |
self.assertTrue(act_event6.act.is_state('ACT_DOUBLE'))
|
|
98 | 97 |
|
99 | 98 |
result = automated_validation(datetime(2020, 10, 2, 12, 20), service, creator) |
100 | 99 |
self.assertEqual(result, (5,2,2,0,1,0,0,0,0,0)) |
101 |
self.assertTrue(act_event.is_state('VALIDE')) |
|
102 |
self.assertTrue(act_event2.is_state('ACT_DOUBLE')) |
|
103 |
self.assertTrue(act_event3.is_state('ABS_EXC')) |
|
104 |
self.assertTrue(act_event4.is_state('VALIDE')) |
|
105 |
self.assertTrue(act_event5.is_state('NON_VALIDE')) |
|
106 |
self.assertTrue(act_event6.is_state('ACT_DOUBLE')) |
|
100 |
self.assertTrue(act_event.act.is_state('VALIDE'))
|
|
101 |
self.assertTrue(act_event2.act.is_state('ACT_DOUBLE'))
|
|
102 |
self.assertTrue(act_event3.act.is_state('ABS_EXC'))
|
|
103 |
self.assertTrue(act_event4.act.is_state('VALIDE'))
|
|
104 |
self.assertTrue(act_event5.act.is_state('NON_VALIDE'))
|
|
105 |
self.assertTrue(act_event6.act.is_state('ACT_DOUBLE'))
|
|
107 | 106 |
|
108 | 107 |
result = automated_validation(datetime(2020, 10, 2, 12, 20), service, creator, commit=False) |
109 | 108 |
self.assertEqual(result, (5,2,2,0,1,0,0,0,0,0)) |
110 |
self.assertTrue(act_event.is_state('VALIDE')) |
|
111 |
self.assertTrue(act_event2.is_state('ACT_DOUBLE')) |
|
112 |
self.assertTrue(act_event3.is_state('ABS_EXC')) |
|
113 |
self.assertTrue(act_event4.is_state('VALIDE')) |
|
114 |
self.assertTrue(act_event5.is_state('NON_VALIDE')) |
|
115 |
self.assertTrue(act_event6.is_state('ACT_DOUBLE')) |
|
109 |
self.assertTrue(act_event.act.is_state('VALIDE')) |
|
110 |
self.assertTrue(act_event2.act.is_state('ACT_DOUBLE')) |
|
111 |
self.assertTrue(act_event3.act.is_state('ABS_EXC')) |
|
112 |
self.assertTrue(act_event4.act.is_state('VALIDE')) |
|
113 |
self.assertTrue(act_event5.act.is_state('NON_VALIDE')) |
|
114 |
self.assertTrue(act_event6.act.is_state('ACT_DOUBLE')) |
calebasse/actes/views.py | ||
---|---|---|
14 | 14 |
service=service) |
15 | 15 |
|
16 | 16 |
class ActListingView(ListView): |
17 |
model=models.EventAct
|
|
17 |
model=models.Act |
|
18 | 18 |
template_name='actes/act_listing.html' |
19 | 19 |
|
20 | 20 |
def get_queryset(self): |
21 | 21 |
qs = super(ActListingView, self).get_queryset() |
22 | 22 |
self.get_search_form() |
23 |
qs = qs.filter(services=self.service)
|
|
23 |
qs = qs.filter(patient__service=self.service)
|
|
24 | 24 |
qs = qs.filter(date=self.date) |
25 | 25 |
if self.request.method == 'POST' and self.search_form.is_valid(): |
26 | 26 |
cd = self.search_form.cleaned_data |
calebasse/agenda/admin.py | ||
---|---|---|
2 | 2 |
|
3 | 3 |
import reversion |
4 | 4 |
|
5 |
from models import Event, EventType, Note, Occurrence
|
|
5 |
from models import Event, EventType, EventWithAct
|
|
6 | 6 |
|
7 | 7 |
admin.site.register(Event, reversion.VersionAdmin) |
8 |
admin.site.register(Occurrence, reversion.VersionAdmin) |
|
9 | 8 |
admin.site.register(EventType, reversion.VersionAdmin) |
10 |
admin.site.register(Note, reversion.VersionAdmin) |
|
9 |
admin.site.register(EventWithAct, reversion.VersionAdmin) |
calebasse/agenda/appointments.py | ||
---|---|---|
23 | 23 |
self.patient_record_paper_id = None |
24 | 24 |
self.event_id = None |
25 | 25 |
self.event_type = None |
26 |
self.occurrence_id = None
|
|
26 |
self.event_id = None
|
|
27 | 27 |
self.workers = None |
28 | 28 |
self.workers_initial = None |
29 | 29 |
self.workers_codes = None |
... | ... | |
41 | 41 |
else: |
42 | 42 |
self.begin_hour = None |
43 | 43 |
|
44 |
def init_from_occurrence(self, occurrence, service):
|
|
44 |
def init_from_event(self, event, service):
|
|
45 | 45 |
""" """ |
46 |
delta = occurrence.end_time - occurrence.start_time
|
|
47 |
self.occurrence_id = occurrence.id
|
|
46 |
delta = event.end_datetime - event.start_datetime
|
|
47 |
self.event_id = event.id
|
|
48 | 48 |
self.length = delta.seconds / 60 |
49 |
self.title = occurrence.title
|
|
50 |
services = occurrence.event.services.all()
|
|
51 |
self.date = occurrence.start_time.date()
|
|
52 |
self.__set_time(time(occurrence.start_time.hour, occurrence.start_time.minute))
|
|
49 |
self.title = event.title
|
|
50 |
services = event.services.all() |
|
51 |
self.date = event.start_datetime.date()
|
|
52 |
self.__set_time(time(event.start_datetime.hour, event.start_datetime.minute))
|
|
53 | 53 |
for e_service in services: |
54 | 54 |
if e_service != service: |
55 | 55 |
name = e_service.name.lower().replace(' ', '-') |
... | ... | |
58 | 58 |
self.type = "busy-here" |
59 | 59 |
else: |
60 | 60 |
self.type = "busy-elsewhere" |
61 |
self.event_id = occurrence.event.id
|
|
62 |
if occurrence.event.room:
|
|
63 |
self.room = occurrence.event.room.name
|
|
64 |
self.description = occurrence.event.description
|
|
65 |
if occurrence.event.event_type.id == 1:
|
|
66 |
event_act = occurrence.event.eventact
|
|
67 |
workers = event_act.participants.all()
|
|
61 |
self.event_id = event.id |
|
62 |
if event.room: |
|
63 |
self.room = event.room.name |
|
64 |
self.description = event.description |
|
65 |
if event.event_type.id == 1: |
|
66 |
event_act = event.act
|
|
67 |
workers = event_act.doctors.all()
|
|
68 | 68 |
self.convocation_sent = event_act.convocation_sent |
69 | 69 |
self.patient = event_act.patient |
70 | 70 |
self.patient_record_id = event_act.patient.id |
... | ... | |
93 | 93 |
validation_states.pop('ACT_DOUBLE') |
94 | 94 |
self.validation = (event_act, state, display_name, validation_states) |
95 | 95 |
else: |
96 |
self.event_type = occurrence.event.event_type
|
|
96 |
self.event_type = event.event_type |
|
97 | 97 |
|
98 | 98 |
def init_free_time(self, length, begin_time): |
99 | 99 |
""" """ |
... | ... | |
116 | 116 |
self.title = title |
117 | 117 |
self.__set_time(time) |
118 | 118 |
|
119 |
def get_daily_appointments(date, worker, service, time_tables, occurrences, holidays):
|
|
119 |
def get_daily_appointments(date, worker, service, time_tables, events, holidays):
|
|
120 | 120 |
""" |
121 | 121 |
""" |
122 | 122 |
appointments = [] |
123 | 123 |
|
124 | 124 |
timetables_set = IntervalSet((t.to_interval(date) for t in time_tables)) |
125 |
occurrences_set = IntervalSet((o.to_interval() for o in occurrences))
|
|
125 |
events_set = IntervalSet((o.to_interval() for o in events))
|
|
126 | 126 |
holidays_set = IntervalSet((h.to_interval(date) for h in holidays)) |
127 |
busy_occurrences_set = IntervalSet((o.to_interval() for o in occurrences if not o.is_event_absence()))
|
|
127 |
busy_occurrences_set = IntervalSet((o.to_interval() for o in events_set if not o.is_event_absence()))
|
|
128 | 128 |
for free_time in timetables_set - (busy_occurrences_set+holidays_set): |
129 | 129 |
if free_time: |
130 | 130 |
delta = free_time.upper_bound - free_time.lower_bound |
... | ... | |
133 | 133 |
appointment.init_free_time(delta_minutes, |
134 | 134 |
time(free_time.lower_bound.hour, free_time.lower_bound.minute)) |
135 | 135 |
appointments.append(appointment) |
136 |
for occurrence in occurrences:
|
|
136 |
for event in events:
|
|
137 | 137 |
appointment = Appointment() |
138 |
appointment.init_from_occurrence(occurrence, service)
|
|
138 |
appointment.init_from_event(event, service)
|
|
139 | 139 |
appointments.append(appointment) |
140 | 140 |
for holiday in holidays: |
141 | 141 |
interval = holiday.to_interval(date) |
calebasse/agenda/conf/default.py | ||
---|---|---|
27 | 27 |
|
28 | 28 |
# Indicate the default length in time for a new occurrence, specifed by using |
29 | 29 |
# a datetime.timedelta object |
30 |
DEFAULT_OCCURRENCE_DURATION = datetime.timedelta(hours=+1)
|
|
30 |
DEFAULT_EVENT_DURATION = datetime.timedelta(hours=+1)
|
|
31 | 31 |
|
32 | 32 |
# If not None, passed to the calendar module's setfirstweekday function. |
33 | 33 |
CALENDAR_FIRST_WEEKDAY = 1 |
calebasse/agenda/forms.py | ||
---|---|---|
4 | 4 |
|
5 | 5 |
from django import forms |
6 | 6 |
|
7 |
from calebasse.dossiers.models import PatientRecord |
|
8 |
from calebasse.personnes.models import Worker |
|
9 |
from calebasse.actes.models import EventAct |
|
10 |
from calebasse.agenda.models import Event, EventType |
|
11 |
from calebasse.ressources.models import ActType |
|
12 |
from calebasse.middleware.request import get_request |
|
7 |
from ..dossiers.models import PatientRecord |
|
8 |
from ..personnes.models import Worker |
|
9 |
from ..ressources.models import ActType |
|
10 |
from ..middleware.request import get_request |
|
13 | 11 |
|
14 | 12 |
from ajax_select import make_ajax_field |
13 |
from models import Event, EventWithAct, EventType |
|
15 | 14 |
|
16 | 15 |
class NewAppointmentForm(forms.ModelForm): |
17 | 16 |
date = forms.DateField(label=u'Date') |
... | ... | |
19 | 18 |
duration = forms.CharField(label=u'Durée', |
20 | 19 |
help_text=u'en minutes; vous pouvez utiliser la roulette de votre souris.') |
21 | 20 |
|
22 |
participants = make_ajax_field(EventAct, 'participants', 'worker-or-group', True) |
|
23 |
patient = make_ajax_field(EventAct, 'patient', 'patientrecord', False) |
|
21 |
participants = make_ajax_field(EventWithAct, 'participants', 'worker-or-group', True)
|
|
22 |
patient = make_ajax_field(EventWithAct, 'patient', 'patientrecord', False)
|
|
24 | 23 |
|
25 | 24 |
class Meta: |
26 |
model = EventAct |
|
25 |
model = EventWithAct
|
|
27 | 26 |
fields = ( |
28 | 27 |
'date', |
29 | 28 |
'time', |
... | ... | |
52 | 51 |
duration = self.cleaned_data['duration'] |
53 | 52 |
try: |
54 | 53 |
return int(duration) |
55 |
except: |
|
56 |
return None
|
|
54 |
except ValueError:
|
|
55 |
return 0
|
|
57 | 56 |
|
58 |
def save(self, commit=False): |
|
59 |
start_datetime = datetime.combine(self.cleaned_data['date'], |
|
57 |
def save(self, commit=True): |
|
58 |
appointment = super(NewAppointmentForm, self).save(commit=False) |
|
59 |
appointment.start_datetime = datetime.combine(self.cleaned_data['date'], |
|
60 | 60 |
self.cleaned_data['time']) |
61 |
end_datetime = start_datetime + timedelta(
|
|
61 |
appointment.end_datetime = appointment.start_datetime + timedelta(
|
|
62 | 62 |
minutes=self.cleaned_data['duration']) |
63 |
patient = self.cleaned_data['patient'] |
|
64 |
creator = get_request().user |
|
65 |
self.instance = EventAct.objects.create_patient_appointment( |
|
66 |
creator=creator, |
|
67 |
title=patient.display_name, |
|
68 |
patient=patient, |
|
69 |
participants=self.cleaned_data['participants'], |
|
70 |
act_type=self.cleaned_data['act_type'], |
|
71 |
service=self.service, |
|
72 |
start_datetime=start_datetime, |
|
73 |
end_datetime=end_datetime, |
|
74 |
description='', |
|
75 |
room=self.cleaned_data['room'], |
|
76 |
note=None,) |
|
77 |
return self.instance |
|
78 |
|
|
79 |
class UpdateAppointmentForm(NewAppointmentForm): |
|
63 |
appointment.recurrence_end_date = appointment.start_datetime.date() |
|
64 |
appointment.creator = get_request().user |
|
65 |
appointment.title = appointment.patient.display_name |
|
66 |
appointment.service = self.service |
|
67 |
appointment.clean() |
|
68 |
if commit: |
|
69 |
appointment.save() |
|
70 |
return appointment |
|
80 | 71 |
|
81 |
def __init__(self, instance, service=None, occurrence=None, **kwargs): |
|
82 |
super(UpdateAppointmentForm, self).__init__(instance=instance, |
|
83 |
service=service, **kwargs) |
|
84 |
self.occurrence = occurrence |
|
85 | 72 |
|
86 |
|
|
87 |
def save(self): |
|
88 |
self.occurrence.start_time = datetime.combine( |
|
89 |
self.cleaned_data['date'], |
|
90 |
self.cleaned_data['time']) |
|
91 |
self.occurrence.end_time = self.occurrence.start_time + timedelta( |
|
92 |
minutes=self.cleaned_data['duration']) |
|
93 |
self.occurrence.save() |
|
94 |
patient = self.cleaned_data['patient'] |
|
95 |
creator = get_request().user |
|
96 |
self.instance.title = patient.display_name |
|
97 |
self.instance.participants = self.cleaned_data['participants'] |
|
98 |
self.instance.save() |
|
99 |
return self.instance |
|
73 |
class UpdateAppointmentForm(NewAppointmentForm): |
|
74 |
pass |
|
100 | 75 |
|
101 | 76 |
|
102 | 77 |
class NewEventForm(forms.ModelForm): |
... | ... | |
106 | 81 |
time = forms.TimeField(label=u'Heure de début') |
107 | 82 |
duration = forms.CharField(label=u'Durée', |
108 | 83 |
help_text=u'en minutes; vous pouvez utiliser la roulette de votre souris.') |
109 |
participants = make_ajax_field(EventAct, 'participants', 'worker-or-group', True) |
|
84 |
|
|
85 |
participants = make_ajax_field(Event, 'participants', 'worker-or-group', True) |
|
110 | 86 |
|
111 | 87 |
class Meta: |
112 | 88 |
model = Event |
113 |
widgets = {'services': forms.CheckboxSelectMultiple} |
|
114 | 89 |
fields = ( |
115 | 90 |
'title', |
116 | 91 |
'date', |
... | ... | |
118 | 93 |
'duration', |
119 | 94 |
'room', |
120 | 95 |
'participants', |
121 |
'services', |
|
122 | 96 |
'event_type' |
123 | 97 |
) |
124 | 98 |
|
... | ... | |
135 | 109 |
except: |
136 | 110 |
return None |
137 | 111 |
|
138 |
def save(self, commit=False): |
|
139 |
start_datetime = datetime.combine(self.cleaned_data['date'], |
|
112 |
def save(self, commit=True): |
|
113 |
event = super(NewEventForm, self).save(commit=False) |
|
114 |
event.start_datetime = datetime.combine(self.cleaned_data['date'], |
|
140 | 115 |
self.cleaned_data['time']) |
141 |
end_datetime = start_datetime + timedelta(
|
|
116 |
event.end_datetime = event.start_datetime + timedelta(
|
|
142 | 117 |
minutes=self.cleaned_data['duration']) |
143 |
self.instance = Event.objects.create_event( |
|
144 |
title=self.cleaned_data['title'], |
|
145 |
event_type=self.cleaned_data['event_type'], |
|
146 |
participants=self.cleaned_data['participants'], |
|
147 |
services=self.cleaned_data['services'], |
|
148 |
start_datetime=start_datetime, |
|
149 |
end_datetime=end_datetime, |
|
150 |
description='', |
|
151 |
room=self.cleaned_data['room'], |
|
152 |
note=None,) |
|
153 |
return self.instance |
|
118 |
event.recurrence_end_date = event.start_datetime.date() |
|
119 |
event.creator = get_request().user |
|
120 |
event.service = self.service |
|
121 |
event.clean() |
|
122 |
if commit: |
|
123 |
event.save() |
|
124 |
return event |
|
154 | 125 |
|
155 | 126 |
def clean(self): |
156 | 127 |
cleaned_data = super(NewEventForm, self).clean() |
... | ... | |
159 | 130 |
self._errors['title'] = self.error_class([ |
160 | 131 |
u"Ce champ est obligatoire pour les événements de type « Autre »."]) |
161 | 132 |
return cleaned_data |
162 |
|
|
163 |
|
|
164 |
class UpdateEventForm(NewEventForm): |
|
165 |
|
|
166 |
def __init__(self, instance, occurrence=None, **kwargs): |
|
167 |
super(UpdateEventForm, self).__init__(instance=instance, **kwargs) |
|
168 |
self.occurrence = occurrence |
|
169 |
|
|
170 |
def save(self): |
|
171 |
self.occurrence.start_time = datetime.combine( |
|
172 |
self.cleaned_data['date'], |
|
173 |
self.cleaned_data['time']) |
|
174 |
self.occurrence.end_time = self.occurrence.start_time + timedelta( |
|
175 |
minutes=self.cleaned_data['duration']) |
|
176 |
self.occurrence.save() |
|
177 |
creator = get_request().user |
|
178 |
self.instance.participants = self.cleaned_data['participants'] |
|
179 |
self.instance.services = self.cleaned_data['services'] |
|
180 |
self.instance.save() |
|
181 |
return self.instance |
calebasse/agenda/managers.py | ||
---|---|---|
1 | 1 |
|
2 |
from datetime import datetime, timedelta, date |
|
2 |
from datetime import datetime, timedelta, date, time
|
|
3 | 3 |
from interval import IntervalSet |
4 | 4 |
|
5 |
from django.db import models
|
|
6 |
from model_utils.managers import InheritanceManager |
|
5 |
from django.db.models import Q
|
|
6 |
from model_utils.managers import InheritanceManager, PassThroughManager, InheritanceQuerySet
|
|
7 | 7 |
|
8 | 8 |
from calebasse.agenda.conf import default |
9 |
from calebasse.utils import weeks_since_epoch |
|
9 | 10 |
from calebasse import agenda |
10 | 11 |
|
11 | 12 |
__all__ = ( |
12 | 13 |
'EventManager', |
13 |
'OccurrenceManager', |
|
14 | 14 |
) |
15 | 15 |
|
16 |
class EventManager(InheritanceManager): |
|
17 |
""" This class allows you to manage events, appointment, ... |
|
18 |
""" |
|
19 |
|
|
20 |
def _set_event(self, event, participants=[], description='', services=[], |
|
21 |
start_datetime=None, end_datetime=None, note=None, room=None, **rrule_params): |
|
22 |
""" Private method to configure an Event or an EventAct |
|
23 |
""" |
|
24 |
event.description = description |
|
25 |
event.participants = participants |
|
26 |
event.services = services |
|
27 |
event.room = room |
|
28 |
if note is not None: |
|
29 |
event.notes.create(note=note) |
|
30 |
start_datetime = start_datetime or datetime.now().replace( |
|
31 |
minute=0, second=0, microsecond=0 |
|
32 |
) |
|
33 |
occurence_duration = default.DEFAULT_OCCURRENCE_DURATION |
|
34 |
end_datetime = end_datetime or start_datetime + occurence_duration |
|
35 |
event.add_occurrences(start_datetime, end_datetime, **rrule_params) |
|
36 |
event.save() |
|
37 |
|
|
38 |
return event |
|
39 | 16 |
|
40 |
|
|
41 |
def create_event(self, title, event_type, participants=[], description='', |
|
42 |
services=[], start_datetime=None, end_datetime=None, room=None, note=None, |
|
43 |
**rrule_params): |
|
44 |
""" |
|
45 |
Convenience function to create an ``Event``, optionally create an |
|
46 |
``EventType``, and associated ``Occurrence``s. ``Occurrence`` creation |
|
47 |
rules match those for ``Event.add_occurrences``. |
|
48 |
|
|
49 |
Args: |
|
50 |
event_type: can be either an ``EventType`` object or the label |
|
51 |
is either created or retrieved. |
|
52 |
participants: List of CalebasseUser |
|
53 |
start_datetime: will default to the current hour if ``None`` |
|
54 |
end_datetime: will default to ``start_datetime`` plus |
|
55 |
default.DEFAULT_OCCURRENCE_DURATION hour if ``None`` |
|
56 |
freq, count, rrule_params: |
|
57 |
follow the ``dateutils`` API (see http://labix.org/python-dateutil) |
|
58 |
Returns: |
|
59 |
Event object |
|
60 |
""" |
|
61 |
|
|
62 |
if isinstance(event_type, str): |
|
63 |
event_type, created = agenda.models.EventType.objects.get_or_create( |
|
64 |
label=event_type |
|
65 |
) |
|
66 |
event = self.create(title=title, event_type=event_type) |
|
67 |
|
|
68 |
return self._set_event(event, participants, services = services, |
|
69 |
start_datetime = start_datetime, end_datetime = end_datetime, |
|
70 |
room=room, **rrule_params) |
|
71 |
|
|
72 |
def create_holiday(self, start_date, end_date, peoples=[], services=[], motive=''): |
|
73 |
event_type, created = agenda.models.EventType.objects.get_or_create( |
|
74 |
label=u"Vacances" |
|
75 |
) |
|
76 |
event = self.create(title="Conge", event_type=event_type) |
|
77 |
start_datetime = datetime(start_date.year, start_date.month, start_date.day) |
|
78 |
end_datetime = datetime(end_date.year, end_date.month, end_date.day, 23, 59) |
|
79 |
return self._set_event(event, peoples, motive, services, start_datetime, end_datetime) |
|
80 |
|
|
81 |
class OccurrenceManager(models.Manager): |
|
82 |
|
|
83 |
def daily_occurrences(self, date=None, participants=None, services=None, |
|
84 |
event_type=None): |
|
85 |
''' |
|
86 |
Returns a queryset of for instances that have any overlap with a |
|
87 |
particular day. |
|
88 |
|
|
89 |
Args: |
|
90 |
date: may be either a datetime.datetime, datetime.date object, or |
|
91 |
``None``. If ``None``, default to the current day. |
|
92 |
participants: a list of CalebasseUser |
|
93 |
services: a list of services |
|
94 |
event_type: a single, or a list of, event types |
|
95 |
''' |
|
96 |
date = date or datetime.now() |
|
97 |
start = datetime(date.year, date.month, date.day) |
|
98 |
end = start.replace(hour=23, minute=59, second=59) |
|
99 |
qs = self.select_related('event').filter( |
|
100 |
models.Q( |
|
101 |
start_time__gte=start, |
|
102 |
start_time__lte=end, |
|
103 |
) | |
|
104 |
models.Q( |
|
105 |
end_time__gte=start, |
|
106 |
end_time__lte=end, |
|
107 |
) | |
|
108 |
models.Q( |
|
109 |
start_time__lt=start, |
|
110 |
end_time__gt=end, |
|
111 |
) |
|
112 |
) |
|
113 |
|
|
114 |
if participants: |
|
115 |
qs = qs.filter(event__participants__in=participants) |
|
116 |
if services: |
|
117 |
qs = qs.filter(event__services__in=services) |
|
118 |
if event_type: |
|
119 |
if type(event_type) is list: |
|
120 |
qs = qs.filter(event__event_type__in=event_type) |
|
121 |
else: |
|
122 |
qs = qs.filter(event__event_type=event_type) |
|
17 |
class EventQuerySet(InheritanceQuerySet): |
|
18 |
def for_today(self, today=None): |
|
19 |
today = today or date.today() |
|
20 |
weeks = weeks_since_epoch(today) |
|
21 |
filters = [Q(start_datetime__gte=datetime.combine(today, time()), |
|
22 |
start_datetime__lte=datetime.combine(today, time(23,59,59))) ] |
|
23 |
base_q = Q(start_datetime__lte=datetime.combine(today, time(23,59,59))) & \ |
|
24 |
(Q(recurrence_end_date__gte=today) | |
|
25 |
Q(recurrence_end_date__isnull=True)) |
|
26 |
for period in range(1, 6): |
|
27 |
filters.append(base_q & Q(recurrence_week_offset=weeks % period, |
|
28 |
recurrence_week_period=period, recurrence_week_day=today.weekday())) |
|
29 |
qs = self.filter(reduce(Q.__or__, filters)) |
|
123 | 30 |
return qs |
124 | 31 |
|
125 |
def daily_disponibility(self, date, occurrences, participants, time_tables, holidays): |
|
32 |
def today_occurences(self, today=None): |
|
33 |
today = today or date.today() |
|
34 |
self = self.for_today(today) |
|
35 |
occurences = ( e.today_occurence(today) for e in self ) |
|
36 |
return sorted(occurences, key=lambda e: e.start_datetime) |
|
37 |
|
|
38 |
def daily_disponibilities(self, date, events, participants, time_tables, |
|
39 |
holidays): |
|
40 |
'''Slice the day into quarters between 8:00 and 19:00, and returns the |
|
41 |
list of particpants with their status amon free, busy and away for each |
|
42 |
hour and quarters. |
|
43 |
|
|
44 |
date - the date of day we slice |
|
45 |
occurences - a dictionnary of iterable of events indexed by participants |
|
46 |
participants - an iterable of participants |
|
47 |
time_tables - a dictionnaty of timetable applying for this day indexed by participants |
|
48 |
holidays - a dictionnary of holidays applying for this day indexed by participants |
|
49 |
''' |
|
126 | 50 |
result = dict() |
127 | 51 |
quarter = 0 |
128 |
occurrences_set = {}
|
|
52 |
events_set = {}
|
|
129 | 53 |
timetables_set = {} |
130 | 54 |
holidays_set = {} |
131 | 55 |
for participant in participants: |
132 |
occurrences_set[participant.id] = IntervalSet((o.to_interval() for o in occurrences[participant.id] if not o.is_event_absence()))
|
|
56 |
events_set[participant.id] = IntervalSet((o.to_interval() for o in events[participant.id] if not o.is_event_absence()))
|
|
133 | 57 |
timetables_set[participant.id] = IntervalSet((t.to_interval(date) for t in time_tables[participant.id])) |
134 | 58 |
holidays_set[participant.id] = IntervalSet((h.to_interval(date) for h in holidays[participant.id])) |
135 | 59 |
start_datetime = datetime(date.year, date.month, date.day, 8, 0) |
... | ... | |
137 | 61 |
while (start_datetime.hour <= 19): |
138 | 62 |
for participant in participants: |
139 | 63 |
if not result.has_key(start_datetime.hour): |
140 |
result[start_datetime.hour] = [0, 1, 2, 3] |
|
141 |
result[start_datetime.hour][0] = [] |
|
142 |
result[start_datetime.hour][1] = [] |
|
143 |
result[start_datetime.hour][2] = [] |
|
144 |
result[start_datetime.hour][3] = [] |
|
64 |
result[start_datetime.hour] = [[], [], [], []] |
|
145 | 65 |
quarter = 0 |
146 |
|
|
147 | 66 |
interval = IntervalSet.between(start_datetime, end_datetime, False) |
148 |
if interval.intersection(occurrences_set[participant.id]):
|
|
67 |
if interval.intersection(events_set[participant.id]):
|
|
149 | 68 |
result[start_datetime.hour][quarter].append({'id': participant.id, 'dispo': 'busy'}) |
150 | 69 |
elif interval.intersection(holidays_set[participant.id]): |
151 | 70 |
result[start_datetime.hour][quarter].append({'id': participant.id, 'dispo': 'busy'}) |
... | ... | |
158 | 77 |
end_datetime += timedelta(minutes=15) |
159 | 78 |
return result |
160 | 79 |
|
161 |
def next_appoinment(self, patient_record): |
|
162 |
qs = self.next_appoinments(patient_record) |
|
80 |
|
|
81 |
class EventManager(PassThroughManager.for_queryset_class(EventQuerySet), |
|
82 |
InheritanceManager): |
|
83 |
""" This class allows you to manage events, appointment, ... |
|
84 |
""" |
|
85 |
|
|
86 |
def create_event(self, creator, title, event_type, participants=[], description='', |
|
87 |
services=[], start_datetime=None, end_datetime=None, room=None, note=None, periodicity=1, until=False, **kwargs): |
|
88 |
""" |
|
89 |
Convenience function to create an ``Event``, optionally create an |
|
90 |
``EventType``. |
|
91 |
|
|
92 |
Args: |
|
93 |
event_type: can be either an ``EventType`` object or the label |
|
94 |
is either created or retrieved. |
|
95 |
participants: List of CalebasseUser |
|
96 |
start_datetime: will default to the current hour if ``None`` |
|
97 |
end_datetime: will default to ``start_datetime`` plus |
|
98 |
default.DEFAULT_EVENT_DURATION hour if ``None`` |
|
99 |
Returns: |
|
100 |
Event object |
|
101 |
""" |
|
102 |
if isinstance(event_type, str): |
|
103 |
event_type, created = agenda.models.EventType.objects.get_or_create( |
|
104 |
label=event_type |
|
105 |
) |
|
106 |
if not start_datetime: |
|
107 |
now = datetime.now() |
|
108 |
start_datetime = datetime.combine(now.date, time(now.hour)) |
|
109 |
if not end_datetime: |
|
110 |
end_datetime = start_datetime + default.DEFAULT_EVENT_DURATION |
|
111 |
if until is False: |
|
112 |
until = start_datetime.date() |
|
113 |
event = self.create(creator=creator, |
|
114 |
title=title, start_datetime=start_datetime, |
|
115 |
end_datetime=end_datetime, event_type=event_type, |
|
116 |
room=room, recurrence_week_period=periodicity, |
|
117 |
recurrence_end_date=until, |
|
118 |
recurrence_week_day=start_datetime.weekday(), **kwargs) |
|
119 |
event.services = services |
|
120 |
event.participants = participants |
|
121 |
return event |
|
122 |
|
|
123 |
def next_appointment(self, patient_record): |
|
124 |
qs = self.next_appointments(patient_record) |
|
163 | 125 |
if qs: |
164 | 126 |
return qs[0] |
165 | 127 |
else: |
166 | 128 |
return None |
167 | 129 |
|
168 |
def next_appoinments(self, patient_record): |
|
169 |
today = date.today() |
|
170 |
return self.filter(start_time__gt=datetime(today.year, today.month, today.day)).\ |
|
171 |
filter(event__event_type__id=1).\ |
|
172 |
filter(event__eventact__patient=patient_record).\ |
|
173 |
prefetch_related('event__eventact').\ |
|
174 |
order_by('start_time') |
|
130 |
def next_appointments(self, patient_record, today=None): |
|
131 |
from calebasse.actes.models import Act |
|
132 |
acts = Act.objects.next_acts(patient_record, today=today) \ |
|
133 |
.filter(parent_event__isnull=False) \ |
|
134 |
.select_related() |
|
135 |
return [ a.parent_event.today_occurence(a.date) for a in acts ] |
|
175 | 136 |
|
176 |
def last_appoinment(self, patient_record): |
|
177 |
qs = self.last_appoinments(patient_record) |
|
137 |
def last_appointment(self, patient_record):
|
|
138 |
qs = self.last_appointments(patient_record)
|
|
178 | 139 |
if qs: |
179 | 140 |
return qs[0] |
180 | 141 |
else: |
181 | 142 |
return None |
182 | 143 |
|
183 |
def last_appoinments(self, patient_record): |
|
184 |
return self.filter(start_time__lt=datetime.now()).\ |
|
185 |
filter(event__event_type__id=1).\ |
|
186 |
filter(event__eventact__patient=patient_record).\ |
|
187 |
prefetch_related('event__eventact').\ |
|
188 |
order_by('-start_time') |
|
144 |
def last_appointments(self, patient_record, today=None): |
|
145 |
from calebasse.actes.models import Act |
|
146 |
acts = Act.objects.last_acts(patient_record, today=today) \ |
|
147 |
.filter(parent_event__isnull=False) \ |
|
148 |
.select_related() |
|
149 |
return [ a.parent_event.today_occurence(a.date) for a in acts ] |
calebasse/agenda/models.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 | 2 |
|
3 |
from datetime import datetime |
|
4 |
|
|
5 |
from dateutil import rrule |
|
3 |
from datetime import datetime, date, timedelta |
|
4 |
from copy import copy |
|
6 | 5 |
|
7 | 6 |
from django.utils.translation import ugettext_lazy as _ |
8 |
from django.contrib.contenttypes.models import ContentType |
|
9 |
from django.contrib.contenttypes import generic |
|
7 |
from django.contrib.auth.models import User |
|
10 | 8 |
from django.db import models |
11 | 9 |
|
10 |
from ..middleware.request import get_request |
|
12 | 11 |
from calebasse.agenda import managers |
12 |
from calebasse.utils import weeks_since_epoch |
|
13 | 13 |
from interval import Interval |
14 | 14 |
|
15 | 15 |
__all__ = ( |
16 |
'Note', |
|
17 | 16 |
'EventType', |
18 | 17 |
'Event', |
19 |
'Occurrence',
|
|
18 |
'EventWithAct',
|
|
20 | 19 |
) |
21 | 20 |
|
22 |
class Note(models.Model): |
|
23 |
''' |
|
24 |
A generic model for adding simple, arbitrary notes to other models such as |
|
25 |
``Event`` or ``Occurrence``. |
|
26 |
''' |
|
27 |
|
|
28 |
class Meta: |
|
29 |
verbose_name = u'Note' |
|
30 |
verbose_name_plural = u'Notes' |
|
31 |
|
|
32 |
def __unicode__(self): |
|
33 |
return self.note |
|
34 |
|
|
35 |
note = models.TextField(_('note')) |
|
36 |
created = models.DateTimeField(_('created'), auto_now_add=True) |
|
37 |
content_type = models.ForeignKey(ContentType) |
|
38 |
object_id = models.IntegerField() |
|
39 |
|
|
40 |
|
|
41 | 21 |
class EventType(models.Model): |
42 | 22 |
''' |
43 | 23 |
Simple ``Event`` classifcation. |
... | ... | |
55 | 35 |
|
56 | 36 |
class Event(models.Model): |
57 | 37 |
''' |
58 |
Container model for general metadata and associated ``Occurrence`` entries.
|
|
38 |
Container model for general agenda events
|
|
59 | 39 |
''' |
60 | 40 |
objects = managers.EventManager() |
61 | 41 |
|
62 | 42 |
title = models.CharField(_('Title'), max_length=32, blank=True) |
63 | 43 |
description = models.TextField(_('Description'), max_length=100) |
64 | 44 |
event_type = models.ForeignKey(EventType, verbose_name=u"Type d'événement") |
65 |
notes = generic.GenericRelation(Note, verbose_name=_('notes')) |
|
45 |
creator = models.ForeignKey(User, verbose_name=_(u'Créateur'), blank=True, null=True) |
|
46 |
create_date = models.DateTimeField(_(u'Date de création'), auto_now_add=True) |
|
66 | 47 |
|
67 | 48 |
services = models.ManyToManyField('ressources.Service', |
68 | 49 |
null=True, blank=True, default=None) |
... | ... | |
71 | 52 |
room = models.ForeignKey('ressources.Room', blank=True, null=True, |
72 | 53 |
verbose_name=u'Salle') |
73 | 54 |
|
55 |
start_datetime = models.DateTimeField(_('Début'), blank=True, null=True, db_index=True) |
|
56 |
end_datetime = models.DateTimeField(_('Fin'), blank=True, null=True) |
|
57 |
|
|
58 |
PERIODS = ( |
|
59 |
(1, u'Toutes les semaines'), |
|
60 |
(2, u'Une semaine sur deux'), |
|
61 |
(3, u'Une semaine sur trois'), |
|
62 |
(4, 'Une semaine sur quatre'), |
|
63 |
(5, 'Une semaine sur cinq') |
|
64 |
) |
|
65 |
OFFSET = range(0,4) |
|
66 |
recurrence_week_day = models.PositiveIntegerField(default=0) |
|
67 |
recurrence_week_offset = models.PositiveIntegerField( |
|
68 |
choices=zip(OFFSET, OFFSET), |
|
69 |
verbose_name=u"Décalage en semaines par rapport au 1/1/1970 pour le calcul de période", |
|
70 |
default=0, |
|
71 |
db_index=True) |
|
72 |
recurrence_week_period = models.PositiveIntegerField( |
|
73 |
choices=PERIODS, |
|
74 |
verbose_name=u"Période en semaines", |
|
75 |
default=None, |
|
76 |
blank=True, |
|
77 |
null=True, |
|
78 |
db_index=True) |
|
79 |
recurrence_end_date = models.DateField( |
|
80 |
verbose_name=_(u'Fin de la récurrence'), |
|
81 |
blank=True, null=True, |
|
82 |
db_index=True) |
|
83 |
|
|
74 | 84 |
class Meta: |
75 | 85 |
verbose_name = u'Evénement' |
76 | 86 |
verbose_name_plural = u'Evénements' |
77 |
ordering = ('title', ) |
|
78 |
|
|
79 |
|
|
80 |
def __unicode__(self): |
|
81 |
return self.title |
|
82 |
|
|
83 |
def add_occurrences(self, start_time, end_time, room=None, **rrule_params): |
|
87 |
ordering = ('start_datetime', 'end_datetime', 'title') |
|
88 |
|
|
89 |
def __init__(self, *args, **kwargs): |
|
90 |
if kwargs.get('start_datetime') and not kwargs.has_key('recurrence_end_date'): |
|
91 |
kwargs['recurrence_end_date'] = kwargs.get('start_datetime').date() |
|
92 |
super(Event, self).__init__(*args, **kwargs) |
|
93 |
|
|
94 |
def clean(self): |
|
95 |
'''Initialize recurrence fields if they are not.''' |
|
96 |
if self.start_datetime: |
|
97 |
if self.recurrence_week_period: |
|
98 |
if self.recurrence_end_date and self.recurrence_end_date < self.start_datetime.date(): |
|
99 |
self.recurrence_end_date = self.start_datetime.date() |
|
100 |
self.recurrence_week_day = self.start_datetime.weekday() |
|
101 |
self.recurrence_week_offset = weeks_since_epoch(self.start_datetime) % self.recurrence_week_period |
|
102 |
|
|
103 |
def timedelta(self): |
|
104 |
'''Distance between start and end of the event''' |
|
105 |
return self.end_datetime - self.start_datetime |
|
106 |
|
|
107 |
def today_occurence(self, today=None): |
|
108 |
'''For a recurring event compute the today 'Event'. |
|
109 |
|
|
110 |
The computed event is the fake one that you cannot save to the database. |
|
84 | 111 |
''' |
85 |
Add one or more occurences to the event using a comparable API to |
|
86 |
``dateutil.rrule``. |
|
87 |
|
|
88 |
If ``rrule_params`` does not contain a ``freq``, one will be defaulted |
|
89 |
to ``rrule.DAILY``. |
|
90 |
|
|
91 |
Because ``rrule.rrule`` returns an iterator that can essentially be |
|
92 |
unbounded, we need to slightly alter the expected behavior here in order |
|
93 |
to enforce a finite number of occurrence creation. |
|
94 |
|
|
95 |
If both ``count`` and ``until`` entries are missing from ``rrule_params``, |
|
96 |
only a single ``Occurrence`` instance will be created using the exact |
|
97 |
``start_time`` and ``end_time`` values. |
|
112 |
today = today or date.today() |
|
113 |
if not self.is_recurring(): |
|
114 |
if today == self.start_datetime.date(): |
|
115 |
return self |
|
116 |
else: |
|
117 |
return None |
|
118 |
if today.weekday() != self.recurrence_week_day: |
|
119 |
return None |
|
120 |
if weeks_since_epoch(today) % self.recurrence_week_period != self.recurrence_week_offset: |
|
121 |
return None |
|
122 |
if not (self.start_datetime.date() <= today <= self.recurrence_end_date): |
|
123 |
return None |
|
124 |
start_datetime = datetime.combine(today, self.start_datetime.timetz()) |
|
125 |
end_datetime = start_datetime + self.timedelta() |
|
126 |
event = copy(self) |
|
127 |
event.start_datetime = start_datetime |
|
128 |
event.end_datetime = end_datetime |
|
129 |
event.recurrence_end_date = None |
|
130 |
event.recurrence_week_offset = None |
|
131 |
event.recurrence_week_period = None |
|
132 |
event.parent = self |
|
133 |
def save(*args, **kwarks): |
|
134 |
raise RuntimeError() |
|
135 |
event.save = save |
|
136 |
return event |
|
137 |
|
|
138 |
def next_occurence(self, today=None): |
|
139 |
'''Returns the next occurence after today.''' |
|
140 |
today = today or date.today() |
|
141 |
for occurence in self.all_occurences(): |
|
142 |
if occurence.start_datetime.date() > today: |
|
143 |
return occurence |
|
144 |
|
|
145 |
def is_recurring(self): |
|
146 |
'''Is this event multiple ?''' |
|
147 |
return self.recurrence_week_period is not None |
|
148 |
|
|
149 |
def all_occurences(self, limit=90): |
|
150 |
'''Returns all occurences of this event as a list or pair (start_datetime, |
|
151 |
end_datetime). |
|
152 |
|
|
153 |
limit - compute occurrences until limit days in the future |
|
154 |
|
|
155 |
Default is to limit to 90 days. |
|
98 | 156 |
''' |
99 |
rrule_params.setdefault('freq', rrule.DAILY) |
|
100 |
|
|
101 |
if 'count' not in rrule_params and 'until' not in rrule_params: |
|
102 |
self.occurrence_set.create(start_time=start_time, end_time=end_time) |
|
157 |
if self.recurrence_week_period: |
|
158 |
day = self.start_datetime.date() |
|
159 |
max_end_date = max(date.today(), self.start_datetime.date()) + timedelta(days=limit) |
|
160 |
end_date = min(self.recurrence_end_date or max_end_date, max_end_date) |
|
161 |
delta = timedelta(days=self.recurrence_week_period*7) |
|
162 |
while day <= end_date: |
|
163 |
yield self.today_occurence(day) |
|
164 |
day += delta |
|
103 | 165 |
else: |
104 |
delta = end_time - start_time |
|
105 |
for ev in rrule.rrule(dtstart=start_time, **rrule_params): |
|
106 |
self.occurrence_set.create(start_time=ev, end_time=ev + delta) |
|
166 |
yield self |
|
107 | 167 |
|
108 |
def upcoming_occurrences(self): |
|
109 |
''' |
|
110 |
Return all occurrences that are set to start on or after the current |
|
111 |
time. |
|
112 |
''' |
|
113 |
return self.occurrence_set.filter(start_time__gte=datetime.now()) |
|
114 |
|
|
115 |
def next_occurrence(self): |
|
116 |
''' |
|
117 |
Return the single occurrence set to start on or after the current time |
|
118 |
if available, otherwise ``None``. |
|
119 |
''' |
|
120 |
upcoming = self.upcoming_occurrences() |
|
121 |
return upcoming and upcoming[0] or None |
|
122 |
|
|
123 |
def daily_occurrences(self, dt=None): |
|
124 |
''' |
|
125 |
Convenience method wrapping ``Occurrence.objects.daily_occurrences``. |
|
126 |
''' |
|
127 |
return Occurrence.objects.daily_occurrences(dt=dt, event=self) |
|
128 |
|
|
129 |
|
|
130 |
class Occurrence(models.Model): |
|
131 |
''' |
|
132 |
Represents the start end time for a specific occurrence of a master ``Event`` |
|
133 |
object. |
|
134 |
''' |
|
135 |
start_time = models.DateTimeField() |
|
136 |
end_time = models.DateTimeField() |
|
137 |
event = models.ForeignKey('Event', verbose_name=_('event'), editable=False) |
|
138 |
notes = models.ManyToManyField('Note', verbose_name=_('notes'), |
|
139 |
null=True, blank=True, default=None) |
|
140 |
|
|
141 |
objects = managers.OccurrenceManager() |
|
168 |
def to_interval(self): |
|
169 |
return Interval(self.start_datetime, self.end_datetime) |
|
142 | 170 |
|
143 |
class Meta: |
|
144 |
verbose_name = u'Occurrence' |
|
145 |
verbose_name_plural = u'Occurrences' |
|
146 |
ordering = ('start_time', 'end_time') |
|
171 |
def is_event_absence(self): |
|
172 |
return False |
|
147 | 173 |
|
148 | 174 |
def __unicode__(self): |
149 |
return u'%s: %s' % (self.title, self.start_time.isoformat())
|
|
175 |
return self.title
|
|
150 | 176 |
|
151 |
def __cmp__(self, other): |
|
152 |
return cmp(self.start_time, other.start_time) |
|
153 | 177 |
|
154 |
@property |
|
155 |
def title(self): |
|
156 |
return self.event.title |
|
178 |
class EventWithActManager(managers.EventManager): |
|
179 |
def create_patient_appointment(self, creator, title, patient, |
|
180 |
doctors=[], act_type=None, service=None, start_datetime=None, end_datetime=None, |
|
181 |
room=None, periodicity=1, until=False): |
|
182 |
appointment = self.create_event(creator=creator, |
|
183 |
title=title, |
|
184 |
event_type=EventType(id=1), |
|
185 |
participants=doctors, |
|
186 |
services=[service], |
|
187 |
start_datetime=start_datetime, |
|
188 |
end_datetime=end_datetime, |
|
189 |
room=room, |
|
190 |
periodicity=periodicity, |
|
191 |
until=until, |
|
192 |
act_type=act_type, |
|
193 |
patient=patient) |
|
194 |
return appointment |
|
195 |
|
|
196 |
|
|
197 |
class EventWithAct(Event): |
|
198 |
'''An event corresponding to an act.''' |
|
199 |
objects = EventWithActManager() |
|
200 |
act_type = models.ForeignKey('ressources.ActType', |
|
201 |
verbose_name=u'Type d\'acte') |
|
202 |
patient = models.ForeignKey('dossiers.PatientRecord') |
|
157 | 203 |
|
158 | 204 |
@property |
159 |
def event_type(self): |
|
160 |
return self.event.event_type |
|
161 |
|
|
162 |
def to_interval(self): |
|
163 |
return Interval(self.start_time, self.end_time) |
|
205 |
def act(self): |
|
206 |
return self.get_or_create_act() |
|
207 |
|
|
208 |
def get_or_create_act(self, today=None): |
|
209 |
from ..actes.models import Act, ActValidationState |
|
210 |
today = today or self.start_datetime.date() |
|
211 |
act, created = Act.objects.get_or_create(patient=self.patient, |
|
212 |
parent_event=getattr(self, 'parent', self), |
|
213 |
date=today, |
|
214 |
act_type=self.act_type) |
|
215 |
self.update_act(act) |
|
216 |
if created: |
|
217 |
ActValidationState.objects.create(act=act, state_name='NON_VALIDE', |
|
218 |
author=self.creator, previous_state=None) |
|
219 |
return act |
|
220 |
|
|
221 |
def update_act(self, act): |
|
222 |
'''Update an act to match details of the meeting''' |
|
223 |
delta = self.timedelta() |
|
224 |
duration = delta.seconds // 60 |
|
225 |
act._duration = duration |
|
226 |
act.doctors = self.participants.select_subclasses() |
|
227 |
act.act_type = self.act_type |
|
228 |
act.patient = self.patient |
|
229 |
act.date = self.start_datetime.date() |
|
230 |
act.save() |
|
231 |
|
|
232 |
def save(self, *args, **kwargs): |
|
233 |
'''Force event_type to be patient meeting.''' |
|
234 |
self.clean() |
|
235 |
self.event_type = EventType(id=1) |
|
236 |
super(EventWithAct, self).save(*args, **kwargs) |
|
237 |
# list of occurences may have changed |
|
238 |
from ..actes.models import Act |
|
239 |
occurences = list(self.all_occurences()) |
|
240 |
acts = Act.objects.filter(parent_event=self) |
|
241 |
occurences_by_date = dict((o.start_datetime.date(), o) for o in occurences) |
|
242 |
acts_by_date = dict() |
|
243 |
for a in acts: |
|
244 |
# sanity check |
|
245 |
assert a.date not in acts_by_date |
|
246 |
acts_by_date[a.date] = a |
|
247 |
for a in acts: |
|
248 |
o = occurences_by_date.get(a.date) |
|
249 |
if o: |
|
250 |
o.update_act(a) |
|
251 |
else: |
|
252 |
if len(a.actvalidationstate_set.all()) > 1: |
|
253 |
a.parent_event = None |
|
254 |
a.save() |
|
255 |
else: |
|
256 |
a.delete() |
|
257 |
participants = self.participants.select_subclasses() |
|
258 |
for o in occurences: |
|
259 |
if o.start_datetime.date() in acts_by_date: |
|
260 |
continue |
|
261 |
o.get_or_create_act() |
|
164 | 262 |
|
165 | 263 |
def is_event_absence(self): |
166 |
if self.event.event_type.id != 1: |
|
167 |
return False |
|
168 |
event_act = self.event.eventact |
|
169 |
return event_act.is_absent() |
|
264 |
return self.act.is_absent() |
|
265 |
|
|
266 |
def __unicode__(self): |
|
267 |
kwargs = { |
|
268 |
'patient': self.patient, |
|
269 |
'start_datetime': self.start_datetime, |
|
270 |
'act_type': self.act_type |
|
271 |
} |
|
272 |
kwargs['doctors'] = ', '.join(map(unicode, self.participants.all())) if self.id else '' |
|
273 |
return u'Rdv le {start_datetime} de {patient} avec {doctors} pour ' \ |
|
274 |
'{act_type} ({act_type.id})'.format(**kwargs) |
calebasse/agenda/templates/agenda/ajax-worker-tab.html | ||
---|---|---|
23 | 23 |
{% endif %} |
24 | 24 |
{% if appointment.event_id %} |
25 | 25 |
{% if appointment.patient_record_id %} |
26 |
<button title="Éditer un rendez-vous" class="edit-appointment icon-edit" data-occurrence-id="{{ appointment.occurrence_id }}"></button>
|
|
26 |
<button title="Éditer un rendez-vous" class="edit-appointment icon-edit" data-event-id="{{ appointment.event_id }}"></button>
|
|
27 | 27 |
{% else %} |
28 |
<button title="Éditer un événement" class="edit-event icon-edit" data-occurrence-id="{{ appointment.occurrence_id }}">
|
|
28 |
<button title="Éditer un événement" class="edit-event icon-edit" data-event-id="{{ appointment.event_id }}">
|
|
29 | 29 |
{% endif %} |
30 |
<button class="remove-appointment icon-remove-sign" title="Supprimer un rendez-vous" data-occurrence-id="{{ appointment.occurrence_id }}" data-rdv="{{ appointment.title }}"></button>
|
|
30 |
<button class="remove-appointment icon-remove-sign" title="Supprimer un rendez-vous" data-event-id="{{ appointment.event_id }}" data-rdv="{{ appointment.title }}"></button>
|
|
31 | 31 |
{% endif %} |
32 | 32 |
</span> |
33 | 33 |
</h3> |
... | ... | |
69 | 69 |
</p> |
70 | 70 |
<a href="/{{ service }}/dossiers/{{ appointment.patient_record_id }}/view" target="_blank">Dossier patient</a> - |
71 | 71 |
<a href="/{{ service }}/dossiers/{{ appointment.patient_record_id }}/view#tab=5" target="_blank">Prochains rendez-vous</a> - |
72 |
<a href="#" class="generate-mail-btn" data-dossier-id="{{ appointment.patient_record_id }}" data-occurence-id="{{ appointment.occurrence_id }}" data-next-url="{{ request.get_full_path }}">Courrier</a> |
|
72 |
<a href="#" class="generate-mail-btn" data-dossier-id="{{ appointment.patient_record_id }}" data-date="{{date}}" data-occurence-id="{{ appointment.occurrence_id }}" data-next-url="{{ request.get_full_path }}">Courrier</a>
|
|
73 | 73 |
{% endif %} |
74 | 74 |
{% if appointment.validation %} |
75 | 75 |
<div><span>{% if appointment.validation.1 %}<strong>{{ appointment.validation.2 }}</strong>, le {{ appointment.validation.1.created }} par {{ appointment.validation.1.author }} |
calebasse/agenda/templates/agenda/ressources.html | ||
---|---|---|
70 | 70 |
{% endif %} |
71 | 71 |
{% if appointment.event_id %} |
72 | 72 |
{% if appointment.patient_record_id %} |
73 |
<button title="Éditer un rendez-vous" class="edit-appointment icon-edit" data-occurrence-id="{{ appointment.occurrence_id }}"></button>
|
|
73 |
<button title="Éditer un rendez-vous" class="edit-appointment icon-edit" data-event-id="{{ appointment.event_id }}"></button>
|
|
74 | 74 |
{% else %} |
75 |
<button title="Éditer un événement" class="edit-event icon-edit" data-occurrence-id="{{ appointment.occurrence_id }}">
|
|
75 |
<button title="Éditer un événement" class="edit-event icon-edit" data-event-id="{{ appointment.event_id }}">
|
|
76 | 76 |
{% endif %} |
77 |
<button class="remove-appointment icon-remove-sign" title="Supprimer un rendez-vous" data-occurrence-id="{{ appointment.occurrence_id }}" data-rdv="{{ appointment.title }}"></button>
|
|
77 |
<button class="remove-appointment icon-remove-sign" title="Supprimer un rendez-vous" data-event-id="{{ appointment.event_id }}" data-rdv="{{ appointment.title }}"></button>
|
|
78 | 78 |
{% endif %} |
79 | 79 |
</span> |
80 | 80 |
</h3> |
... | ... | |
112 | 112 |
</p> |
113 | 113 |
<a href="/{{ service }}/dossiers/{{ appointment.patient_record_id }}/view" target="_blank">Dossier patient</a> - |
114 | 114 |
<a href="/{{ service }}/dossiers/{{ appointment.patient_record_id }}/view#tab=5" target="_blank">Prochains rendez-vous</a> - |
115 |
<a href="#" class="generate-mail-btn" data-dossier-id="{{ appointment.patient_record_id }}" data-occurence-id="{{ appointment.occurrence_id }}" data-next-url="{{ request.get_full_path }}">Courrier</a> |
|
115 |
<a href="#" class="generate-mail-btn" data-dossier-id="{{ appointment.patient_record_id }}" data-date="{{date}}" data-occurence-id="{{ appointment.occurrence_id }}" data-next-url="{{ request.get_full_path }}">Courrier</a>
|
|
116 | 116 |
{% endif %} |
117 | 117 |
{% if appointment.validation %} |
118 | 118 |
<div><span>{% if appointment.validation.1 %}<strong>{{ appointment.validation.2 }}</strong>, le {{ appointment.validation.1.created }} par {{ appointment.validation.1.author }} |
calebasse/agenda/tests.py | ||
---|---|---|
4 | 4 |
|
5 | 5 |
Replace this with more appropriate tests for your application. |
6 | 6 |
""" |
7 |
from datetime import datetime |
|
7 |
from datetime import datetime, date, timedelta
|
|
8 | 8 |
|
9 | 9 |
from django.test import TestCase |
10 | 10 |
from django.contrib.auth.models import User |
11 |
from datetime import datetime, date |
|
12 |
from dateutil import rrule |
|
13 | 11 |
|
14 |
from calebasse.agenda.models import Occurrence, Event |
|
15 |
from calebasse.actes.models import EventAct |
|
16 |
from calebasse.dossiers.models import PatientRecord |
|
12 |
from calebasse.agenda.models import Event, EventType, EventWithAct |
|
17 | 13 |
from calebasse.dossiers.models import create_patient |
18 | 14 |
from calebasse.ressources.models import ActType, Service, WorkerType |
19 | 15 |
from calebasse.personnes.models import Worker |
16 |
from calebasse.actes.models import Act |
|
20 | 17 |
|
21 | 18 |
class EventTest(TestCase): |
22 | 19 |
fixtures = ['services', 'filestates'] |
23 | 20 |
def setUp(self): |
24 | 21 |
self.creator = User.objects.create(username='John') |
25 | 22 |
|
26 |
def test_create_events(self): |
|
27 |
event = Event.objects.create_event("test 1", 'un test', description='42 42', |
|
28 |
start_datetime=datetime(2012, 10, 20, 13), end_datetime=datetime(2012, 10, 20, 14), |
|
29 |
freq=rrule.WEEKLY, count=3) |
|
30 |
self.assertEqual(str(event), 'test 1') |
|
23 |
def test_recurring_events(self): |
|
24 |
event = Event.objects.create(start_datetime=datetime(2012, 10, 20, 13), |
|
25 |
end_datetime=datetime(2012, 10, 20, 13, 30), event_type=EventType(id=1), |
|
26 |
recurrence_week_period=3, recurrence_end_date=date(2012, 12, 1)) |
|
27 |
event.clean() |
|
28 |
event.save() |
|
29 |
# Test model |
|
30 |
self.assertEqual(event.timedelta(), timedelta(minutes=30)) |
|
31 |
occurences = list(event.all_occurences()) |
|
32 |
self.assertEqual(occurences[0].start_datetime, |
|
33 |
datetime(2012, 10, 20, 13)) |
|
34 |
self.assertEqual(occurences[0].end_datetime, |
|
35 |
datetime(2012, 10, 20, 13, 30)) |
|
36 |
self.assertEqual(occurences[1].start_datetime, |
|
37 |
datetime(2012, 11, 10, 13)) |
|
38 |
self.assertEqual(occurences[1].end_datetime, |
|
39 |
datetime(2012, 11, 10, 13, 30)) |
|
40 |
self.assertEqual(occurences[2].start_datetime, |
|
41 |
datetime(2012, 12, 1, 13)) |
|
42 |
self.assertEqual(occurences[2].end_datetime, |
|
43 |
datetime(2012, 12, 1, 13, 30)) |
|
44 |
self.assertEqual(len(occurences), 3) |
|
45 |
self.assertTrue(event.is_recurring()) |
|
46 |
self.assertEqual(event.next_occurence(today=date(2012, 10, 21)).start_datetime, |
|
47 |
datetime(2012, 11, 10, 13)) |
|
48 |
self.assertEqual(event.next_occurence(today=date(2012, 11, 30)).start_datetime, |
|
49 |
datetime(2012, 12, 1, 13)) |
|
50 |
self.assertEqual(event.next_occurence(today=date(2012, 12, 2)), None) |
|
51 |
# Test manager |
|
52 |
i = datetime(2012, 10, 1) |
|
53 |
while i < datetime(2013, 2, 1): |
|
54 |
d = i.date() |
|
55 |
if d in (date(2012, 10, 20), date(2012, 11, 10), date(2012, 12, 1)): |
|
56 |
self.assertEqual(list(Event.objects.for_today(d)), [event], d) |
|
57 |
else: |
|
58 |
self.assertEqual(list(Event.objects.for_today(d)), [], d) |
|
59 |
i += timedelta(days=1) |
|
60 |
|
|
31 | 61 |
|
32 | 62 |
def test_create_appointments(self): |
33 |
service_camsp = Service.objects.create(name='CAMSP')
|
|
63 |
service_camsp = Service.objects.get(name='CAMSP')
|
|
34 | 64 |
|
35 |
patient = create_patient('Jean', 'Lepoulpe', service_camsp, self.creator, date_selected=datetime(2020, 10, 5))
|
|
65 |
patient = create_patient('Jean', 'LEPOULPE', service_camsp, self.creator, date_selected=datetime(2020, 10, 5))
|
|
36 | 66 |
wtype = WorkerType.objects.create(name='ElDoctor', intervene=True) |
37 | 67 |
therapist1 = Worker.objects.create(first_name='Bob', last_name='Leponge', type=wtype) |
38 | 68 |
therapist2 = Worker.objects.create(first_name='Jean', last_name='Valjean', type=wtype) |
39 |
therapist3 = Worker.objects.create(first_name='Pierre', last_name='PaulJacques', type=wtype) |
|
40 | 69 |
act_type = ActType.objects.create(name='trepanation') |
41 | 70 |
service = Service.objects.create(name='CMPP') |
42 |
act_event = EventAct.objects.create_patient_appointment(self.creator, 'RDV avec M X', patient,
|
|
71 |
appointment1 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV avec M X', patient,
|
|
43 | 72 |
[therapist1, therapist2], act_type, service, |
44 | 73 |
start_datetime=datetime(2020, 10, 2, 7, 15), |
45 | 74 |
end_datetime=datetime(2020, 10, 2, 9, 20), |
46 |
freq=rrule.WEEKLY, byweekday=rrule.FR, until=datetime(2040, 10, 2)) |
|
47 |
act_event2 = EventAct.objects.create_patient_appointment(self.creator, 'RDV avec M Y', patient, [therapist3], |
|
75 |
periodicity=None, until=None) |
|
76 |
self.assertEqual(unicode(appointment1), u'Rdv le 2020-10-02 07:15:00 de Jean LEPOULPE avec Bob LEPONGE, Jean VALJEAN pour trepanation (1)') |
|
77 |
|
|
78 |
def test_create_recurring_appointment(self): |
|
79 |
service_camsp = Service.objects.get(name='CAMSP') |
|
80 |
patient = create_patient('Jean', 'LEPOULPE', service_camsp, self.creator, date_selected=datetime(2020, 10, 5)) |
|
81 |
wtype = WorkerType.objects.create(name='ElDoctor', intervene=True) |
|
82 |
therapist3 = Worker.objects.create(first_name='Pierre', last_name='PaulJacques', type=wtype) |
|
83 |
act_type = ActType.objects.create(name='trepanation') |
|
84 |
service = Service.objects.create(name='CMPP') |
|
85 |
appointment2 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV avec M Y', patient, [therapist3], |
|
48 | 86 |
act_type, service, start_datetime=datetime(2020, 10, 2, 10, 15), |
49 | 87 |
end_datetime=datetime(2020, 10, 2, 12, 20), |
50 |
freq=rrule.WEEKLY, byweekday=rrule.FR, until=datetime(2021, 10, 2)) |
|
51 |
self.assertEqual(str(act_event), 'Rdv le 2020-10-02 07:15:00 de Jean Lepoulpe avec Bob Leponge, Jean Valjean pour trepanation (1)') |
|
52 |
self.assertEqual( |
|
53 |
str(Occurrence.objects.daily_occurrences(datetime(2020, 10, 8), [therapist2])), |
|
54 |
'[]' |
|
55 |
) |
|
56 |
self.assertEqual( |
|
57 |
str(Occurrence.objects.daily_occurrences(datetime(2020, 10, 9), [therapist2])), |
|
58 |
'[<Occurrence: RDV avec M X: 2020-10-09T07:15:00>]' |
|
59 |
) |
|
60 |
self.assertEqual( |
|
61 |
str(Occurrence.objects.daily_occurrences(datetime(2020, 10, 9), [therapist3])), |
|
62 |
'[<Occurrence: RDV avec M Y: 2020-10-09T10:15:00>]' |
|
63 |
) |
|
88 |
periodicity=2, until=date(2020, 10, 16)) |
|
89 |
occurences = list(appointment2.all_occurences()) |
|
90 |
self.assertEqual(len(occurences), 2) |
|
91 |
self.assertEqual(Act.objects.filter(parent_event=appointment2).count(), |
|
92 |
2) |
|
93 |
self.assertEqual(occurences[0].act.date, occurences[0].start_datetime.date()) |
|
94 |
self.assertEqual(occurences[1].act.date, occurences[1].start_datetime.date()) |
|
95 |
self.assertEqual(Act.objects.filter(parent_event=appointment2).count(), |
|
96 |
2) |
|
97 |
appointment2.recurrence_week_period = None |
|
98 |
appointment2.save() |
|
99 |
self.assertEqual(Act.objects.filter(parent_event=appointment2).count(), |
|
100 |
1) |
|
101 |
appointment2.recurrence_week_period = 2 |
|
102 |
appointment2.recurrence_end_date = date(2020, 10, 16) |
|
103 |
appointment2.save() |
|
104 |
occurences = list(appointment2.all_occurences()) |
|
105 |
self.assertEqual(len(occurences), 2) |
|
106 |
self.assertEqual(Act.objects.filter(parent_event=appointment2).count(), 2) |
|
107 |
occurences[1].act.set_state('ANNUL_NOUS', self.creator) |
|
108 |
appointment2.recurrence_week_period = None |
|
109 |
appointment2.save() |
|
110 |
occurences = list(appointment2.all_occurences()) |
|
111 |
self.assertEqual(len(occurences), 1) |
|
112 |
self.assertEqual(Act.objects.filter(parent_event=appointment2).count(), 1) |
|
113 |
self.assertEqual(Act.objects.count(), 2) |
|
64 | 114 |
|
65 |
def test_create_holiday(self): |
|
66 |
"""docstring for test_create_event""" |
|
67 |
wtype = WorkerType.objects.create(name='ElProfessor', intervene=True) |
|
68 |
user = Worker.objects.create(first_name='Jean-Claude', last_name='Van Damme', type=wtype) |
|
69 |
event = Event.objects.create_holiday(date(2012, 12, 12), date(2012,12,30), |
|
70 |
[user], motive='tournage d\'un film') |
|
71 |
self.assertEqual(str(event), 'Conge') |
|
72 |
#event = user.event.occurrence_set.all()[0] |
|
73 |
#self.assertEqual(event.end_time - event.start_time, timedelta(0, 7200)) |
calebasse/agenda/urls.py | ||
---|---|---|
16 | 16 |
url(r'^nouveau-rdv/$', |
17 | 17 |
NewAppointmentView.as_view(), |
18 | 18 |
name='nouveau-rdv'), |
19 |
url(r'^update-rdv/(?P<id>\d+)$',
|
|
19 |
url(r'^update-rdv/(?P<pk>\d+)$',
|
|
20 | 20 |
UpdateAppointmentView.as_view(), |
21 | 21 |
name='update-rdv'), |
22 | 22 |
url(r'^new-event/$', |
23 | 23 |
NewEventView.as_view(), |
24 | 24 |
name='new-event'), |
25 |
url(r'^update-event/(?P<id>\d+)$',
|
|
25 |
url(r'^update-event/(?P<pk>\d+)$',
|
|
26 | 26 |
UpdateEventView.as_view(), |
27 | 27 |
name='update-event'), |
28 | 28 |
url(r'^activite-du-service/$', |
calebasse/agenda/views.py | ||
---|---|---|
7 | 7 |
from django.http import HttpResponseRedirect |
8 | 8 |
|
9 | 9 |
from calebasse.cbv import TemplateView, CreateView, UpdateView |
10 |
from calebasse.agenda.models import Occurrence, Event, EventType
|
|
10 |
from calebasse.agenda.models import Event, EventType, EventWithAct
|
|
11 | 11 |
from calebasse.personnes.models import TimeTable, Holiday |
12 |
from calebasse.actes.models import EventAct |
|
13 | 12 |
from calebasse.agenda.appointments import get_daily_appointments, get_daily_usage |
14 | 13 |
from calebasse.personnes.models import Worker |
15 | 14 |
from calebasse.ressources.models import WorkerType, Room |
16 |
from calebasse.actes.validation import get_acts_of_the_day |
|
15 |
from calebasse.actes.validation import (get_acts_of_the_day, |
|
16 |
get_days_with_acts_not_locked) |
|
17 | 17 |
from calebasse.actes.validation_states import VALIDATION_STATES |
18 | 18 |
from calebasse.actes.models import Act, ValidationMessage |
19 |
from calebasse.actes.validation import (automated_validation, |
|
20 |
unlock_all_acts_of_the_day, are_all_acts_of_the_day_locked) |
|
19 |
from calebasse.actes.validation import (automated_validation, unlock_all_acts_of_the_day) |
|
21 | 20 |
from calebasse import cbv |
22 | 21 |
|
23 |
from forms import (NewAppointmentForm, NewEventForm, |
|
24 |
UpdateAppointmentForm, UpdateEventForm) |
|
22 |
from forms import (NewAppointmentForm, NewEventForm, UpdateAppointmentForm) |
|
25 | 23 |
|
26 | 24 |
def redirect_today(request, service): |
27 | 25 |
'''If not date is given we redirect on the agenda for today''' |
... | ... | |
70 | 68 |
appointments_times = dict() |
71 | 69 |
appoinment_type = EventType.objects.get(id=1) |
72 | 70 |
meeting_type = EventType.objects.get(id=2) |
73 |
occurrences = Occurrence.objects.daily_occurrences(context['date'], |
|
74 |
services=[self.service], |
|
75 |
event_type=[appoinment_type, meeting_type]) |
|
76 |
for occurrence in occurrences: |
|
77 |
start_time = occurrence.start_time.strftime("%H:%M") |
|
78 |
if not appointments_times.has_key(start_time): |
|
79 |
appointments_times[start_time] = dict() |
|
80 |
appointments_times[start_time]['row'] = 0 |
|
81 |
appointments_times[start_time]['appointments'] = [] |
|
71 |
plain_events = Event.objects.for_today(self.date) \ |
|
72 |
.filter(services=self.service, |
|
73 |
event_type__in=[appoinment_type, meeting_type]) |
|
74 |
events = [ e.today_occurence(self.date) for e in plain_events ] |
|
75 |
for event in events: |
|
76 |
start_datetime = event.start_datetime.strftime("%H:%M") |
|
77 |
if not appointments_times.has_key(start_datetime): |
|
78 |
appointments_times[start_datetime] = dict() |
|
79 |
appointments_times[start_datetime]['row'] = 0 |
|
80 |
appointments_times[start_datetime]['appointments'] = [] |
|
82 | 81 |
appointment = dict() |
83 |
length = occurrence.end_time - occurrence.start_time
|
|
82 |
length = event.end_datetime - event.start_datetime
|
|
84 | 83 |
if length.seconds: |
85 | 84 |
length = length.seconds / 60 |
86 | 85 |
appointment['length'] = "%sm" % length |
87 |
if occurrence.event.event_type == EventType.objects.get(id=1):
|
|
86 |
if event.event_type == EventType.objects.get(id=1): |
|
88 | 87 |
appointment['type'] = 1 |
89 |
event_act = occurrence.event.eventact
|
|
88 |
event_act = event.act
|
|
90 | 89 |
appointment['label'] = event_act.patient.display_name |
91 | 90 |
appointment['act'] = event_act.act_type.name |
92 |
elif occurrence.event.event_type == EventType.objects.get(id=2):
|
|
91 |
elif event.event_type == EventType.objects.get(id=2): |
|
93 | 92 |
appointment['type'] = 2 |
94 |
appointment['label'] = '%s - %s' % (occurrence.event.event_type.label,
|
|
95 |
occurrence.event.title)
|
|
93 |
appointment['label'] = '%s - %s' % (event.event_type.label, |
|
94 |
event.title) |
|
96 | 95 |
else: |
97 | 96 |
appointment['type'] = 0 |
98 | 97 |
appointment['label'] = '???' |
99 |
appointment['participants'] = occurrence.event.participants.all()
|
|
100 |
appointments_times[start_time]['row'] += 1 |
|
101 |
appointments_times[start_time]['appointments'].append(appointment) |
|
98 |
appointment['participants'] = event.participants.all() |
|
99 |
appointments_times[start_datetime]['row'] += 1
|
|
100 |
appointments_times[start_datetime]['appointments'].append(appointment)
|
|
102 | 101 |
context['appointments_times'] = sorted(appointments_times.items()) |
103 | 102 |
return context |
104 | 103 |
|
105 | 104 |
|
106 | 105 |
class NewAppointmentView(cbv.ReturnToObjectMixin, cbv.ServiceFormMixin, CreateView): |
107 |
model = EventAct |
|
106 |
model = EventWithAct
|
|
108 | 107 |
form_class = NewAppointmentForm |
109 | 108 |
template_name = 'agenda/nouveau-rdv.html' |
110 | 109 |
success_url = '..' |
... | ... | |
119 | 118 |
|
120 | 119 |
|
121 | 120 |
class UpdateAppointmentView(UpdateView): |
122 |
model = EventAct |
|
121 |
model = EventWithAct
|
|
123 | 122 |
form_class = UpdateAppointmentForm |
124 | 123 |
template_name = 'agenda/update-rdv.html' |
125 | 124 |
success_url = '..' |
126 | 125 |
|
127 |
def get_object(self, queryset=None): |
|
128 |
self.occurrence = Occurrence.objects.get(id=self.kwargs['id']) |
|
129 |
if self.occurrence.event.eventact: |
|
130 |
return self.occurrence.event.eventact |
|
131 |
|
|
132 | 126 |
def get_initial(self): |
133 | 127 |
initial = super(UpdateView, self).get_initial() |
134 |
initial['date'] = self.object.date
|
|
135 |
initial['time'] = self.occurrence.start_time.strftime("%H:%M")
|
|
136 |
time = self.occurrence.end_time - self.occurrence.start_time
|
|
128 |
initial['date'] = self.object.start_datetime.strftime("%Y-%m-%d")
|
|
129 |
initial['time'] = self.object.start_datetime.strftime("%H:%M")
|
|
130 |
time = self.object.end_datetime - self.object.start_datetime
|
|
137 | 131 |
if time: |
138 | 132 |
time = time.seconds / 60 |
139 | 133 |
else: |
... | ... | |
144 | 138 |
|
145 | 139 |
def get_form_kwargs(self): |
146 | 140 |
kwargs = super(UpdateAppointmentView, self).get_form_kwargs() |
147 |
kwargs['occurrence'] = self.occurrence |
|
148 | 141 |
kwargs['service'] = self.service |
149 | 142 |
return kwargs |
150 | 143 |
|
... | ... | |
165 | 158 |
initial['room'] = self.request.GET.get('room') |
166 | 159 |
return initial |
167 | 160 |
|
161 |
|
|
168 | 162 |
class UpdateEventView(UpdateView): |
169 | 163 |
model = Event |
170 |
form_class = UpdateEventForm
|
|
164 |
form_class = NewEventForm
|
|
171 | 165 |
template_name = 'agenda/update-event.html' |
172 | 166 |
success_url = '..' |
173 | 167 |
|
174 |
def get_object(self, queryset=None): |
|
175 |
self.occurrence = Occurrence.objects.get(id=self.kwargs['id']) |
|
176 |
return self.occurrence.event |
|
177 |
|
|
178 | 168 |
def get_initial(self): |
179 | 169 |
initial = super(UpdateEventView, self).get_initial() |
180 |
initial['date'] = self.occurrence.start_time.date()
|
|
181 |
initial['time'] = self.occurrence.start_time.strftime("%H:%M")
|
|
182 |
time = self.occurrence.end_time - self.occurrence.start_time
|
|
170 |
initial['date'] = self.object.start_datetime.strftime("%Y-%m-%d")
|
|
171 |
initial['time'] = self.object.start_datetime.strftime("%H:%M")
|
|
172 |
time = self.object.end_datetime - self.object.start_datetime
|
|
183 | 173 |
if time: |
184 | 174 |
time = time.seconds / 60 |
185 | 175 |
else: |
... | ... | |
188 | 178 |
initial['participants'] = self.object.participants.values_list('id', flat=True) |
189 | 179 |
return initial |
190 | 180 |
|
191 |
def get_form_kwargs(self): |
|
192 |
kwargs = super(UpdateEventView, self).get_form_kwargs() |
|
193 |
kwargs['occurrence'] = self.occurrence |
|
194 |
return kwargs |
|
195 |
|
|
196 |
def new_appointment(request): |
|
197 |
pass |
|
198 | 181 |
|
199 | 182 |
class AgendaServiceActValidationView(TemplateView): |
200 |
|
|
201 | 183 |
template_name = 'agenda/act-validation.html' |
202 | 184 |
|
203 | 185 |
def acts_of_the_day(self): |
... | ... | |
299 | 281 |
|
300 | 282 |
|
301 | 283 |
class AgendasTherapeutesView(AgendaHomepageView): |
302 |
|
|
303 | 284 |
template_name = 'agenda/agendas-therapeutes.html' |
304 | 285 |
|
305 | 286 |
def get_context_data(self, **kwargs): |
... | ... | |
312 | 293 |
holidays = Holiday.objects.select_related('worker'). \ |
313 | 294 |
for_period(self.date, self.date). \ |
314 | 295 |
order_by('start_date') |
315 |
occurrences = Occurrence.objects.daily_occurrences(context['date']).order_by('start_time') |
|
296 |
plain_events = Event.objects.for_today(self.date) \ |
|
297 |
.order_by('start_datetime').select_subclasses() |
|
298 |
events = [ e.today_occurence(self.date) for e in plain_events ] |
|
316 | 299 |
|
317 |
occurrences_workers = {}
|
|
300 |
events_workers = {}
|
|
318 | 301 |
time_tables_workers = {} |
319 | 302 |
holidays_workers = {} |
320 | 303 |
context['workers_agenda'] = [] |
321 | 304 |
for worker in context['workers']: |
322 | 305 |
time_tables_worker = [tt for tt in time_tables if tt.worker.id == worker.id] |
323 |
occurrences_worker = [o for o in occurrences if worker.id in o.event.participants.values_list('id', flat=True)]
|
|
306 |
events_worker = [o for o in events if worker.id in o.participants.values_list('id', flat=True)]
|
|
324 | 307 |
holidays_worker = [h for h in holidays if h.worker_id in (None, worker.id)] |
325 |
occurrences_workers[worker.id] = occurrences_worker
|
|
308 |
events_workers[worker.id] = events_worker
|
|
326 | 309 |
time_tables_workers[worker.id] = time_tables_worker |
327 | 310 |
holidays_workers[worker.id] = holidays_worker |
328 | 311 |
context['workers_agenda'].append({'worker': worker, |
329 | 312 |
'appointments': get_daily_appointments(context['date'], worker, self.service, |
330 |
time_tables_worker, occurrences_worker, holidays_worker)})
|
|
313 |
time_tables_worker, events_worker, holidays_worker)})
|
|
331 | 314 |
|
332 | 315 |
for worker_agenda in context.get('workers_agenda', []): |
333 | 316 |
patient_appointments = [x for x in worker_agenda['appointments'] if x.patient_record_id] |
... | ... | |
342 | 325 |
return context |
343 | 326 |
|
344 | 327 |
class JoursNonVerrouillesView(TemplateView): |
345 |
|
|
346 | 328 |
template_name = 'agenda/days-not-locked.html' |
347 | 329 |
|
348 | 330 |
def get_context_data(self, **kwargs): |
349 | 331 |
context = super(JoursNonVerrouillesView, self).get_context_data(**kwargs) |
350 |
acts = EventAct.objects.filter(is_billed=False,
|
|
332 |
acts = Act.objects.filter(is_billed=False, |
|
351 | 333 |
patient__service=self.service).order_by('date') |
352 |
days_not_locked = [] |
|
353 |
for act in acts: |
|
354 |
current_day = datetime.datetime(act.date.year, act.date.month, act.date.day) |
|
355 |
if not current_day in days_not_locked: |
|
356 |
locked = are_all_acts_of_the_day_locked(current_day, self.service) |
|
357 |
if not locked: |
|
358 |
days_not_locked.append(current_day) |
|
359 |
context['days_not_locked'] = days_not_locked |
|
334 |
days = set(acts.values_list('date', flat=True)) |
|
335 |
max_day, min_day = max(days), min(days) |
|
336 |
days &= set(get_days_with_acts_not_locked(min_day, max_day, self.service)) |
|
337 |
context['days_not_locked'] = days |
|
360 | 338 |
return context |
361 | 339 |
|
362 | 340 |
class RessourcesView(TemplateView): |
... | ... | |
366 | 344 |
def get_context_data(self, **kwargs): |
367 | 345 |
context = super(RessourcesView, self).get_context_data(**kwargs) |
368 | 346 |
|
369 |
occurrences = Occurrence.objects.daily_occurrences(context['date']).order_by('start_time') |
|
347 |
plain_events = Event.objects.for_today(self.date) \ |
|
348 |
.order_by('start_datetime').select_subclasses() |
|
349 |
events = [ e.today_occurence(self.date) for e in plain_events ] |
|
370 | 350 |
|
371 | 351 |
context['ressources_types'] = [] |
372 | 352 |
context['ressources_agenda'] = [] |
... | ... | |
376 | 356 |
context['ressources_types'].append(data) |
377 | 357 |
ressources.extend(data['ressources']) |
378 | 358 |
|
379 |
occurrences_ressources = {}
|
|
359 |
events_ressources = {}
|
|
380 | 360 |
for ressource in ressources: |
381 |
occurrences_ressource = [o for o in occurrences if ressource == o.event.room]
|
|
382 |
occurrences_ressources[ressource.id] = occurrences_ressource
|
|
361 |
events_ressource = [e for e in events if ressource == e.room]
|
|
362 |
events_ressources[ressource.id] = events_ressource
|
|
383 | 363 |
context['ressources_agenda'].append({'ressource': ressource, |
384 | 364 |
'appointments': get_daily_usage(context['date'], ressource, |
385 |
self.service, occurrences_ressource)})
|
|
365 |
self.service, events_ressource)})
|
|
386 | 366 |
|
387 | 367 |
return context |
388 | 368 |
|
... | ... | |
401 | 381 |
holidays_worker = Holiday.objects.for_worker_id(worker_id). \ |
402 | 382 |
for_period(self.date, self.date). \ |
403 | 383 |
order_by('start_date') |
404 |
occurrences = Occurrence.objects.daily_occurrences(context['date']).order_by('start_time') |
|
405 |
occurrences_worker = [o for o in occurrences if worker_id in o.event.participants.values_list('id', flat=True)] |
|
384 |
plain_events = Event.objects.for_today(self.date) \ |
|
385 |
.order_by('start_datetime').select_subclasses() |
|
386 |
events = [ e.today_occurence(self.date) for e in plain_events ] |
|
387 |
events_worker = [e for e in events if worker_id in e.participants.values_list('id', flat=True)] |
|
406 | 388 |
|
407 | 389 |
worker = Worker.objects.get(pk=worker_id) |
408 | 390 |
context['worker_agenda'] = {'worker': worker, |
409 | 391 |
'appointments': get_daily_appointments(context['date'], worker, self.service, |
410 |
time_tables_worker, occurrences_worker, holidays_worker)}
|
|
392 |
time_tables_worker, events_worker, holidays_worker)}
|
|
411 | 393 |
return context |
412 | 394 |
|
413 | 395 |
class AjaxWorkerDisponibilityColumnView(TemplateView): |
... | ... | |
425 | 407 |
holidays_worker = Holiday.objects.for_worker_id(worker_id). \ |
426 | 408 |
for_period(self.date, self.date). \ |
427 | 409 |
order_by('start_date') |
428 |
occurrences = Occurrence.objects.daily_occurrences(context['date']).order_by('start_time')
|
|
429 |
occurrences_worker = [o for o in occurrences if worker_id in o.event.participants.values_list('id', flat=True)]
|
|
410 |
events = Event.objects.today_occurences(self.date)
|
|
411 |
events_worker = [e for e in events if worker_id in e.participants.values_list('id', flat=True)]
|
|
430 | 412 |
|
431 | 413 |
worker = Worker.objects.get(pk=worker_id) |
432 | 414 |
time_tables_workers = {worker.id: time_tables_worker} |
433 |
occurrences_workers = {worker.id: occurrences_worker}
|
|
415 |
events_workers = {worker.id: events_worker}
|
|
434 | 416 |
holidays_workers = {worker.id: holidays_worker} |
435 | 417 |
|
436 | 418 |
context['initials'] = worker.get_initials() |
437 | 419 |
context['worker_id'] = worker.id |
438 |
context['disponibility'] = Occurrence.objects.daily_disponibility(context['date'],
|
|
439 |
occurrences_workers, [worker], time_tables_workers, holidays_workers)
|
|
420 |
context['disponibility'] = Event.objects.daily_disponibilities(self.date,
|
|
421 |
events_workers, [worker], time_tables_workers, holidays_workers)
|
|
440 | 422 |
return context |
calebasse/api.py | ||
---|---|---|
1 | 1 |
|
2 | 2 |
from tastypie.authorization import DjangoAuthorization |
3 | 3 |
from tastypie.resources import ModelResource |
4 |
from calebasse.agenda.models import Event, Occurrence
|
|
4 |
from calebasse.agenda.models import Event |
|
5 | 5 |
from calebasse.dossiers.models import PatientRecord, PatientAddress |
6 | 6 |
|
7 | 7 |
|
... | ... | |
11 | 11 |
resource_name = 'event' |
12 | 12 |
authorization = DjangoAuthorization() |
13 | 13 |
|
14 |
class OccurrenceResource(ModelResource): |
|
15 |
class Meta: |
|
16 |
queryset = Occurrence.objects.all() |
|
17 |
resource_name = 'occurrence' |
|
18 |
authorization = DjangoAuthorization() |
|
19 |
|
|
20 | 14 |
class PatientRecordRessource(ModelResource): |
21 | 15 |
class Meta: |
22 | 16 |
queryset = PatientRecord.objects.all() |
... | ... | |
31 | 25 |
|
32 | 26 |
patientaddress_ressource = PatientAddressRessource() |
33 | 27 |
event_resource = EventResource() |
34 |
occurrence_resource = OccurrenceResource() |
|
35 | 28 |
patientrecord_resource = PatientRecordRessource() |
36 | 29 |
|
calebasse/dossiers/models.py | ||
---|---|---|
578 | 578 |
cmpp = Service.objects.get(name='CMPP') |
579 | 579 |
for act in acts: |
580 | 580 |
if act.is_state('VALIDE') and act.is_billable() and \ |
581 |
act.date >= self.get_state().date_selected and \ |
|
581 |
act.date >= self.get_state().date_selected.date() and \
|
|
582 | 582 |
are_all_acts_of_the_day_locked(act.date): |
583 | 583 |
cared, hc = act.is_act_covered_by_diagnostic_healthcare() |
584 | 584 |
if hc: |
calebasse/dossiers/views.py | ||
---|---|---|
15 | 15 |
from calebasse import cbv |
16 | 16 |
from calebasse.doc_templates import make_doc_from_template |
17 | 17 |
from calebasse.dossiers import forms |
18 |
from calebasse.agenda.models import Occurrence |
|
18 |
from calebasse.agenda.models import Event, EventWithAct |
|
19 |
from calebasse.actes.models import Act |
|
19 | 20 |
from calebasse.agenda.appointments import Appointment |
20 | 21 |
from calebasse.dossiers.models import (PatientRecord, PatientContact, |
21 | 22 |
PatientAddress, Status, FileState, create_patient, CmppHealthCareTreatment, |
... | ... | |
27 | 28 |
|
28 | 29 |
def get_next_rdv(patient_record): |
29 | 30 |
next_rdv = {} |
30 |
occurrence = Occurrence.objects.next_appoinment(patient_record)
|
|
31 |
if occurrence:
|
|
32 |
next_rdv['start_datetime'] = occurrence.start_time
|
|
33 |
next_rdv['participants'] = occurrence.event.participants.all()
|
|
34 |
next_rdv['act_type'] = occurrence.event.eventact.act_type
|
|
31 |
event = Event.objects.next_appointment(patient_record)
|
|
32 |
if event:
|
|
33 |
next_rdv['start_datetime'] = event.start_time
|
|
34 |
next_rdv['participants'] = event.participants.all() |
|
35 |
next_rdv['act_type'] = event.eventact.act_type |
|
35 | 36 |
return next_rdv |
36 | 37 |
|
37 | 38 |
def get_last_rdv(patient_record): |
38 | 39 |
last_rdv = {} |
39 |
occurrence = Occurrence.objects.last_appoinment(patient_record)
|
|
40 |
if occurrence:
|
|
41 |
last_rdv['start_datetime'] = occurrence.start_time
|
|
42 |
last_rdv['participants'] = occurrence.event.participants.all()
|
|
43 |
last_rdv['act_type'] = occurrence.event.eventact.act_type
|
|
40 |
event = Event.objects.last_appointment(patient_record)
|
|
41 |
if event:
|
|
42 |
last_rdv['start_datetime'] = event.start_time
|
|
43 |
last_rdv['participants'] = event.participants.all() |
|
44 |
last_rdv['act_type'] = event.eventact.act_type |
|
44 | 45 |
return last_rdv |
45 | 46 |
|
46 | 47 |
class NewPatientRecordView(cbv.FormView, cbv.ServiceViewMixin): |
... | ... | |
254 | 255 |
ctx['service_id'] = self.service.id |
255 | 256 |
ctx['states'] = FileState.objects.filter(patient=self.object).filter(status__services=self.service) |
256 | 257 |
ctx['next_rdvs'] = [] |
257 |
for rdv in Occurrence.objects.next_appoinments(ctx['object']):
|
|
258 |
state = rdv.event.eventact.get_state()
|
|
258 |
for act in Act.objects.next_acts(ctx['object']).select_related():
|
|
259 |
state = act.get_state() |
|
259 | 260 |
if not state.previous_state: |
260 | 261 |
state = None |
261 |
ctx['next_rdvs'].append((rdv, state))
|
|
262 |
ctx['next_rdvs'].append((act.parent_event, state))
|
|
262 | 263 |
ctx['last_rdvs'] = [] |
263 |
for rdv in Occurrence.objects.last_appoinments(ctx['object']):
|
|
264 |
state = rdv.event.eventact.get_state()
|
|
264 |
for act in Act.objects.last_acts(ctx['object']):
|
|
265 |
state = act.get_state() |
|
265 | 266 |
if not state.previous_state: |
266 | 267 |
state = None |
267 |
ctx['last_rdvs'].append((rdv, state))
|
|
268 |
ctx['last_rdvs'].append((act.parent_event, state))
|
|
268 | 269 |
ctx['status'] = [] |
269 | 270 |
if ctx['object'].service.name == "CMPP": |
270 | 271 |
if ctx['object'].last_state.status.type == "ACCUEIL": |
... | ... | |
577 | 578 |
ctx['object'] = PatientRecord.objects.get(id=self.kwargs['patientrecord_id']) |
578 | 579 |
ctx['service_id'] = self.service.id |
579 | 580 |
if self.request.GET.get('event-id'): |
581 |
date = self.request.GET.get('date') |
|
582 |
date = datetime.strptime(date, '%Y-%m-%d').date() |
|
580 | 583 |
appointment = Appointment() |
581 |
occurrence = Occurrence.objects.get(id=self.request.GET.get('event-id')) |
|
582 |
appointment.init_from_occurrence(occurrence, self.service) |
|
584 |
event = Event.objects.get(id=self.request.GET.get('event-id')) |
|
585 |
event = event.today_occurence(date) |
|
586 |
appointment.init_from_event(event, self.service) |
|
583 | 587 |
ctx['appointment'] = appointment |
584 | 588 |
return ctx |
585 | 589 |
|
... | ... | |
632 | 636 |
else: |
633 | 637 |
qs = qs.filter(last_state__status__type__in='') |
634 | 638 |
|
635 |
qs_events = Occurrence.objects.select_related('event') |
|
636 | 639 |
try: |
637 | 640 |
date_actes_start = datetime.strptime(form.data['date_actes_start'], "%d/%m/%Y") |
638 |
qs_events = qs_events.filter(models.Q(start_time__gte=date_actes_start))
|
|
641 |
qs = qs.filter(act_set__date__gte=date_actes_start.date())
|
|
639 | 642 |
except (ValueError, KeyError): |
640 |
date_actes_start = None
|
|
643 |
pass
|
|
641 | 644 |
try: |
642 | 645 |
date_actes_end = datetime.strptime(form.data['date_actes_end'], "%d/%m/%Y") |
643 |
qs_events = qs_events.filter(models.Q(end_time__lte=date_actes_end))
|
|
646 |
qs = qs.filter(act_set__date__lte=date_actes_end.date())
|
|
644 | 647 |
except (ValueError, KeyError): |
645 |
date_actes_end = None |
|
646 |
|
|
647 |
if date_actes_start or date_actes_end: |
|
648 |
qs = qs.filter(id__in=[x.event.eventact.patient.id for x in qs_events]) |
|
649 |
|
|
648 |
pass |
|
650 | 649 |
qs = qs.filter(service=self.service).order_by('last_name') |
651 | 650 |
return qs |
652 | 651 |
|
calebasse/facturation/tests.py | ||
---|---|---|
10 | 10 |
from calebasse.actes.validation import automated_validation, \ |
11 | 11 |
are_all_acts_of_the_day_locked, \ |
12 | 12 |
get_days_with_acts_not_locked |
13 |
from calebasse.actes.models import EventAct |
|
13 |
from calebasse.actes.models import Act |
|
14 |
from calebasse.agenda.models import EventWithAct |
|
14 | 15 |
from calebasse.dossiers.models import create_patient, PatientRecord, \ |
15 | 16 |
SessadHealthCareNotification, CmppHealthCareTreatment, CmppHealthCareDiagnostic |
16 | 17 |
from calebasse.dossiers.models import Status |
... | ... | |
39 | 40 |
service_camsp = Service.objects.get(name='CAMSP') |
40 | 41 |
|
41 | 42 |
patient_a = create_patient('a', 'A', service_camsp, self.creator, date_selected=datetime(2020, 10, 5)) |
42 |
act0 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3], |
|
43 |
act0 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3],
|
|
43 | 44 |
self.act_type, service_camsp, start_datetime=datetime(2020, 10, 6, 10, 15), |
44 | 45 |
end_datetime=datetime(2020, 10, 6, 12, 20)) |
45 | 46 |
status_suivi = Status.objects.filter(services__name='CAMSP').filter(type='SUIVI')[0] |
46 | 47 |
patient_a.set_state(status_suivi, self.creator, date_selected=datetime(2020, 10, 7)) |
47 |
act1 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3], |
|
48 |
act1 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3],
|
|
48 | 49 |
self.act_type, service_camsp, start_datetime=datetime(2020, 10, 7, 10, 15), |
49 | 50 |
end_datetime=datetime(2020, 10, 7, 12, 20)) |
50 |
act2 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3], |
|
51 |
act2 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3],
|
|
51 | 52 |
self.act_type, service_camsp, start_datetime=datetime(2020, 10, 7, 14, 15), |
52 | 53 |
end_datetime=datetime(2020, 10, 7, 16, 20)) |
53 |
act3 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3], |
|
54 |
act3 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3],
|
|
54 | 55 |
self.act_type, service_camsp, start_datetime=datetime(2020, 10, 7, 16, 20), |
55 | 56 |
end_datetime=datetime(2020, 10, 7, 17, 20)) |
56 | 57 |
status_clos = Status.objects.filter(services__name='CAMSP').filter(type='CLOS')[0] |
57 | 58 |
patient_a.set_state(status_clos, self.creator, date_selected=datetime(2020, 10, 8)) |
58 |
act4 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3], |
|
59 |
act4 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3],
|
|
59 | 60 |
self.act_type, service_camsp, start_datetime=datetime(2020, 10, 8, 10, 15), |
60 | 61 |
end_datetime=datetime(2020, 10, 8, 12, 20)) |
61 | 62 |
|
62 | 63 |
patient_b = create_patient('b', 'B', service_camsp, self.creator, date_selected=datetime(2020, 10, 4)) |
63 |
act5 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_b, [self.therapist3], |
|
64 |
act5 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_b, [self.therapist3],
|
|
64 | 65 |
self.act_type, service_camsp, start_datetime=datetime(2020, 10, 4, 10, 15), |
65 | 66 |
end_datetime=datetime(2020, 10, 4, 12, 20)) |
66 |
act6 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_b, [self.therapist3], |
|
67 |
act6 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_b, [self.therapist3],
|
|
67 | 68 |
self.act_type, service_camsp, start_datetime=datetime(2020, 10, 5, 10, 15), |
68 | 69 |
end_datetime=datetime(2020, 10, 5, 12, 20)) |
69 | 70 |
act6.set_state('ABS_EXC', self.creator) |
70 |
act7 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_b, [self.therapist3], |
|
71 |
act7 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_b, [self.therapist3],
|
|
71 | 72 |
self.act_type, service_camsp, start_datetime=datetime(2020, 10, 5, 10, 15), |
72 | 73 |
end_datetime=datetime(2020, 10, 5, 12, 20)) |
73 | 74 |
act7.switch_billable = True |
74 | 75 |
act7.save() |
75 | 76 |
patient_b.set_state(status_suivi, self.creator, date_selected=datetime(2020, 10, 6)) |
76 |
act8 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_b, [self.therapist3], |
|
77 |
act8 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_b, [self.therapist3],
|
|
77 | 78 |
self.act_type, service_camsp, start_datetime=datetime(2020, 10, 7, 10, 15), |
78 | 79 |
end_datetime=datetime(2020, 10, 7, 12, 20)) |
79 |
act9 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_b, [self.therapist3], |
|
80 |
act9 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_b, [self.therapist3],
|
|
80 | 81 |
self.act_type, service_camsp, start_datetime=datetime(2020, 10, 7, 14, 15), |
81 | 82 |
end_datetime=datetime(2020, 10, 7, 16, 20)) |
82 |
act10 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_b, [self.therapist3], |
|
83 |
act10 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_b, [self.therapist3],
|
|
83 | 84 |
self.act_type, service_camsp, start_datetime=datetime(2020, 10, 7, 16, 20), |
84 | 85 |
end_datetime=datetime(2020, 10, 7, 17, 20)) |
85 |
act11 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_b, [self.therapist3], |
|
86 |
act11 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_b, [self.therapist3],
|
|
86 | 87 |
self.act_type, service_camsp, start_datetime=datetime(2020, 10, 8, 10, 15), |
87 | 88 |
end_datetime=datetime(2020, 10, 8, 12, 20)) |
88 | 89 |
patient_b.set_state(status_clos, self.creator, date_selected=datetime(2020, 10, 9)) |
... | ... | |
149 | 150 |
service_sessad = Service.objects.get(name='SESSAD DYS') |
150 | 151 |
|
151 | 152 |
patient_a = create_patient('a', 'A', service_sessad, self.creator, date_selected=datetime(2020, 10, 5)) |
152 |
act0 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3], |
|
153 |
act0 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3],
|
|
153 | 154 |
self.act_type, service_sessad, start_datetime=datetime(2020, 10, 6, 10, 15), |
154 | 155 |
end_datetime=datetime(2020, 10, 6, 12, 20)) |
155 | 156 |
status_traitement = Status.objects.filter(services__name='SESSAD DYS').filter(type='TRAITEMENT')[0] |
156 | 157 |
patient_a.set_state(status_traitement, self.creator, date_selected=datetime(2020, 10, 7)) |
157 |
act1 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3], |
|
158 |
act1 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3],
|
|
158 | 159 |
self.act_type, service_sessad, start_datetime=datetime(2020, 10, 7, 10, 15), |
159 | 160 |
end_datetime=datetime(2020, 10, 7, 12, 20)) |
160 |
act2 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3], |
|
161 |
act2 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3],
|
|
161 | 162 |
self.act_type, service_sessad, start_datetime=datetime(2020, 10, 7, 14, 15), |
162 | 163 |
end_datetime=datetime(2020, 10, 7, 16, 20)) |
163 |
act3 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3], |
|
164 |
act3 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3],
|
|
164 | 165 |
self.act_type, service_sessad, start_datetime=datetime(2020, 10, 7, 16, 20), |
165 | 166 |
end_datetime=datetime(2020, 10, 7, 17, 20)) |
166 | 167 |
status_clos = Status.objects.filter(services__name='SESSAD DYS').filter(type='CLOS')[0] |
167 | 168 |
patient_a.set_state(status_clos, self.creator, date_selected=datetime(2020, 10, 8)) |
168 |
act4 = EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3], |
|
169 |
act4 = EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3],
|
|
169 | 170 |
self.act_type, service_sessad, start_datetime=datetime(2020, 10, 8, 10, 15), |
170 | 171 |
end_datetime=datetime(2020, 10, 8, 12, 20)) |
171 | 172 |
|
... | ... | |
196 | 197 |
service_cmpp = Service.objects.get(name='CMPP') |
197 | 198 |
|
198 | 199 |
patient_a = create_patient('a', 'A', service_cmpp, self.creator, date_selected=datetime(2020, 10, 1)) |
199 |
acts = [ EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3], |
|
200 |
acts = [ EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3],
|
|
200 | 201 |
self.act_type, service_cmpp, start_datetime=datetime(2020, 10, i, 10, 15), |
201 | 202 |
end_datetime=datetime(2020, 10, i, 12, 20)) for i in range (1, 32)] |
202 | 203 |
status_accueil = Status.objects.filter(services__name='CMPP').filter(type='ACCUEIL')[0] |
... | ... | |
236 | 237 |
patient_a = PatientRecord.objects.get(id=patient_a.id) |
237 | 238 |
self.assertEqual(patient_a.get_state().status, status_traitement) |
238 | 239 |
|
239 |
acts_2 = [ EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3], |
|
240 |
acts_2 = [ EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient_a, [self.therapist3],
|
|
240 | 241 |
self.act_type, service_cmpp, start_datetime=datetime(2020, 11, i, 10, 15), |
241 | 242 |
end_datetime=datetime(2020, 11, i, 12, 20)) for i in range (1, 31)] |
242 | 243 |
for i in range(1, 31): |
... | ... | |
281 | 282 |
patients = [] |
282 | 283 |
for j in range(2): |
283 | 284 |
patients.append(create_patient(str(j), str(j), service_cmpp, self.creator, date_selected=datetime(2012, 10, 1))) |
284 |
acts = [ EventAct.objects.create_patient_appointment(self.creator, 'RDV', patients[j], [self.therapist3], |
|
285 |
acts = [ EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patients[j], [self.therapist3],
|
|
285 | 286 |
self.act_type, service_cmpp, start_datetime=datetime(2012, 10, i, 10, 15), |
286 | 287 |
end_datetime=datetime(2012, 10, i, 12, 20)) for i in range (1, 32)] |
287 |
acts_2 = [ EventAct.objects.create_patient_appointment(self.creator, 'RDV', patients[j], [self.therapist3], |
|
288 |
acts_2 = [ EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patients[j], [self.therapist3],
|
|
288 | 289 |
self.act_type, service_cmpp, start_datetime=datetime(2012, 11, i, 10, 15), |
289 | 290 |
end_datetime=datetime(2012, 11, i, 12, 20)) for i in range (1, 31)] |
290 | 291 |
hct = CmppHealthCareTreatment(patient=patients[j], start_date=datetime(2012, 10, 7), author=self.creator) |
... | ... | |
376 | 377 |
|
377 | 378 |
|
378 | 379 |
patient = create_patient('A', 'a', service_cmpp, self.creator, date_selected=datetime(2012, 10, 1)) |
379 |
acts = [ EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3], |
|
380 |
acts = [ EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3],
|
|
380 | 381 |
self.act_type, service_cmpp, start_datetime=datetime(2012, 10, i, 10, 15), |
381 | 382 |
end_datetime=datetime(2012, 10, i, 12, 20)) for i in range (1, 32)] |
382 | 383 |
hct = CmppHealthCareTreatment(patient=patient, start_date=datetime(2011, 11, 7), author=self.creator) |
... | ... | |
407 | 408 |
self.assertEqual(len_patient_with_lost_acts, 0) |
408 | 409 |
|
409 | 410 |
|
410 |
acts_2 = [ EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3], |
|
411 |
acts_2 = [ EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3],
|
|
411 | 412 |
self.act_type, service_cmpp, start_datetime=datetime(2012, 11, i, 10, 15), |
412 | 413 |
end_datetime=datetime(2012, 11, i, 12, 20)) for i in range (1, 31)] |
413 | 414 |
|
... | ... | |
447 | 448 |
|
448 | 449 |
self.assertEqual(patient.last_state.status.type, "ACCUEIL") |
449 | 450 |
|
450 |
EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3], |
|
451 |
EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3],
|
|
451 | 452 |
self.act_type, service_cmpp, start_datetime=datetime(2012, 10, 1, 10, 15), |
452 | 453 |
end_datetime=datetime(2012, 10, 1, 12, 20)) |
453 | 454 |
|
... | ... | |
457 | 458 |
self.assertEqual(patient.last_state.status.type, "DIAGNOSTIC") |
458 | 459 |
self.assertEqual(patient.last_state.date_selected, datetime(2012, 10, 1, 0, 0)) |
459 | 460 |
|
460 |
acts = [ EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3], |
|
461 |
acts = [ EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3],
|
|
461 | 462 |
self.act_type, service_cmpp, start_datetime=datetime(2012, 10, i, 10, 15), |
462 | 463 |
end_datetime=datetime(2012, 10, i, 12, 20)) for i in range (2, 32)] |
463 | 464 |
|
... | ... | |
472 | 473 |
|
473 | 474 |
self.assertEqual(patient.last_state.status.type, "ACCUEIL") |
474 | 475 |
|
475 |
EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3], |
|
476 |
EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3],
|
|
476 | 477 |
self.act_type, service_cmpp, start_datetime=datetime(2012, 10, 1, 10, 15), |
477 | 478 |
end_datetime=datetime(2012, 10, 1, 12, 20)) |
478 | 479 |
|
... | ... | |
489 | 490 |
self.assertEqual(patient.last_state.status.type, "CLOS") |
490 | 491 |
self.assertEqual(patient.last_state.date_selected, datetime(2012, 12, 9, 0, 0)) |
491 | 492 |
|
492 |
acts = [ EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3], |
|
493 |
acts = [ EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3],
|
|
493 | 494 |
self.act_type, service_cmpp, start_datetime=datetime(2012, 10, i, 10, 15), |
494 | 495 |
end_datetime=datetime(2012, 10, i, 12, 20)) for i in range (2, 32)] |
495 | 496 |
|
... | ... | |
506 | 507 |
price_o = add_price(120, date(2012, 10, 1)) |
507 | 508 |
|
508 | 509 |
patient = create_patient('A', 'a', service_cmpp, self.creator, date_selected=datetime(2012, 10, 1)) |
509 |
acts = [ EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3], |
|
510 |
acts = [ EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3],
|
|
510 | 511 |
self.act_type, service_cmpp, start_datetime=datetime(2012, 10, i, 10, 15), |
511 | 512 |
end_datetime=datetime(2012, 10, i, 12, 20)) for i in range (1, 4)] |
512 | 513 |
|
... | ... | |
545 | 546 |
|
546 | 547 |
hcd.set_act_number(5) |
547 | 548 |
|
548 |
acts = [ EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3], |
|
549 |
acts = [ EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3],
|
|
549 | 550 |
self.act_type, service_cmpp, start_datetime=datetime(2012, 10, i, 10, 15), |
550 | 551 |
end_datetime=datetime(2012, 10, i, 12, 20)) for i in range (4, 32)] |
551 | 552 |
|
... | ... | |
601 | 602 |
|
602 | 603 |
hct.set_act_number(28) |
603 | 604 |
|
604 |
acts = [ EventAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3], |
|
605 |
acts = [ EventWithAct.objects.create_patient_appointment(self.creator, 'RDV', patient, [self.therapist3],
|
|
605 | 606 |
self.act_type, service_cmpp, start_datetime=datetime(2012, 11, i, 10, 15), |
606 | 607 |
end_datetime=datetime(2012, 11, i, 12, 20)) for i in range (1, 4)] |
607 | 608 |
|
calebasse/fixtures/tests/test_actes.json | ||
---|---|---|
2 | 2 |
{ |
3 | 3 |
"fields": { |
4 | 4 |
"act_type": 97, |
5 |
"date": "2012-10-30T12:00:00",
|
|
5 |
"date": "2012-10-30", |
|
6 | 6 |
"patient": 8, |
7 | 7 |
"transport_company": null, |
8 | 8 |
"transport_type": null, |
9 |
"validation_locked": false |
|
9 |
"validation_locked": false, |
|
10 |
"doctors": [ |
|
11 |
5 |
|
12 |
], |
|
13 |
"parent_event": 1 |
|
10 | 14 |
}, |
11 | 15 |
"model": "actes.act", |
12 | 16 |
"pk": 1 |
... | ... | |
14 | 18 |
{ |
15 | 19 |
"fields": { |
16 | 20 |
"act_type": 10, |
17 |
"date": "2012-10-30T00:00:00",
|
|
21 |
"date": "2012-10-30", |
|
18 | 22 |
"patient": 9, |
19 | 23 |
"transport_company": null, |
20 | 24 |
"transport_type": null, |
21 |
"validation_locked": false |
|
22 |
}, |
|
23 |
"model": "actes.act", |
|
24 |
"pk": 2 |
|
25 |
}, |
|
26 |
{ |
|
27 |
"fields": { |
|
28 |
"attendance": "absent", |
|
29 |
"convocation_sent": false, |
|
30 |
"event_ptr": 1, |
|
31 |
"participants": [ |
|
25 |
"validation_locked": false, |
|
26 |
"doctors": [ |
|
32 | 27 |
5 |
33 | 28 |
], |
34 |
"services": [ |
|
35 |
1 |
|
36 |
] |
|
29 |
"parent_event": 2 |
|
37 | 30 |
}, |
38 |
"model": "actes.eventact", |
|
39 |
"pk": 1 |
|
40 |
}, |
|
41 |
{ |
|
42 |
"fields": { |
|
43 |
"attendance": "absent", |
|
44 |
"convocation_sent": false, |
|
45 |
"event_ptr": 2, |
|
46 |
"participants": [ |
|
47 |
5 |
|
48 |
], |
|
49 |
"services": [ |
|
50 |
1 |
|
51 |
] |
|
52 |
}, |
|
53 |
"model": "actes.eventact", |
|
31 |
"model": "actes.act", |
|
54 | 32 |
"pk": 2 |
55 | 33 |
}, |
56 | 34 |
{ |
calebasse/fixtures/tests/test_agenda.json | ||
---|---|---|
105 | 105 |
1, |
106 | 106 |
2 |
107 | 107 |
], |
108 |
"room": 2 |
|
108 |
"room": 2, |
|
109 |
"create_date": "2012-10-20T11:30:00", |
|
110 |
"start_datetime": "2012-10-30T11:30:00", |
|
111 |
"end_datetime": "2012-10-30T12:00:00" |
|
109 | 112 |
} |
110 | 113 |
}, |
111 | 114 |
{ |
... | ... | |
121 | 124 |
"services": [ |
122 | 125 |
1 |
123 | 126 |
], |
124 |
"room": 1 |
|
127 |
"room": 1, |
|
128 |
"create_date": "2012-10-20T11:30:00", |
|
129 |
"start_datetime": "2012-10-30T10:45:00", |
|
130 |
"end_datetime": "2012-10-30T11:30:00" |
|
125 | 131 |
} |
126 | 132 |
}, |
127 | 133 |
{ |
... | ... | |
137 | 143 |
"services": [ |
138 | 144 |
1 |
139 | 145 |
], |
140 |
"room": 2 |
|
146 |
"room": 2, |
|
147 |
"create_date": "2012-10-20T11:30:00", |
|
148 |
"start_datetime": "2012-10-30T10:00:00", |
|
149 |
"end_datetime": "2012-10-30T10:45:00" |
|
141 | 150 |
} |
142 | 151 |
}, |
143 | 152 |
{ |
144 |
"pk": 1, |
|
145 |
"model": "agenda.occurrence", |
|
146 |
"fields": { |
|
147 |
"notes": [], |
|
148 |
"start_time": "2012-10-30T10:00:00", |
|
149 |
"end_time": "2012-10-30T10:45:00", |
|
150 |
"event": 1 |
|
151 |
} |
|
153 |
"fields": { |
|
154 |
"act_type": 97, |
|
155 |
"patient": 10, |
|
156 |
"event_ptr": 1 |
|
157 |
}, |
|
158 |
"model": "agenda.eventwithact", |
|
159 |
"pk": 1 |
|
152 | 160 |
}, |
153 | 161 |
{ |
154 |
"pk": 2, |
|
155 |
"model": "agenda.occurrence", |
|
156 |
"fields": { |
|
157 |
"notes": [], |
|
158 |
"start_time": "2012-10-30T10:45:00", |
|
159 |
"end_time": "2012-10-30T11:30:00", |
|
160 |
"event": 2 |
|
161 |
} |
|
162 |
}, |
|
163 |
{ |
|
164 |
"pk": 3, |
|
165 |
"model": "agenda.occurrence", |
|
166 |
"fields": { |
|
167 |
"notes": [], |
|
168 |
"start_time": "2012-10-30T11:30:00", |
|
169 |
"end_time": "2012-10-30T12:00:00", |
|
170 |
"event": 3 |
|
171 |
} |
|
162 |
"fields": { |
|
163 |
"act_type": 10, |
|
164 |
"patient": 9, |
|
165 |
"event_ptr": 2 |
|
166 |
}, |
|
167 |
"model": "agenda.eventwithact", |
|
168 |
"pk": 2 |
|
172 | 169 |
} |
173 | 170 |
] |
calebasse/static/js/calebasse.agenda.js | ||
---|---|---|
26 | 26 |
if (r == true) |
27 | 27 |
{ |
28 | 28 |
$.ajax({ |
29 |
url: '/api/occurrence/' + $(this).data('occurrence-id') + '/',
|
|
29 |
url: '/api/event/' + $(this).data('event-id') + '/',
|
|
30 | 30 |
type: 'DELETE', |
31 | 31 |
success: function(data) { |
32 | 32 |
window.location.reload(true); |
... | ... | |
45 | 45 |
event_dialog(new_appointment_url, 'Nouveau rendez-vous', '850px', 'Ajouter'); |
46 | 46 |
}); |
47 | 47 |
$(base).find('.edit-appointment').click(function() { |
48 |
event_dialog("update-rdv/" + $(this).data('occurrence-id') , 'Modifier rendez-vous', '850px', 'Modifier');
|
|
48 |
event_dialog("update-rdv/" + $(this).data('event-id') , 'Modifier rendez-vous', '850px', 'Modifier');
|
|
49 | 49 |
return false; |
50 | 50 |
}); |
51 | 51 |
$(base).find('.newevent').click(function() { |
... | ... | |
56 | 56 |
event_dialog($(this).data('url') + "?" + qs, 'Nouvel événement', '850px', 'Ajouter'); |
57 | 57 |
}); |
58 | 58 |
$(base).find('.edit-event').click(function() { |
59 |
event_dialog("update-event/" + $(this).data('occurrence-id') , 'Modifier un événement', '850px', 'Modifier');
|
|
59 |
event_dialog("update-event/" + $(this).data('event-id') , 'Modifier un événement', '850px', 'Modifier');
|
|
60 | 60 |
return false; |
61 | 61 |
}); |
62 | 62 |
$(base).find('#print-button').click(function() { window.print(); }); |
63 | 63 |
|
64 | 64 |
$('.generate-mail-btn', base).click(function() { |
65 |
var url = '../../dossiers/' + $(this).data('dossier-id') + '/generate?event-id=' + $(this).data('occurence-id'); |
|
65 |
var url = '../../dossiers/' + $(this).data('dossier-id') + '/generate?event-id=' + $(this).data('occurence-id' + '&date=' + $(this).data('date'));
|
|
66 | 66 |
$('#ajax-dlg').load(url, |
67 | 67 |
function () { |
68 | 68 |
$(this).dialog({title: 'Générer un courrier', width: '500px', |
calebasse/urls.py | ||
---|---|---|
5 | 5 |
|
6 | 6 |
from urls_utils import decorated_includes |
7 | 7 |
|
8 |
from calebasse.api import (event_resource, occurrence_resource,
|
|
8 |
from calebasse.api import (event_resource, |
|
9 | 9 |
patientrecord_resource, patientaddress_ressource) |
10 | 10 |
|
11 | 11 |
admin.autodiscover() |
... | ... | |
34 | 34 |
url(r'^accounts/', include('django.contrib.auth.urls')), |
35 | 35 |
url(r'^api/', |
36 | 36 |
decorated_includes(login_required, include(event_resource.urls))), |
37 |
url(r'^api/', |
|
38 |
decorated_includes(login_required, include(occurrence_resource.urls)), |
|
39 |
), |
|
40 | 37 |
url(r'^api/', |
41 | 38 |
decorated_includes(login_required, include(patientrecord_resource.urls)), |
42 | 39 |
), |
Also available in: Unified diff
agenda/actes/dossiers: move Occurence fields into Event, add recurring events support