First version
This commit is contained in:
1
polyclinic_scheduling/apps/schedule/__init__.py
Normal file
1
polyclinic_scheduling/apps/schedule/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
default_app_config = 'apps.schedule.apps.ScheduleConfig'
|
15
polyclinic_scheduling/apps/schedule/admin.py
Normal file
15
polyclinic_scheduling/apps/schedule/admin.py
Normal file
@ -0,0 +1,15 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Schedule
|
||||
|
||||
# Register your models here.
|
||||
@admin.register(Schedule)
|
||||
class ScheduleAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'employee', 'email', 'created_at', 'processed')
|
||||
ordering = ('name', 'created_at')
|
||||
search_fields = ('name', 'email')
|
||||
|
||||
def processed(self,obj):
|
||||
return len(obj.output_peregrine) > 0
|
||||
|
||||
processed.boolean = True
|
8
polyclinic_scheduling/apps/schedule/apps.py
Normal file
8
polyclinic_scheduling/apps/schedule/apps.py
Normal file
@ -0,0 +1,8 @@
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
class ScheduleConfig(AppConfig):
|
||||
name = 'apps.schedule'
|
||||
label = 'schedule'
|
||||
verbose_name = _('Schedule')
|
||||
verbose_name_plural = _('Schedules')
|
9
polyclinic_scheduling/apps/schedule/forms.py
Normal file
9
polyclinic_scheduling/apps/schedule/forms.py
Normal file
@ -0,0 +1,9 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .models import Schedule
|
||||
|
||||
class ScheduleForm(forms.Form):
|
||||
name = forms.CharField(label=_('Department name'), help_text=_('Enter a descriptive name for this schedule'), max_length=100)
|
||||
email = forms.CharField(label=_('Email address for results'), help_text=_('When the job is done, the results will be sent to this email address'), max_length=100)
|
||||
json = forms.CharField(label=_('Email address for results'), help_text=_('When the job is done, the results will be sent to this email address'), widget=forms.HiddenInput(), strip=True)
|
@ -0,0 +1,36 @@
|
||||
# Generated by Django 3.0.6 on 2020-05-13 13:33
|
||||
|
||||
import collections
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import jsonfield.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('employee', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Schedule',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, help_text='The date and time this model has been created', verbose_name='Date created')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, help_text='The date and time this model has been updated', verbose_name='Date updated')),
|
||||
('name', models.CharField(help_text='Name of the schedule', max_length=100, verbose_name='Name')),
|
||||
('email', models.CharField(help_text='Email address where the results will be sent to.', max_length=100, verbose_name='Email address')),
|
||||
('planning_source', jsonfield.fields.JSONField(blank=True, help_text='The schedule input in JSON format based on the form data', load_kwargs={'object_pairs_hook': collections.OrderedDict}, verbose_name='Schedule input')),
|
||||
('planning_peregrine', models.TextField(blank=True, help_text='This is the translated content from the source for use with Peregrine cluster', verbose_name='Peregrine input')),
|
||||
('peregrine_accepted', models.BooleanField(default=False, help_text='When true, the Peregrine cluster has picked up the job.', verbose_name='Peregrine accepted')),
|
||||
('output_peregrine', models.BinaryField(blank=True, help_text='This is the output in binary format from the Peregrine cluster', verbose_name='Peregrine binary output')),
|
||||
('employee', models.ForeignKey(help_text='Select the employee that is responsible for this schedule request', on_delete=django.db.models.deletion.CASCADE, to='employee.Employee')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
26
polyclinic_scheduling/apps/schedule/models.py
Normal file
26
polyclinic_scheduling/apps/schedule/models.py
Normal file
@ -0,0 +1,26 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from lib.models.base import MetaDataModel
|
||||
from apps.employee.models import Employee
|
||||
|
||||
from jsonfield import JSONField
|
||||
import collections
|
||||
|
||||
# Create your models here.
|
||||
class Schedule(MetaDataModel):
|
||||
employee = models.ForeignKey(Employee, on_delete=models.CASCADE, help_text=_('Select the employee that is responsible for this schedule request'))
|
||||
|
||||
name = models.CharField(_('Name'), max_length=100, help_text=_('Name of the schedule'))
|
||||
email = models.CharField(_('Email address'), max_length=100, help_text=_('Email address where the results will be sent to.'))
|
||||
|
||||
planning_source = JSONField(_('Schedule input'), blank=True, load_kwargs={'object_pairs_hook': collections.OrderedDict}, help_text=_('The schedule input in JSON format based on the form data'))
|
||||
planning_peregrine = models.TextField(_('Peregrine input'), blank=True, help_text=_('This is the translated content from the source for use with Peregrine cluster'))
|
||||
|
||||
peregrine_accepted = models.BooleanField(_('Peregrine accepted'),default=False, help_text=_('When true, the Peregrine cluster has picked up the job.'))
|
||||
|
||||
output_peregrine = models.BinaryField(_('Peregrine binary output'), blank=True, help_text=_('This is the output in binary format from the Peregrine cluster'))
|
||||
|
||||
def __str__(self):
|
||||
"""str: Returns a readable name for the schedule. Format is [schedule_name] (employee_name)."""
|
||||
return '{} ({})'.format(self.name, self.employee)
|
@ -0,0 +1,37 @@
|
||||
{% extends 'base.html' %} <!-- Add this for inheritance -->
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}{% trans "Schedules overview list" %}{% endblock %}
|
||||
{% block pagetitle %}{% trans "Schedules overview list" %}{% endblock %}
|
||||
{% block content %}
|
||||
<p>
|
||||
<strong>{% trans "Schedules overview list" %}</strong>
|
||||
<table>
|
||||
<tr>
|
||||
{% comment %} <th>{% trans "Department" %}</th> {% endcomment %}
|
||||
<th>{% trans "Name" %}</th>
|
||||
<th>{% trans "Created" %}</th>
|
||||
<th>{% trans "Updated" %}</th>
|
||||
<th>{% trans "Running" %}</th>
|
||||
<th>{% trans "Report" %}</th>
|
||||
</tr>
|
||||
{% for schedule in object_list %}
|
||||
<tr>
|
||||
{% comment %} <td><span>{{ schedule.name }}</span></td> {% endcomment %}
|
||||
<td>{% comment %}<a href="{% url 'schedule:detail' pk=schedule.id %}">{% endcomment %}{{ schedule.name }}{% comment %}</a>{% endcomment %}</td>
|
||||
<td>{{ schedule.created_at|date:"SHORT_DATETIME_FORMAT" }}</td>
|
||||
<td>{{ schedule.updated_at|date:"SHORT_DATETIME_FORMAT" }}</td>
|
||||
<td>None</td>
|
||||
<td>None</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="6" class="rug-text-center">{% trans "No schedules available" %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<br />
|
||||
<br />
|
||||
{% include "pager.html" %}
|
||||
</p>
|
||||
{% endblock %}
|
@ -0,0 +1,650 @@
|
||||
{% extends 'base.html' %} <!-- Add this for inheritance -->
|
||||
{% load i18n %}
|
||||
|
||||
{% block title %}{% trans "New schedule" %}{% endblock %}
|
||||
{% block pagetitle %}{% trans "New schedule" %}{% endblock %}
|
||||
{% block content %}
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
|
||||
<div class="container">
|
||||
<form method="POST" action="{% url 'schedule:new' %}">
|
||||
{% csrf_token %}
|
||||
{{ form.json }}
|
||||
<h1>Algemene informatie</h1>
|
||||
<p>Als een afdeling meerdere wachtkamers heeft, vul dan dit formulier meerdere keren in; een keer voor elke groep van behandelkamers die een wachtkamer delen.</p>
|
||||
<div class="form-group">
|
||||
<label for="id_name">Naam van de afdeling</label>
|
||||
<input type="text" class="form-control" id="id_name" name="name" aria-describedby="afdelingnaamHelp" required>
|
||||
<small id="afdelingnaamHelp" class="form-text text-muted">Geef de naam op van de afdeling</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="id_email">Emailadres voor de resultaten</label>
|
||||
<input type="email" class="form-control" id="id_email" name="email" aria-describedby="emailadresHelp" required value={{user.email}}>
|
||||
<small id="emailadresHelp" class="form-text text-muted">Geef het emailadres op om de uitkomsten te ontvangen</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="patienten">Aantal patiënten dat kan wachten in wachtkamer</label>
|
||||
<input type="number" class="form-control" id="patienten" name="patienten" min="1" max="100" aria-describedby="patientenHelp" required>
|
||||
<small id="patientenHelp" class="form-text text-muted">Met bewaren 1,5m afstand tussen lopende en zittende patiënten!</small>
|
||||
</div>
|
||||
<br />
|
||||
<hr>
|
||||
<br />
|
||||
<h1>Specialisaties binnen de afdeling</h1>
|
||||
<div class="poliekliniek_specialisatie">
|
||||
<div class="form-group">
|
||||
<label for="specialisatie_1" class="h4">Specialisatie 1</label>
|
||||
<input type="text" class="form-control" style="font-size: 1.5em" id="specialisatie_1" name="specialisatie_1" aria-describedby="specialisatie_1Help" required>
|
||||
<small id="specialisatie_1Help" class="form-text text-muted float-right d-none"><a href="#">Verwijder</a></small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="specialisatie_afkorting_1">Specialisatie afkorting</label>
|
||||
<input type="text" class="form-control" maxlength="5" id="specialisatie_afkorting_1" name="specialisatie_afkorting_1" aria-describedby="specialisatie_afkorting_1Help" required>
|
||||
<small id="specialisatie_1Help" class="form-text text-muted">Geef een afkorting op voor deze specialisatie. Deze gebruiken wij in de figuren van de rapportage.</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="specialisatie_aantal_artsen_1">Aantal artsen</label>
|
||||
<input type="number" class="form-control" min="0" max="100" id="specialisatie_aantal_artsen_1" name="specialisatie_aantal_artsen_1" aria-describedby="specialisatie_aantal_artsen_1Help" required>
|
||||
<small id="specialisatie_aantal_artsen_1Help" class="form-text text-muted">Maximaal aantal artsen dat op enig moment tegelijk aan het werk zou kunnen zijn.</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="specialisatie_aantal_kamers_1">Aantal behandelkamers</label>
|
||||
<input type="number" class="form-control" min="0" max="100" id="specialisatie_aantal_kamers_1" name="specialisatie_aantal_kamers_1" aria-describedby="specialisatie_aantal_kamers_1Help" required>
|
||||
<small id="specialisatie_aantal_kamers_1Help" class="form-text text-muted">Aantal behandelkamers dat beschikbaar is per specialisatie</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="specialisatie_aantal_behandelingen_1">Aantal verschillende soorten behandelingen</label>
|
||||
<input type="number" class="form-control" min="0" max="100" id="specialisatie_aantal_behandelingen_1" name="specialisatie_aantal_behandelingen_1" aria-describedby="specialisatie_aantal_behandelingen_1Help" required>
|
||||
<small id="specialisatie_aantal_behandelingen_1Help" class="form-text text-muted"></small>
|
||||
</div>
|
||||
<div class="form-group werktijden">
|
||||
<label>Werktijden <small class="text-danger" style="display:none"> Nog niet volledig</small></label>
|
||||
|
||||
<div class="container ml-4">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">de hele werkdag</div>
|
||||
<div class="col-sm-3">
|
||||
<select class="form-control" id="werkdag_start_afdeling_1" name="werkdag_start_afdeling_1" required>
|
||||
<option value="">Maak een keuze</option>
|
||||
<option value="0600">06:00</option>
|
||||
<option value="0615">06:15</option>
|
||||
<option value="0630">06:30</option>
|
||||
<option value="0645">06:45</option>
|
||||
<option value="0700">07:00</option>
|
||||
<option value="0715">07:15</option>
|
||||
<option value="0730">07:30</option>
|
||||
<option value="0745">07:45</option>
|
||||
<option value="0800">08:00</option>
|
||||
<option value="0815">08:15</option>
|
||||
<option value="0830">08:30</option>
|
||||
<option value="0845">08:45</option>
|
||||
<option value="0900">09:00</option>
|
||||
<option value="0915">09:15</option>
|
||||
<option value="0930">09:30</option>
|
||||
<option value="0945">09:45</option>
|
||||
<option value="1000">10:00</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<select class="form-control" id="werkdag_end_afdeling_1" name="werkdag_end_afdeling_1" required>
|
||||
<option value="">Maak een keuze</option>
|
||||
<option value="1200">12:00</option>
|
||||
<option value="1215">12:15</option>
|
||||
<option value="1230">12:30</option>
|
||||
<option value="1245">12:45</option>
|
||||
<option value="1300">13:00</option>
|
||||
<option value="1315">13:15</option>
|
||||
<option value="1330">13:30</option>
|
||||
<option value="1345">13:45</option>
|
||||
<option value="1400">14:00</option>
|
||||
<option value="1415">14:15</option>
|
||||
<option value="1430">14:30</option>
|
||||
<option value="1445">14:45</option>
|
||||
<option value="1500">15:00</option>
|
||||
<option value="1515">15:15</option>
|
||||
<option value="1530">15:30</option>
|
||||
<option value="1545">15:45</option>
|
||||
<option value="1600">16:00</option>
|
||||
<option value="1615">16:15</option>
|
||||
<option value="1630">16:30</option>
|
||||
<option value="1645">16:45</option>
|
||||
<option value="1700">17:00</option>
|
||||
<option value="1715">17:15</option>
|
||||
<option value="1720">17:30</option>
|
||||
<option value="1745">17:45</option>
|
||||
<option value="1800">18:00</option>
|
||||
<option value="1815">18:15</option>
|
||||
<option value="1830">18:30</option>
|
||||
<option value="1845">18:45</option>
|
||||
<option value="1900">19:00</option>
|
||||
<option value="1915">19:15</option>
|
||||
<option value="1930">19:30</option>
|
||||
<option value="1945">19:45</option>
|
||||
<option value="2000">20:00</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">ochtendpauze</div>
|
||||
<div class="col-sm-3">
|
||||
<select class="form-control" id="ochtend_pauze_start_afdeling_1" name="ochtend_pauze_start_afdeling_1" required>
|
||||
<option value="">Maak een keuze</option>
|
||||
<option value="0">Geen pauze</option>
|
||||
<option value="0900">09:00</option>
|
||||
<option value="0915">09:15</option>
|
||||
<option value="0930">09:30</option>
|
||||
<option value="0945">09:45</option>
|
||||
<option value="1000">10:00</option>
|
||||
<option value="1015">10:15</option>
|
||||
<option value="1030">10:30</option>
|
||||
<option value="1045">10:45</option>
|
||||
<option value="1100">11:00</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<select class="form-control" id="ochtend_pauze_end_afdeling_1" name="ochtend_pauze_end_afdeling_1" required>
|
||||
<option value="">Maak een keuze</option>
|
||||
<option value="0">Geen pauze</option>
|
||||
<option value="0915">09:15</option>
|
||||
<option value="0930">09:30</option>
|
||||
<option value="0945">09:45</option>
|
||||
<option value="1000">10:00</option>
|
||||
<option value="1015">10:15</option>
|
||||
<option value="1030">10:30</option>
|
||||
<option value="1045">10:45</option>
|
||||
<option value="1100">11:00</option>
|
||||
<option value="1115">11:15</option>
|
||||
<option value="1130">11:30</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">lunchpauze</div>
|
||||
<div class="col-sm-3">
|
||||
<select class="form-control" id="lunch_pauze_start_afdeling_1" name="lunch_pauze_start_afdeling_1" required>
|
||||
<option value="">Maak een keuze</option>
|
||||
<option value="0">Geen pauze</option>
|
||||
<option value="1130">11:30</option>
|
||||
<option value="1145">11:45</option>
|
||||
<option value="1200">12:00</option>
|
||||
<option value="1215">12:15</option>
|
||||
<option value="1230">12:30</option>
|
||||
<option value="1245">12:45</option>
|
||||
<option value="1300">13:00</option>
|
||||
<option value="1315">13:15</option>
|
||||
<option value="1330">13:30</option>
|
||||
<option value="1345">13:45</option>
|
||||
<option value="1400">14:00</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<select class="form-control" id="lunch_pauze_end_afdeling_1" name="lunch_pauze_end_afdeling_1" required>
|
||||
<option value="">Maak een keuze</option>
|
||||
<option value="0">Geen pauze</option>
|
||||
<option value="1200">12:00</option>
|
||||
<option value="1215">12:15</option>
|
||||
<option value="1230">12:30</option>
|
||||
<option value="1245">12:45</option>
|
||||
<option value="1300">13:00</option>
|
||||
<option value="1315">13:15</option>
|
||||
<option value="1330">13:30</option>
|
||||
<option value="1345">13:45</option>
|
||||
<option value="1400">14:00</option>
|
||||
<option value="1415">14:15</option>
|
||||
<option value="1430">14:30</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6">middagpauze</div>
|
||||
<div class="col-sm-3">
|
||||
<select class="form-control" id="middag_pauze_start_afdeling_1" name="middag_pauze_start_afdeling_1" required>
|
||||
<option value="">Maak een keuze</option>
|
||||
<option value="0">Geen pauze</option>
|
||||
<option value="1430">14:30</option>
|
||||
<option value="1445">14:45</option>
|
||||
<option value="1500">15:00</option>
|
||||
<option value="1515">15:15</option>
|
||||
<option value="1530">15:30</option>
|
||||
<option value="1545">15:45</option>
|
||||
<option value="1600">16:00</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<select class="form-control" id="middag_pauze_end_afdeling_1" name="middag_pauze_end_afdeling_1" required>
|
||||
<option value="">Maak een keuze</option>
|
||||
<option value="0">Geen pauze</option>
|
||||
<option value="1445">14:45</option>
|
||||
<option value="1500">15:00</option>
|
||||
<option value="1515">15:15</option>
|
||||
<option value="1530">15:30</option>
|
||||
<option value="1545">15:45</option>
|
||||
<option value="1600">16:00</option>
|
||||
<option value="1615">16:15</option>
|
||||
<option value="1630">16:30</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-4 font-weight-bold"><a href="#" class="add_specialisatie">klik hier om een extra specialisatie toe te voegen</a></div>
|
||||
<br />
|
||||
<hr>
|
||||
<br />
|
||||
|
||||
<h1>Behandelingen</h1>
|
||||
<p>In het model worden slots van 5 minuten gebruikt voor het bepalen van starttijden. etc. Afspraken starten daarmee om bijv. 10.00, 10.05, 10.10.<br />Afspraakduur wordt daarmee ook in veelvouden van 5 minuten gevraagd.</p>
|
||||
<p>Zowel afspraken waar de patiënt fysiek in het ziekenhuis is, als wel telefoongesprekken worden hier gevraagd. Beide type afspraken kunnen in het raster worden gepland.</p>
|
||||
<p>"Normaal" betekent: zoals het was voor COVID-19<br />30% betekent: als je maar 30% van de patiënten kunt binnenkrijgen, hoeveel afspraken van elk type zou je dan willen inplannen?</p>
|
||||
<div class="container">
|
||||
<div class="row mb-2">
|
||||
<div class="col"><strong>Naam behandeling</strong></div>
|
||||
<div class="col"><strong>Duur (in minuten)</strong></div>
|
||||
<div class="col"><strong>Specialisatie</strong></div>
|
||||
<div class="col"><strong>Methode</strong></div>
|
||||
<div class="col"><strong>Normaal aantal</strong></div>
|
||||
<div class="col"><strong>Gewenst als op 30%</strong></div>
|
||||
</div>
|
||||
|
||||
<div class="row behandeling">
|
||||
<div class="col">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" id="behandeling_1" name="behandeling_1" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="form-group">
|
||||
<select class="form-control" id="behandeling_durartion_1" name="behandeling_durartion_1" required>
|
||||
<option value="5">5</option>
|
||||
<option value="10">10</option>
|
||||
<option value="15">15</option>
|
||||
<option value="20">20</option>
|
||||
<option value="25">25</option>
|
||||
<option value="30">30</option>
|
||||
<option value="35">35</option>
|
||||
<option value="40">40</option>
|
||||
<option value="45">45</option>
|
||||
<option value="50">50</option>
|
||||
<option value="55">55</option>
|
||||
<option value="60">60</option>
|
||||
<option value="65">65</option>
|
||||
<option value="70">70</option>
|
||||
<option value="75">75</option>
|
||||
<option value="80">80</option>
|
||||
<option value="85">85</option>
|
||||
<option value="90">90</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="form-group">
|
||||
<select class="form-control specialismes" id="behandeling_specialisme_1" name="behandeling_specialisme_1" required></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="form-group">
|
||||
<select class="form-control" id="behandeling_method_1" name="behandeling_method_1" required>
|
||||
<option value="live">in persoon</option>
|
||||
<option value="phone">telefonisch</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="form-group">
|
||||
<input type="number" class="form-control behandeling_calc" id="behandeling_100p_1" name="behandeling_100p_1" min="0" max="100" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="form-group">
|
||||
<input type="number" class="form-control behandeling_calc" id="behandeling_30p_1" name="behandeling_30p_1" min="0" max="100" required>
|
||||
<small class="form-text text-muted float-right d-none"><a href="#">Verwijder</a></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-4 font-weight-bold"><a href="#" class="add_behandeling">klik hier om een nieuwe behandeling toe te voegen</a></div>
|
||||
|
||||
<div class="row behandeling_calc_summary">
|
||||
<div class="col-8"><strong>Totaal aantal afspraken</strong></div>
|
||||
<div class="col-2 text-center">0</div>
|
||||
<div class="col-2 text-center">0</div>
|
||||
</div>
|
||||
<div class="row behandeling_calc_remarks">
|
||||
<div class="col-12"></div>
|
||||
</div>
|
||||
<br />
|
||||
<hr>
|
||||
<br />
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
<!-- Optional JavaScript -->
|
||||
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
|
||||
<!--
|
||||
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.1-muted 6.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
|
||||
-->
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
function addSpecialisatie() {
|
||||
var clone = jQuery('div.poliekliniek_specialisatie:first').clone()
|
||||
clone.find('input').val('');
|
||||
clone.find('small').removeClass('d-none');
|
||||
clone.insertAfter('div.poliekliniek_specialisatie:last');
|
||||
updateSpecialisaties();
|
||||
loadRemoveSpecialisatie();
|
||||
}
|
||||
|
||||
function loadRemoveSpecialisatie() {
|
||||
jQuery('div.poliekliniek_specialisatie small a').off('click').on('click',function(event){
|
||||
event.preventDefault();
|
||||
jQuery(this).parentsUntil('.poliekliniek_specialisatie').parent().remove();
|
||||
updateSpecialisaties();
|
||||
updateSpecialisatieValues();
|
||||
});
|
||||
}
|
||||
|
||||
function updateSpecialisaties() {
|
||||
jQuery('div.poliekliniek_specialisatie').each(function(counter,element){
|
||||
if (counter > 0) {
|
||||
element = jQuery(element);
|
||||
var nr = counter + 1;
|
||||
element.find('label').first().text('Specialisatie ' + nr);
|
||||
element.find('select,input').each(function(index,selectitem){
|
||||
selectitem = jQuery(selectitem);
|
||||
selectitem.prop('name',selectitem.prop('name').replace(/_\d+$/,'_' + nr));
|
||||
selectitem.prop('id',selectitem.prop('id').replace(/_\d+$/,'_' + nr));
|
||||
|
||||
if (selectitem.attr('aria-describedby')) {
|
||||
selectitem.attr('aria-describedby',selectitem.attr('aria-describedby').replace(/_\d+Help$/,'_' + nr + 'Help'));
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
jQuery('div.poliekliniek_specialisatie input').off('change').on('change',function(){
|
||||
updateSpecialisatieValues();
|
||||
});
|
||||
}
|
||||
|
||||
function updateSpecialisatieValues() {
|
||||
var specialismes = [];
|
||||
jQuery('div.poliekliniek_specialisatie').each(function(){
|
||||
specialismes.push(jQuery('input:first',this).val());
|
||||
});
|
||||
|
||||
jQuery('select.specialismes').each(function(counter,element){
|
||||
element = jQuery(element);
|
||||
let selected_index = element[0].selectedIndex;
|
||||
|
||||
element.find('option').remove();
|
||||
jQuery.each(specialismes,function(index,item) {
|
||||
element.append(jQuery('<option>').val(item).text(item));
|
||||
});
|
||||
|
||||
if (selected_index > -1) {
|
||||
element[0].selectedIndex = selected_index;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function addBehandelkamer() {
|
||||
var clone = jQuery('div.row.behandelkamer:first').clone()
|
||||
clone.find('input').val('');
|
||||
clone.find('selected').val('');
|
||||
clone.find('small').removeClass('d-none');
|
||||
|
||||
clone.insertAfter('div.row.behandelkamer:last');
|
||||
|
||||
updateBehandelkamers();
|
||||
loadRemoveBehandelkamer();
|
||||
}
|
||||
|
||||
function loadRemoveBehandelkamer() {
|
||||
jQuery('div.behandelkamer small a').off('click').on('click',function(event){
|
||||
event.preventDefault();
|
||||
jQuery(this).parentsUntil('.behandelkamer').parent().remove();
|
||||
|
||||
updateBehandelkamers();
|
||||
});
|
||||
}
|
||||
|
||||
function updateBehandelkamers() {
|
||||
jQuery('div.behandelkamer').each(function(counter,element){
|
||||
if (counter > 0) {
|
||||
element = jQuery(element);
|
||||
var nr = counter + 1;
|
||||
element.find('input').prop('id','behandelkamer_' + nr);
|
||||
element.find('input').prop('name','behandelkamer_' + nr);
|
||||
|
||||
element.find('select').prop('id','behandelkamer_specialisme_' + nr);
|
||||
element.find('select').prop('name','behandelkamer_specialisme_' + nr);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function addBehandeling() {
|
||||
var clone = jQuery('div.row.behandeling:first').clone()
|
||||
|
||||
clone.find('input').val('');
|
||||
clone.find('selected').val('');
|
||||
clone.find('small').removeClass('d-none');
|
||||
|
||||
clone.insertAfter('div.row.behandeling:last');
|
||||
|
||||
jQuery('input.behandeling_calc').off('change keyup').on('change keyup',function(){
|
||||
calculateBehandelingen();
|
||||
});
|
||||
|
||||
updateBehandelingen();
|
||||
loadRemoveBehandeling();
|
||||
}
|
||||
|
||||
function loadRemoveBehandeling() {
|
||||
jQuery('div.behandeling small a').off('click').on('click',function(event){
|
||||
event.preventDefault();
|
||||
jQuery(this).parentsUntil('.behandeling').parent().remove();
|
||||
|
||||
updateBehandelingen();
|
||||
});
|
||||
}
|
||||
|
||||
function updateBehandelingen() {
|
||||
jQuery('div.behandeling').each(function(counter,element){
|
||||
if (counter > 0) {
|
||||
element = jQuery(element);
|
||||
var nr = counter + 1;
|
||||
|
||||
element.find('select,input').each(function(index,selectitem){
|
||||
selectitem = jQuery(selectitem);
|
||||
selectitem.prop('name',selectitem.prop('name').replace(/_\d+$/,'_' + nr));
|
||||
selectitem.prop('id',selectitem.prop('id').replace(/_\d+$/,'_' + nr));
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function calculateBehandelingen() {
|
||||
let total = 0, percentage = 0;
|
||||
let ok = true;
|
||||
|
||||
jQuery('div.row.behandeling').each(function(counter,row){
|
||||
row = jQuery(row);
|
||||
total += (row.find('input[name*="_100p_"]').val() != '' ? row.find('input[name*="_100p_"]').val() * 1 : 0);
|
||||
percentage += (row.find('input[name*="_30p_"]').val() != '' ? row.find('input[name*="_30p_"]').val() * 1 : 0);
|
||||
});
|
||||
|
||||
jQuery('div.row.behandeling_calc_summary div:nth-child(2)').text(total);
|
||||
jQuery('div.row.behandeling_calc_summary div:nth-child(3)').text(percentage);
|
||||
|
||||
let calc_message = '';
|
||||
let class_message = '';
|
||||
|
||||
if (percentage > (total * 0.3)) {
|
||||
calc_message = 'U heeft teveel afspraken geselecteerd voor het 30% scenario';
|
||||
class_message = 'alert-danger';
|
||||
ok = false;
|
||||
} else if ((total * 0.3) - percentage >= 1) {
|
||||
calc_message = 'U kunt meer afspraken toevoegen voor het 30% scenario';
|
||||
class_message = 'alert-warning';
|
||||
} else {
|
||||
calc_message = 'Dit klopt precies';
|
||||
class_message = 'alert-success';
|
||||
}
|
||||
jQuery('div.behandeling_calc_remarks div').removeClass('alert-danger alert-warning alert-success').addClass(class_message).text(calc_message);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
function validate_working_hours() {
|
||||
jQuery('div.form-group.werktijden').each(function(index,element){
|
||||
jQuery(element).find('select').removeClass('is-invalid');
|
||||
check_working_hours(element,true);
|
||||
jQuery(element).find('select').filter(function(){ let value = jQuery(this).val(); return !(value != null && value != '') }).addClass('is-invalid');
|
||||
})
|
||||
return jQuery('small.text-danger:visible').length == 0;
|
||||
}
|
||||
|
||||
function check_working_hours(html, showerror) {
|
||||
html = jQuery(html).parentsUntil('.werktijden').parent();
|
||||
html = jQuery(html[0]);
|
||||
|
||||
let day_start = html.find('select[name^="werkdag_start_afdeling_"]');
|
||||
let day_end = html.find('select[name^="werkdag_end_afdeling_"]');
|
||||
|
||||
let morning_break_start = html.find('select[name^="ochtend_pauze_start_afdeling_"]');
|
||||
let morning_break_end = html.find('select[name^="ochtend_pauze_end_afdeling_"]');
|
||||
|
||||
let lunch_start = html.find('select[name^="lunch_pauze_start_afdeling_"]');
|
||||
let lunch_end = html.find('select[name^="lunch_pauze_end_afdeling_"]');
|
||||
|
||||
let afternoon_break_start = html.find('select[name^="middag_pauze_start_afdeling_"]');
|
||||
let afternoon_break_end = html.find('select[name^="middag_pauze_end_afdeling_"]');
|
||||
|
||||
morning_break_start.find('option').each(function(index,element){
|
||||
if ('' !== element.value && element.value > 0) {
|
||||
// Only allow options that are between the day start and day end.
|
||||
let time = day_start.val();
|
||||
element.disabled = (time && element.value < day_start.val()) || (day_end.val() && element.value >= day_end.val());
|
||||
}
|
||||
});
|
||||
|
||||
morning_break_end.find('option').each(function(index,element){
|
||||
if ('' !== element.value && element.value > 0) {
|
||||
// Only allow options that are between the day start and day end.
|
||||
// Or when morning_break_start is selected and valid, add period time for end time selections
|
||||
let time = ('' != morning_break_start.val() ? morning_break_start.val() : day_start.val());
|
||||
element.disabled = (time && element.value <= time) || (day_end.val() && element.value > day_end.val());
|
||||
}
|
||||
});
|
||||
|
||||
lunch_start.find('option').each(function(index,element){
|
||||
if ('' !== element.value && element.value > 0) {
|
||||
// Only allow options that are between the day start and day end.
|
||||
// Or when morning_break_end is selected and valid, add period time for end time selections
|
||||
let time = ('' != morning_break_end.val() ? morning_break_end.val() : day_start.val());
|
||||
element.disabled = (time && element.value < time) || (day_end.val() && element.value >= day_end.val());
|
||||
}
|
||||
});
|
||||
|
||||
lunch_end.find('option').each(function(index,element){
|
||||
if ('' !== element.value && element.value > 0) {
|
||||
// Only allow options that are between the day start and day end.
|
||||
// Or when lunch_start is selected and valid, add period time for end time selections
|
||||
let time = ('' != lunch_start.val() ? lunch_start.val() : day_start.val()) * 1;
|
||||
element.disabled = (time && element.value <= time) || (day_end.val() && element.value > day_end.val());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
afternoon_break_start.find('option').each(function(index,element){
|
||||
if ('' !== element.value && element.value > 0) {
|
||||
// Only allow options that are between the day start and day end.
|
||||
// Or when lunch_end is selected and valid, add period time for end time selections
|
||||
let time = ('' != lunch_end.val() ? lunch_end.val() : day_start.val());
|
||||
element.disabled = (time && element.value < time) || (day_end.val() && element.value >= day_end.val());
|
||||
}
|
||||
});
|
||||
|
||||
afternoon_break_end.find('option').each(function(index,element){
|
||||
if ('' !== element.value && element.value > 0) {
|
||||
// Only allow options that are between the day start and day end.
|
||||
// Or when morning_break_start is selected and valid, add period time for end time selections
|
||||
let time = ('' != afternoon_break_start.val() ? afternoon_break_start.val() : day_start.val());
|
||||
element.disabled = (time && element.value <= time) || (day_end.val() && element.value > day_end.val());
|
||||
}
|
||||
});
|
||||
|
||||
if (showerror) {
|
||||
html.find('small.text-danger').toggle(day_start.val() == '' || day_start.val() == null ||
|
||||
day_end.val() == '' || day_end.val() == null ||
|
||||
morning_break_start.val() == '' || morning_break_start.val() == null ||
|
||||
morning_break_end.val() == '' || morning_break_end.val() == null ||
|
||||
lunch_start.val() == '' || lunch_start.val() == null ||
|
||||
lunch_end.val() == '' || lunch_end.val() == null ||
|
||||
afternoon_break_start.val() == '' || afternoon_break_start.val() == null ||
|
||||
afternoon_break_end.val() == '' || afternoon_break_end.val() == null);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
jQuery(function() {
|
||||
jQuery('a.add_specialisatie').on('click',function(event){
|
||||
event.preventDefault();
|
||||
addSpecialisatie();
|
||||
});
|
||||
|
||||
jQuery('div.poliekliniek_specialisatie input').off('change').on('change',function(){
|
||||
updateSpecialisatieValues();
|
||||
});
|
||||
|
||||
jQuery('a.add_behandelkamer').on('click',function(event){
|
||||
event.preventDefault();
|
||||
addBehandelkamer();
|
||||
});
|
||||
|
||||
jQuery('a.add_behandeling').on('click',function(event){
|
||||
event.preventDefault();
|
||||
addBehandeling();
|
||||
});
|
||||
|
||||
jQuery('div.form-group.werktijden select').off('change').on('change',function(event){
|
||||
check_working_hours(this);
|
||||
});
|
||||
|
||||
jQuery('input.behandeling_calc').off('change keyup').on('change keyup',function(event){
|
||||
calculateBehandelingen();
|
||||
});
|
||||
|
||||
jQuery('form').on('submit',function(event){
|
||||
//event.preventDefault();
|
||||
|
||||
if (validate_working_hours() &&
|
||||
calculateBehandelingen()) {
|
||||
|
||||
let formdata = new FormData(this);
|
||||
formdata.delete('csrfmiddlewaretoken');
|
||||
formdata.delete('json');
|
||||
|
||||
jQuery('input#id_json').val(JSON.stringify(Object.fromEntries(formdata)));
|
||||
|
||||
// alert('Alle velden zijn ok! Formulier wordt nu verder verwerkt.');
|
||||
console.log(event);
|
||||
return true;
|
||||
} else {
|
||||
alert('Er zijn wat problemen met het formulier. Controleer de invoer velden');
|
||||
|
||||
}
|
||||
return true;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
{% endblock %}
|
3
polyclinic_scheduling/apps/schedule/tests.py
Normal file
3
polyclinic_scheduling/apps/schedule/tests.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
9
polyclinic_scheduling/apps/schedule/urls.py
Normal file
9
polyclinic_scheduling/apps/schedule/urls.py
Normal file
@ -0,0 +1,9 @@
|
||||
from django.urls import path, include
|
||||
|
||||
from . import views
|
||||
|
||||
app_name = 'schedule'
|
||||
urlpatterns = [
|
||||
path('', views.ScheduleListView.as_view(), name='list'),
|
||||
path('new', views.new_or_update_study, name='new'),
|
||||
]
|
50
polyclinic_scheduling/apps/schedule/views.py
Normal file
50
polyclinic_scheduling/apps/schedule/views.py
Normal file
@ -0,0 +1,50 @@
|
||||
from django.shortcuts import render, redirect
|
||||
|
||||
from django.views.generic.list import ListView
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
||||
from .models import Schedule
|
||||
from .forms import ScheduleForm
|
||||
|
||||
import json
|
||||
|
||||
# Create your views here.
|
||||
class ScheduleListView(LoginRequiredMixin,ListView):
|
||||
|
||||
model = Schedule
|
||||
paginate_by = 10
|
||||
|
||||
def get_queryset(self):
|
||||
return Schedule.objects.filter(employee=self.request.user.employee).order_by('-created_at')
|
||||
|
||||
@login_required
|
||||
def new_or_update_study(request, schedule = None):
|
||||
template_name = 'schedule/schedule_new.html'
|
||||
|
||||
if request.method == 'POST':
|
||||
schedule_form = ScheduleForm(request.POST)
|
||||
|
||||
if schedule_form.is_valid():
|
||||
new_schedule = Schedule()
|
||||
|
||||
try:
|
||||
new_schedule.planning_source = json.loads(schedule_form.cleaned_data['json'])
|
||||
except json.JSONDecodeError as ex:
|
||||
# For now, sorry, ignore
|
||||
pass
|
||||
|
||||
new_schedule.employee = request.user.employee
|
||||
new_schedule.name = schedule_form.cleaned_data['name']
|
||||
new_schedule.email = schedule_form.cleaned_data['email']
|
||||
|
||||
new_schedule.save()
|
||||
|
||||
return redirect('schedule:list')
|
||||
|
||||
else:
|
||||
schedule_form = ScheduleForm()
|
||||
|
||||
return render(request, template_name, {
|
||||
'form' : schedule_form,
|
||||
})
|
Reference in New Issue
Block a user