agenda.patch
calebasse/agenda/appointments.py | ||
---|---|---|
85 | 85 |
self.patient_record_paper_id = event.patient.paper_id |
86 | 86 |
self.act_type = event.act_type.name |
87 | 87 |
self.is_billed = event.act.is_billed |
88 |
self.already_billed = event.act.already_billed |
|
88 | 89 |
state = event.get_state() |
89 | 90 |
state_name = state.state_name if state else 'NON_VALIDE' |
90 | 91 |
display_name = VALIDATION_STATES[state_name] |
calebasse/agenda/forms.py | ||
---|---|---|
8 | 8 |
from ..dossiers.models import PatientRecord |
9 | 9 |
from ..personnes.models import Worker |
10 |
from ..actes.models import Act |
|
10 | 11 |
from ..ressources.models import ActType |
11 | 12 |
from ..middleware.request import get_request |
... | ... | |
154 | 155 |
def clean(self): |
155 | 156 |
cleaned_data = super(UpdatePeriodicAppointmentForm, self).clean() |
156 |
acts = self.instance.act_set.filter(is_billed=True).order_by('-date') |
|
157 |
if acts and cleaned_data.get('recurrence_end_date'): |
|
158 |
recurrence_end_date = cleaned_data['recurrence_end_date'] |
|
159 |
if recurrence_end_date < acts[0].date: |
|
157 |
start_datetime = cleaned_data.get('start_datetime') |
|
158 |
if start_datetime: |
|
159 |
acts = Act.objects.filter( |
|
160 |
Q(parent_event=self.instance, |
|
161 |
already_billed=True, date__lt=start_datetime) | \ |
|
162 |
Q(parent_event__exception_to=self.instance, |
|
163 |
already_billed=True, date__lt=start_datetime)) |
|
164 |
if acts: |
|
165 |
self._errors['start_datetime'] = self.error_class([ |
|
166 |
u"La date de début doit être antérieure au premier acte déja facturé de la récurrence"]) |
|
167 |
recurrence_end_date = cleaned_data.get('recurrence_end_date') |
|
168 |
if recurrence_end_date: |
|
169 |
acts = Act.objects.filter( |
|
170 |
Q(parent_event=self.instance, |
|
171 |
already_billed=True, date__gt=recurrence_end_date) | \ |
|
172 |
Q(parent_event__exception_to=self.instance, |
|
173 |
already_billed=True, date__gt=recurrence_end_date)) |
|
174 |
if acts: |
|
160 | 175 |
self._errors['recurrence_end_date'] = self.error_class([ |
161 |
u"La date doit être supérieur au dernier acte facturé de la récurrence"])
|
|
176 |
u"La date de fin doit être postérieure au dernier acte déja facturé de la récurrence"])
|
|
162 | 177 |
return cleaned_data |
163 | 178 |
class DisablePatientAppointmentForm(UpdateAppointmentForm): |
... | ... | |
279 | 294 |
cleaned_data = super(PeriodicEventsSearchForm, self).clean() |
280 | 295 |
if cleaned_data.get('start_date') and cleaned_data.get('end_date'): |
281 | 296 |
if cleaned_data['start_date'] > cleaned_data['end_date']: |
282 |
raise forms.ValidationError(u'La date de début doit être supérieure à la date de fin')
|
|
297 |
raise forms.ValidationError(u'La date de début doit être antérieure à la date de fin')
|
|
283 | 298 |
return cleaned_data |
calebasse/agenda/models.py | ||
---|---|---|
207 | 207 |
'''Distance between start and end of the event''' |
208 | 208 |
return self.end_datetime - self.start_datetime |
209 |
@property |
|
210 |
def time(self): |
|
211 |
return self.start_datetime.time() |
|
212 | ||
213 |
@property |
|
214 |
def date(self): |
|
215 |
return self.start_datetime.date() |
|
216 | ||
217 |
@property |
|
218 |
def duration(self): |
|
219 |
if self.timedelta(): |
|
220 |
return self.timedelta().seconds / 60 |
|
221 |
return 0 |
|
222 | ||
209 | 223 |
def match_date(self, date): |
210 | 224 |
if self.is_recurring(): |
211 | 225 |
# consider exceptions |
... | ... | |
360 | 374 |
assert self.start_datetime is not None |
361 | 375 |
self.sanitize() # init periodicity fields |
362 | 376 |
super(Event, self).save(*args, **kwargs) |
377 |
self.events_cleaning() |
|
363 | 378 |
self.acts_cleaning() |
364 | 379 |
def delete(self, *args, **kwargs): |
365 |
self.canceled = True |
|
366 |
# save will clean acts |
|
367 |
self.save(*args, **kwargs) |
|
380 |
if not self.one_act_already_billed(): |
|
381 |
for exception in self.exceptions.all(): |
|
382 |
exception.delete() |
|
383 |
self.canceled = True |
|
384 |
if hasattr(self, 'eventwithact'): |
|
385 |
# Needed |
|
386 |
self.eventwithact.canceled = True |
|
387 |
# save will clean acts |
|
388 |
self.save(*args, **kwargs) |
|
389 | ||
390 |
def one_act_already_billed(self): |
|
391 |
''' |
|
392 |
Return True if at least one act of the present event or an act |
|
393 |
of one of its exceptions is already billed. |
|
394 |
''' |
|
395 |
from ..actes.models import Act |
|
396 |
acts = Act.objects.filter( |
|
397 |
models.Q(parent_event=self, |
|
398 |
already_billed=True) | \ |
|
399 |
models.Q(parent_event__exception_to=self, |
|
400 |
already_billed=True)) |
|
401 |
if acts: |
|
402 |
return True |
|
403 |
return False |
|
404 | ||
405 |
def one_act_is_billed(self): |
|
406 |
''' |
|
407 |
Return True if at least one act of the present event or an act |
|
408 |
of one of its exceptions is billed. |
|
409 |
''' |
|
410 |
from ..actes.models import Act |
|
411 |
acts = Act.objects.filter( |
|
412 |
models.Q(parent_event=self, is_billed=True) | \ |
|
413 |
models.Q(parent_event__exception_to=self, is_billed=True)) |
|
414 |
if acts: |
|
415 |
return True |
|
416 |
return False |
|
417 | ||
418 |
def events_cleaning(self): |
|
419 |
""" |
|
420 |
Delete exceptions out of bounds if not with an associated act |
|
421 |
already billed. |
|
422 |
""" |
|
423 |
events = None |
|
424 |
if self.recurrence_end_date: |
|
425 |
events = Event.objects.filter( |
|
426 |
models.Q(exception_to=self, |
|
427 |
exception_date__lt=self.start_datetime.date()) | \ |
|
428 |
models.Q(exception_to=self, |
|
429 |
exception_date__gt=self.recurrence_end_date)) |
|
430 |
else: |
|
431 |
events = Event.objects.filter(exception_to=self, |
|
432 |
exception_date__lt=self.start_datetime.date()) |
|
433 |
for event in events: |
|
434 |
if hasattr(event, 'eventwithact'): |
|
435 |
if not event.eventwithact.act.already_billed: |
|
436 |
event.delete() |
|
437 |
else: |
|
438 |
event.delete() |
|
368 | 439 |
def acts_cleaning(self): |
369 | 440 |
# list of occurences may have changed |
... | ... | |
382 | 453 |
if acts: |
383 | 454 |
eventwithact = self.eventwithact |
384 | 455 |
for act in acts: |
385 |
if act.is_billed: |
|
386 |
pass |
|
387 | 456 |
occurrence = eventwithact.today_occurrence(act.date) |
388 | 457 |
if occurrence: |
389 | 458 |
occurrence.update_act(act) |
390 | 459 |
else: |
391 |
act.delete() |
|
460 |
if not act.already_billed: |
|
461 |
act.delete() |
|
392 | 462 |
def to_interval(self): |
393 | 463 |
return Interval(self.start_datetime, self.end_datetime) |
... | ... | |
538 | 608 |
act.save() |
539 | 609 |
def init_act(self, act): |
540 |
delta = self.timedelta() |
|
541 |
duration = delta.seconds // 60 |
|
542 |
act._duration = duration |
|
543 |
act.act_type = self.act_type |
|
544 |
act.patient = self.patient |
|
610 |
if not act.is_billed: |
|
611 |
delta = self.timedelta() |
|
612 |
duration = delta.seconds // 60 |
|
613 |
act._duration = duration |
|
614 |
act.act_type = self.act_type |
|
615 |
act.patient = self.patient |
|
616 |
act.date = self.start_datetime.date() |
|
617 |
act.time = self.start_datetime.time() |
|
545 | 618 |
act.parent_event = self |
546 |
act.date = self.start_datetime.date() |
|
547 |
act.time = self.start_datetime.time() |
|
548 | 619 |
def save(self, *args, **kwargs): |
549 | 620 |
'''Force event_type to be patient meeting.''' |
calebasse/agenda/templates/agenda/ajax-worker-tab.html | ||
---|---|---|
58 | 58 |
{% else %} |
59 | 59 |
<button title="Éditer un événement" class="edit-event icon-edit" data-event-id="{{ appointment.event_id }}"> |
60 | 60 |
{% endif %} |
61 |
{% if not appointment.is_billed %}
|
|
61 |
{% if not appointment.already_billed %}
|
|
62 | 62 |
<button class="remove-appointment icon-remove-sign" title="Supprimer un rendez-vous" data-url="{% url 'delete-occurrence' service=service date=date pk=appointment.event_id %}" data-rdv="{{ appointment.title }}"></button> |
63 | 63 |
{% endif %} |
64 | 64 |
{% endif %} |
calebasse/agenda/templates/agenda/appointment.html | ||
---|---|---|
3 | 3 |
{{ form.non_field_errors }} |
4 | 4 |
{{ form.start_datetime }} |
5 | 5 |
{{ form.start_datetime.errors }} |
6 |
{% if object.is_recurring and object.one_act_is_billed %}<p><em>Le rendez-vous périodique a un acte qui est facturé ce qui empêche de le modifier à l'exception de la description, de la ressource et des dates de début et de fin.</em></p>{% endif %} |
|
7 |
{% if object.is_recurring and object.one_act_already_billed %}<p><em>Le rendez-vous périodique a un acte qui a déjà été facturé ce qui empêche de le supprimer.</em></p>{% endif %} |
|
6 | 8 |
<table id="new-appointment-table"> |
7 | 9 |
<tr> |
8 | 10 |
<td {% if form.time.field.required %}class="required"{% endif %}> |
9 | 11 |
<p> |
10 | 12 |
{{ form.time.label_tag }} |
13 |
{% if object.is_recurring and object.one_act_is_billed %} |
|
14 |
{{ object.time }} |
|
15 |
{{ form.time.as_hidden }} |
|
16 |
{% else %} |
|
11 | 17 |
{{ form.time }} |
18 |
{% endif %} |
|
12 | 19 |
{{ form.time.errors }} |
13 | 20 |
</p> |
14 | 21 |
</td> |
15 | 22 |
<td {% if form.duration.field.required %}class="required"{% endif %}> |
16 | 23 |
<p> |
17 | 24 |
{{ form.duration.label_tag }} |
18 |
{{ form.duration|add_class:"mousewheel"|attr:"data-mousewheel-increment:5" }} |
|
25 |
{% if object.is_recurring and object.one_act_is_billed %} |
|
26 |
{{ object.duration }} |
|
27 |
{{ form.duration.as_hidden }} |
|
28 |
{% else %} |
|
29 |
{{ form.duration }} |
|
30 |
{% endif %} |
|
19 | 31 |
{{ form.duration.errors }} |
20 |
<div> |
|
21 |
{{ form.duration.help_text }} |
|
22 |
</div> |
|
23 | 32 |
</p> |
24 | 33 |
</td> |
25 | 34 |
<td {% if form.date.field.required %}class="required"{% endif %}> |
... | ... | |
43 | 52 |
<td {% if form.participants.field.required %}class="required"{% endif %}> |
44 | 53 |
<h4>{{ form.participants.label_tag }}</h4> |
45 | 54 |
<div id="intervenants"> |
55 |
{% if object.is_recurring and object.one_act_is_billed %} |
|
56 |
<ul>{% for p in object.participants.all %}<li>{{ p }}</li>{% endfor %}</ul> |
|
57 |
<input id="id_participants" name="participants" value="|{% for p in object.participants.all %}{{ p.id }}|{% endfor %}" type="hidden"/> |
|
58 |
{% else %} |
|
46 | 59 |
{{ form.participants }} |
60 |
{% endif %} |
|
47 | 61 |
{{ form.participants.errors }} |
48 | 62 |
</div> |
49 | 63 |
</td> |
50 | 64 |
<td {% if form.patient.field.required %}class="required"{% endif %}> |
51 | 65 |
<h4>{{ form.patient.label_tag }}</h4> |
52 | 66 |
<div id="patient"> |
53 |
{% if object.exception_to and not object.exception_to.canceled %}
|
|
67 |
{% if object.is_recurring or object.exception_to or object.act.already_billed %}
|
|
54 | 68 |
{{ object.patient }} |
69 |
{{ form.patient.as_hidden }} |
|
55 | 70 |
{% else %} |
56 | 71 |
{{ form.patient }} |
57 | 72 |
{{ form.patient.errors }} |
... | ... | |
60 | 75 |
</td> |
61 | 76 |
<td {% if form.act_type.field.required %}class="required"{% endif %}> |
62 | 77 |
<h4>{{ form.act_type.label_tag }}</h4> |
78 |
{% if object.is_recurring and object.one_act_is_billed %} |
|
79 |
{{ object.act_type }} |
|
80 |
{{ form.act_type.as_hidden }} |
|
81 |
{% else %} |
|
63 | 82 |
{{ form.act_type }} |
83 |
{% endif %} |
|
64 | 84 |
{{ form.act_type.errors }} |
65 | 85 |
</td> |
66 | 86 |
</tr> |
... | ... | |
79 | 99 |
<hr/> |
80 | 100 |
{% if object.id != object.exception_to.id %} |
81 | 101 |
<p><em>Attention: cet objet est une exception à un rendez-vous périodique; si |
82 |
vous modifiez ou supprimiez ce rendez-vous périodique, l'exception n'en serait pas
|
|
102 |
vous modifiez ou supprimez le rendez-vous périodique, l'exception n'en sera pas
|
|
83 | 103 |
affectée.</em></p> |
84 | 104 |
{% endif %} |
85 |
<div>Occurence du {{object.exception_date}} d'un rendez-vous périodique |
|
86 |
{% if object.exception_to.canceled %}<em>supprimée</em> et initialement prévue{% endif %} |
|
87 |
{{ object.exception_to.recurrence_description|lower }}</div> |
|
105 | ||
106 |
<p>Occurence du {{object.exception_date}} d'un rendez-vous périodique |
|
107 |
{% if object.exception_to.canceled %}<em>supprimé</em> et initialement prévu{% endif %} |
|
108 |
{{ object.exception_to.recurrence_description|lower }}</p> |
|
109 | ||
88 | 110 |
{% if not object.exception_to.canceled %} |
89 |
<button type="button" data-delete-url="{% url 'delete-event' service=service date=date pk=object.exception_to.pk %}" data-id="{{ object.exception_to.id }}" class="update-periodic-rdv">Éditer le rendez-vous périodique</button>
|
|
111 |
<p><button type="button" data-delete-url="{% url 'delete-event' service=service date=date pk=object.exception_to.pk %}" data-id="{{ object.exception_to.id }}" data-one_act_already_billed="{{ object.exception_to.one_act_already_billed }}" class="update-periodic-rdv">Éditer le rendez-vous périodique</button></p>
|
|
90 | 112 |
{% endif %} |
113 | ||
91 | 114 |
{% endif %} |
calebasse/agenda/templates/agenda/periodicity.html | ||
---|---|---|
4 | 4 |
<td {% if form.recurrence_periodicity.field.required %}class="required"{% endif %}> |
5 | 5 |
<p> |
6 | 6 |
{{ form.recurrence_periodicity.label_tag }} |
7 |
{% if object.one_act_already_billed %} |
|
8 |
{{ object.recurrence_description }} |
|
9 |
{{ form.recurrence_periodicity.as_hidden }} |
|
10 |
{% else %} |
|
7 | 11 |
{{ form.recurrence_periodicity }} |
8 | 12 |
{{ form.recurrence_periodicity.errors }} |
13 |
{% endif %} |
|
9 | 14 |
</p> |
10 | 15 |
</td> |
11 | 16 |
<td {% if form.recurrence_end_date.field.required %}class="required"{% endif %}> |
calebasse/agenda/views.py | ||
---|---|---|
274 | 276 |
form_class = UpdatePeriodicEventForm |
275 | 277 |
template_name = 'agenda/new-event.html' |
276 |
def delete_eventwithact(event): |
|
277 |
assert event.event_type_id == 1 |
|
278 | ||
279 |
# in case of "event" is an instance of "Event" model and not "EventWithAct" |
|
280 |
# and so doesn't have 'act' attribute |
|
281 |
try: |
|
282 |
if event.act.id \ |
|
283 |
and not event.act.is_billed: |
|
284 |
event.act.delete() |
|
285 | ||
286 |
if not event.act.id or \ |
|
287 |
not event.act.is_billed: |
|
288 |
event.delete() |
|
289 |
except AttributeError: |
|
290 |
event.delete() |
|
291 | ||
292 | 278 |
class DeleteOccurrenceView(TodayOccurrenceMixin, cbv.DeleteView): |
293 | 279 |
model = Event |
294 | 280 |
success_url = '..' |
... | ... | |
297 | 283 |
def delete(self, request, *args, **kwargs): |
298 | 284 |
self.object = self.get_object() |
299 |
if self.object.event_type_id == 1: |
|
300 |
delete_eventwithact(self.object) |
|
301 |
else: |
|
302 |
self.object.delete() |
|
303 | ||
285 |
# If the exception does not exist we need to create it before set it canceled |
|
286 |
self.object.save() |
|
287 |
self.object.delete() |
|
304 | 288 |
return HttpResponse(status=204) |
305 | 289 |
class DeleteEventView(cbv.DeleteView): |
... | ... | |
311 | 295 |
def delete(self, request, *args, **kwargs): |
312 | 296 |
self.object = self.get_object() |
313 |
# If exceptions remove them only if act is not billed |
|
314 |
for exception in self.object.exceptions.all(): |
|
315 |
exception.recurrence_periodicity = None |
|
316 |
exception.exception_to = None |
|
317 |
exception.save() |
|
318 |
if exception.event_type_id == 1: |
|
319 |
delete_eventwithact(exception) |
|
320 |
else: |
|
321 |
exception.delete() |
|
322 | ||
323 |
if self.object.event_type_id == 1: |
|
324 |
delete_eventwithact(self.object) |
|
325 |
else: |
|
326 |
self.object.delete() |
|
297 |
self.object.delete() |
|
327 | 298 |
return HttpResponse(status=204) |
328 | 299 |
class AgendaServiceActValidationView(TemplateView): |
calebasse/static/js/calebasse.agenda.js | ||
---|---|---|
290 | 290 |
$(base).on('click', '.update-periodic-rdv', function () { |
291 | 291 |
$('.ui-icon-closethick').click(); |
292 | 292 |
var id = $(this).data('id'); |
293 |
var delete_url = $(this).data('delete-url'); |
|
294 |
var delete_button = { |
|
295 |
text: "Supprimer", |
|
296 |
id: "delete-btn", |
|
297 |
click: function () { |
|
298 |
var r = delete_prompt("Etes-vous sûr de vouloir supprimer ce rendez-vous récurrent ?"); |
|
299 |
if (r == true) |
|
300 |
{ |
|
301 |
$.ajax({ |
|
302 |
url: delete_url, |
|
303 |
type: 'DELETE', |
|
304 |
success: function(data) { |
|
305 |
window.location.reload(true); |
|
306 |
return false; |
|
293 |
var one_act_already_billed = $(this).data('one_act_already_billed'); |
|
294 |
var delete_button = null |
|
295 |
if (one_act_already_billed == 'False') { |
|
296 |
var delete_url = $(this).data('delete-url'); |
|
297 |
var delete_button = { |
|
298 |
text: "Supprimer", |
|
299 |
id: "delete-btn", |
|
300 |
click: function () { |
|
301 |
var r = delete_prompt("Etes-vous sûr de vouloir supprimer ce rendez-vous récurrent ?"); |
|
302 |
if (r == true) |
|
303 |
{ |
|
304 |
$.ajax({ |
|
305 |
url: delete_url, |
|
306 |
type: 'DELETE', |
|
307 |
success: function(data) { |
|
308 |
window.location.reload(true); |
|
309 |
return false; |
|
310 |
} |
|
311 |
}); |
|
307 | 312 |
} |
308 |
}); |
|
309 | 313 |
} |
310 |
} |
|
311 |
};
|
|
314 |
};
|
|
315 |
} |
|
312 | 316 |
generic_ajaxform_dialog('/' + service + '/' + app_name + '/' + current_date + '/update-periodic-rdv/' + id, |
313 | 317 |
'Modifier un rendez-vous périodique', '#ajax-dlg', '900px', 'Modifier', null, init_datepickers, null, delete_button); |
314 | 318 |
}); |