diff --git a/smash/web/forms.py b/smash/web/forms.py index 6dda525d948bdc994968347163c5fb989dbc4240..66f6a6890105002106cd9fa7b99be162769bad80 100644 --- a/smash/web/forms.py +++ b/smash/web/forms.py @@ -6,7 +6,7 @@ from django.forms import ModelForm, Form from django.utils.dates import MONTHS from models import Subject, Worker, Appointment, Visit, AppointmentType, ContactAttempt, AppointmentTypeLink, \ - Availability + Availability, Holiday from models.constants import SUBJECT_TYPE_CHOICES, SCREENING_NUMBER_PREFIXES_FOR_TYPE """ @@ -430,13 +430,13 @@ class AvailabilityEditForm(ModelForm): worker = Worker.objects.get(id=self.cleaned_data["person"].id) availabilities = worker.availability_set.all() for availability in availabilities: - if availability.id<> self.availability_id: + if availability.id <> self.availability_id: validate_availability_conflict(self, self.cleaned_data, availability) def validate_availability_conflict(self, cleaned_data, availability): - start_hour = self.cleaned_data.get("available_from",None) - end_hour = self.cleaned_data.get("available_till",None) + start_hour = self.cleaned_data.get("available_from", None) + end_hour = self.cleaned_data.get("available_till", None) if availability.day_number == self.cleaned_data.get("day_number", None) and \ ((start_hour <= availability.available_from < end_hour) or (start_hour < availability.available_till <= end_hour) or @@ -447,3 +447,22 @@ def validate_availability_conflict(self, cleaned_data, availability): self.add_error('day_number', error) self.add_error('available_from', error) self.add_error('available_till', error) + + +class HolidayAddForm(ModelForm): + datetime_start = forms.DateTimeField(widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS), + initial=datetime.datetime.now().replace(hour=8, minute=0), + ) + datetime_end = forms.DateTimeField(widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS), + initial=datetime.datetime.now().replace(hour=17, minute=0), + ) + + class Meta: + model = Holiday + fields = '__all__' + + def clean(self): + worker = Worker.objects.get(id=self.cleaned_data["person"].id) + availabilities = worker.availability_set.all() + for availability in availabilities: + validate_availability_conflict(self, self.cleaned_data, availability) diff --git a/smash/web/migrations/0045_holiday_info.py b/smash/web/migrations/0045_holiday_info.py new file mode 100644 index 0000000000000000000000000000000000000000..37ab292b75130fbaa95ceaac2afb68f76fc6de5b --- /dev/null +++ b/smash/web/migrations/0045_holiday_info.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-09-04 15:09 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('web', '0044_auto_20170904_1602'), + ] + + operations = [ + migrations.AddField( + model_name='holiday', + name='info', + field=models.TextField(blank=True, max_length=2000, verbose_name=b'Comments'), + ), + ] diff --git a/smash/web/models/holiday.py b/smash/web/models/holiday.py index 113df03a4f50dbed5485d8c172fb7222ab0efcd8..01cceaeadf3c442b6f6bb51874c47e682aae1072 100644 --- a/smash/web/models/holiday.py +++ b/smash/web/models/holiday.py @@ -16,6 +16,11 @@ class Holiday(models.Model): verbose_name='On leave until' ) + info = models.TextField(max_length=2000, + blank=True, + verbose_name='Comments' + ) + def __str__(self): return "%s %s" % (self.person.first_name, self.person.last_name) diff --git a/smash/web/templates/doctors/add_holiday.html b/smash/web/templates/doctors/add_holiday.html new file mode 100644 index 0000000000000000000000000000000000000000..797bab7d47ad70f20606fd0c71805e53f6e2e0b5 --- /dev/null +++ b/smash/web/templates/doctors/add_holiday.html @@ -0,0 +1,74 @@ +{% extends "_base.html" %} +{% load static %} +{% load filters %} + +{% block styles %} + {{ block.super }} + {% include "includes/datetimepicker.css.html" %} + <link rel="stylesheet" href="{% static 'AdminLTE/plugins/awesomplete/awesomplete.css' %}"/> +{% endblock styles %} + +{% block ui_active_tab %}'workers'{% endblock ui_active_tab %} +{% block page_header %}New worker holiday{% endblock page_header %} +{% block page_description %}{% endblock page_description %} + +{% block title %}{{ block.super }} - Add availability{% endblock %} + +{% block breadcrumb %} + {% include "doctors/breadcrumb.html" %} +{% endblock breadcrumb %} + +{% block maincontent %} + + {% block content %} + <div class="box box-info"> + <div class="box-header with-border"> + <a href="{% url 'web.views.doctor_edit' doctor_id %}" class="btn btn-block btn-default">Go back (without + changes)</a> + </div> + + <form method="post" action="" class="form-horizontal"> + {% csrf_token %} + + <div class="box-body"> + <div class="col-sm-6"> + {% for field in form %} + <div class="form-group {% if field.errors %}has-error{% endif %}"> + <label for="{# TODO #}" class="col-sm-4 control-label"> + {{ field.label }} + </label> + + <div class="col-sm-8"> + {{ field|add_class:'form-control' }} + </div> + + {% if field.errors %} + <span class="help-block"> + {{ field.errors }} + </span> + {% endif %} + </div> + {% endfor %} + </div> + </div><!-- /.box-body --> + + <div class="box-footer"> + <div class="col-sm-6"> + <button type="submit" class="btn btn-block btn-success">Add</button> + </div> + <div class="col-sm-6"> + <a href="{% url 'web.views.doctor_edit' doctor_id %}" + class="btn btn-block btn-default">Cancel</a> + </div> + </div><!-- /.box-footer --> + </form> + </div> + {% endblock %} + +{% endblock maincontent %} + +{% block scripts %} + {{ block.super }} + + {% include "includes/datetimepicker.js.html" %} +{% endblock scripts %} diff --git a/smash/web/templates/doctors/edit.html b/smash/web/templates/doctors/edit.html index 241ad9eafc2164f92f9469c683f33624847ec0d1..e41beaed77e99201e1f6fcbb5c865c13a0f83812 100644 --- a/smash/web/templates/doctors/edit.html +++ b/smash/web/templates/doctors/edit.html @@ -61,56 +61,97 @@ </div><!-- /.box-footer --> </form> </div> - {% endblock %} - <div class="box-body"> - <table id="table" class="table table-bordered table-striped"> - <thead> - <tr> - <th>Day</th> - <th>From</th> - <th>Until</th> - <th>Modify</th> - <th>Remove</th> - </tr> - </thead> - <tbody> - {% for availability in availabilities %} + + <div class="box-header with-border"> + <h3 class="box-title">Availability</h3> + </div> + <div class="box-body"> + <table id="table" class="table table-bordered table-striped"> + <thead> <tr> - <td> - {% for weekday in weekdays %} - {% if availability.day_number == weekday.0 %} - {{ weekday.1 }} - {% endif %} - {% endfor %} - </td> - <td>{{ availability.available_from }}</td> - <td>{{ availability.available_till }}</td> - <td> - <a href="{% url 'web.views.doctor_availability_edit' availability.id %}" type="button" - class="btn btn-block btn-default">Edit</a> - </td> - <td> - <a href="{% url 'web.views.doctor_availability_delete' availability.id %}" type="button" - class="btn btn-block btn-default">Delete</a> - </td> + <th>Day</th> + <th>From</th> + <th>Until</th> + <th>Modify</th> + <th>Remove</th> </tr> - {% endfor %} - - </tbody> - </table> + </thead> + <tbody> + {% for availability in availabilities %} + <tr> + <td> + {% for weekday in weekdays %} + {% if availability.day_number == weekday.0 %} + {{ weekday.1 }} + {% endif %} + {% endfor %} + </td> + <td>{{ availability.available_from }}</td> + <td>{{ availability.available_till }}</td> + <td> + <a href="{% url 'web.views.doctor_availability_edit' availability.id %}" type="button" + class="btn btn-block btn-default">Edit</a> + </td> + <td> + <a href="{% url 'web.views.doctor_availability_delete' availability.id %}" type="button" + class="btn btn-block btn-default">Delete</a> + </td> + </tr> + {% endfor %} + + </tbody> + </table> + + <div class="box-footer"> + <div class="col-sm-6"> + <a href="{% url 'views.doctor.doctor_availability_add' doctor_id %}" type="button" + class="btn btn-block btn-success">Add availability</a> + </div> + </div><!-- /.box-footer --> - <div class="box-footer"> - <div class="col-sm-6"> - <a href="{% url 'views.doctor.doctor_availability_add' doctor_id %}" type="button" - class="btn btn-block btn-success">Add availability</a> - </div> - </div><!-- /.box-footer --> + </div> - </div> + <div class="box-header with-border"> + <h3 class="box-title">Holidays</h3> + </div> + <div class="box-body"> + <table id="table" class="table table-bordered table-striped"> + <thead> + <tr> + <th>From</th> + <th>Until</th> + <th>Info</th> + <th>Remove</th> + </tr> + </thead> + <tbody> + {% for holiday in holidays %} + <tr> + <td>{{ holiday.datetime_start }}</td> + <td>{{ holiday.datetime_end }}</td> + <td>{{ holiday.info }}</td> + <td> + <a href="{% url 'web.views.doctor_holiday_delete' holiday.id %}" type="button" + class="btn btn-block btn-default">Delete</a> + </td> + </tr> + {% endfor %} + + </tbody> + </table> + + <div class="box-footer"> + <div class="col-sm-6"> + <a href="{% url 'views.doctor.doctor_holiday_add' doctor_id %}" type="button" + class="btn btn-block btn-success">Add holiday</a> + </div> + </div><!-- /.box-footer --> + </div> + {% endblock %} {% endblock maincontent %} @@ -124,7 +165,7 @@ $('#table').DataTable({ "paging": true, "lengthChange": false, - "searching": true, + "searching": false, "ordering": false, "info": true, "autoWidth": false diff --git a/smash/web/templates/subjects/edit.html b/smash/web/templates/subjects/edit.html index 956823144048a7cdf7829f6b6976059d3ecb4958..e2cb7121d332a7032a8ce1d0f19cb6e5e4ca079b 100644 --- a/smash/web/templates/subjects/edit.html +++ b/smash/web/templates/subjects/edit.html @@ -139,7 +139,7 @@ <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> - <h4 class="modal-title">Are you sure that you want to perfom this operation?</h4> + <h4 class="modal-title">Are you sure that you want to perform this operation?</h4> </div> <div class="modal-body"> <p>Marking a subject resigned or deceased cannot be undone.</p> diff --git a/smash/web/urls.py b/smash/web/urls.py index f23574d1e5748d82c9b9d679b19a5f2325f00b0d..332b57008700a272e3962fbc9ce23eceffa4bb75 100644 --- a/smash/web/urls.py +++ b/smash/web/urls.py @@ -90,13 +90,19 @@ urlpatterns = [ url(r'^doctors$', views.doctor.doctors, name='web.views.doctors'), url(r'^doctors/add$', views.doctor.doctor_add, name='web.views.doctor_add'), url(r'^doctors/edit/(?P<doctor_id>\d+)$', views.doctor.doctor_edit, name='web.views.doctor_edit'), + url(r'^doctors/(?P<doctor_id>\d+)/availability/add$', views.doctor.doctor_availability_add, + name='views.doctor.doctor_availability_add'), + url(r'^doctors/availability/(?P<availability_id>\d+)/delete$', views.doctor.doctor_availability_delete, name='web.views.doctor_availability_delete'), url(r'^doctors/availability/(?P<availability_id>\d+)/edit', views.doctor.doctor_availability_edit, name='web.views.doctor_availability_edit'), - url(r'^doctors/(?P<doctor_id>\d+)/availability/add$', views.doctor.doctor_availability_add, - name='views.doctor.doctor_availability_add'), + url(r'^doctors/(?P<doctor_id>\d+)/holiday/add$', views.doctor.doctor_holiday_add, + name='views.doctor.doctor_holiday_add'), + + url(r'^doctors/holiday/(?P<holiday_id>\d+)/delete$', views.doctor.doctor_holiday_delete, + name='web.views.doctor_holiday_delete'), #################### # EQUIPMENT # diff --git a/smash/web/views/doctor.py b/smash/web/views/doctor.py index 5e3a4f04f09ad6747a072e47c5a1895d5e27c830..dca2692f13606e93c2368e7390847b671616af00 100644 --- a/smash/web/views/doctor.py +++ b/smash/web/views/doctor.py @@ -2,8 +2,8 @@ from django.shortcuts import redirect, get_object_or_404 from . import wrap_response -from ..forms import WorkerAddForm, WorkerEditForm, AvailabilityAddForm, AvailabilityEditForm -from ..models import Worker, Availability +from ..forms import WorkerAddForm, WorkerEditForm, AvailabilityAddForm, AvailabilityEditForm, HolidayAddForm +from ..models import Worker, Availability, Holiday from ..models.constants import WEEKDAY_CHOICES @@ -38,10 +38,12 @@ def doctor_edit(request, doctor_id): else: form = WorkerEditForm(instance=the_doctor) availabilities = Availability.objects.filter(person=doctor_id).order_by('day_number', 'available_from'); + holidays = Holiday.objects.filter(person=doctor_id).order_by('-datetime_start'); return wrap_response(request, 'doctors/edit.html', { 'form': form, 'availabilities': availabilities, + 'holidays': holidays, 'doctor_id': doctor_id, 'weekdays': WEEKDAY_CHOICES }) @@ -88,3 +90,29 @@ def doctor_availability_edit(request, availability_id): 'availability_id': availability_id, 'doctor_id': availability.person_id, }) + + +def doctor_holiday_delete(request, holiday_id): + holiday = Holiday.objects.filter(id=holiday_id) + doctor_id = holiday[0].person.id + holiday.delete() + return redirect(doctor_edit, doctor_id=doctor_id) + + +def doctor_holiday_add(request, doctor_id): + doctors = Worker.objects.filter(id=doctor_id) + doctor = None + if len(doctors) > 0: + doctor = doctors[0] + if request.method == 'POST': + form = HolidayAddForm(request.POST, request.FILES) + if form.is_valid(): + form.save() + return redirect(doctor_edit, doctor_id=doctor_id) + else: + form = HolidayAddForm(initial={'person': doctor}) + return wrap_response(request, 'doctors/add_holiday.html', + { + 'form': form, + 'doctor_id': doctor_id + })