From e1d9f1ecadfc93d169e0c6415a6d818d956d90fd Mon Sep 17 00:00:00 2001 From: Ross Date: Tue, 12 Dec 2023 21:57:11 +0000 Subject: [PATCH] start building rota functions into site --- rota/__init__.py | 0 rota/admin.py | 12 +++ rota/apps.py | 6 ++ rota/forms.py | 22 +++++ rota/migrations/0001_initial.py | 82 +++++++++++++++++++ ...2_rename_userrotadetails_userrotadetail.py | 20 +++++ rota/migrations/__init__.py | 0 rota/models.py | 80 ++++++++++++++++++ rota/tests.py | 3 + rota/urls.py | 12 +++ rota/views.py | 11 +++ 11 files changed, 248 insertions(+) create mode 100644 rota/__init__.py create mode 100644 rota/admin.py create mode 100644 rota/apps.py create mode 100644 rota/forms.py create mode 100644 rota/migrations/0001_initial.py create mode 100644 rota/migrations/0002_rename_userrotadetails_userrotadetail.py create mode 100644 rota/migrations/__init__.py create mode 100644 rota/models.py create mode 100644 rota/tests.py create mode 100644 rota/urls.py create mode 100644 rota/views.py diff --git a/rota/__init__.py b/rota/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/rota/admin.py b/rota/admin.py new file mode 100644 index 00000000..7668caa7 --- /dev/null +++ b/rota/admin.py @@ -0,0 +1,12 @@ +from django.contrib import admin + +# Register your models here. + +from rota.models import LeaveRequest, MultiLeaveRequest, OutOfProgrameEvent, Rota, RotaRotation, UserRotaDetail + +admin.site.register(LeaveRequest) +admin.site.register(MultiLeaveRequest) +admin.site.register(OutOfProgrameEvent) +admin.site.register(Rota) +admin.site.register(RotaRotation) +admin.site.register(UserRotaDetail) \ No newline at end of file diff --git a/rota/apps.py b/rota/apps.py new file mode 100644 index 00000000..8fe22c17 --- /dev/null +++ b/rota/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class RotaConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "rota" diff --git a/rota/forms.py b/rota/forms.py new file mode 100644 index 00000000..28e8e1b6 --- /dev/null +++ b/rota/forms.py @@ -0,0 +1,22 @@ + +from django.forms import ( + Form, + ModelForm, + ModelMultipleChoiceField, + ModelChoiceField, + ChoiceField, + CharField, + HiddenInput, + EmailField, + IntegerField, +) +from django.forms import inlineformset_factory +from atlas.models import CaseCollection +from django.contrib.auth.models import User + +from rota.models import UserRotaDetail + +class UserRotaDetailForm(ModelForm): + class Meta: + model = UserRotaDetail + exclude = ("",) \ No newline at end of file diff --git a/rota/migrations/0001_initial.py b/rota/migrations/0001_initial.py new file mode 100644 index 00000000..143fd2fe --- /dev/null +++ b/rota/migrations/0001_initial.py @@ -0,0 +1,82 @@ +# Generated by Django 4.1.4 on 2023-12-12 14:22 + +from django.conf import settings +import django.contrib.postgres.fields.ranges +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('generic', '0009_modality_short_code_alter_modality_modality'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='RotaRotation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(help_text='Name of the rotation', max_length=100)), + ], + ), + migrations.CreateModel( + name='UserRotaDetails', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('end_date', models.DateField(blank=True, help_text='The date the user should be roted up until, for example their CCT date', null=True)), + ('start_date', models.DateField(blank=True, help_text='The date the user should be roted from, for example if they join part way through a rota cycle', null=True)), + ('full_time_equivalence', models.IntegerField(default=100, help_text='Percentage of FTE, 100 = Full Time', validators=[django.core.validators.MaxValueValidator(100), django.core.validators.MinValueValidator(0)])), + ('nwd_monday', models.BooleanField(default=False)), + ('nwd_tuesday', models.BooleanField(default=False)), + ('nwd_wednesday', models.BooleanField(default=False)), + ('nwd_thursday', models.BooleanField(default=False)), + ('nwd_friday', models.BooleanField(default=False)), + ('proc_site', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='generic.site')), + ('rotation', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='rota.rotarotation')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='Rota', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('start_date', models.DateField(help_text='The rota start date')), + ('weeks_to_rota', models.IntegerField(default=26, help_text='The number of (whole) weeks the rota cycle runs for')), + ('rotations', models.ManyToManyField(help_text='The rotations that are in the rota', to='rota.rotarotation')), + ], + ), + migrations.CreateModel( + name='OutOfProgrameEvent', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date_range', django.contrib.postgres.fields.ranges.DateRangeField(help_text='The range of the out of programe event')), + ('end_date', models.DateField()), + ('reason', models.CharField(max_length=255)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='MultiLeaveRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date_range', django.contrib.postgres.fields.ranges.DateRangeField(help_text='The range of the leave request')), + ('reason', models.CharField(max_length=255)), + ('users', models.ManyToManyField(to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='LeaveRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date_range', django.contrib.postgres.fields.ranges.DateRangeField(help_text='The range of the leave request')), + ('status', models.CharField(choices=[('UNDECIDED', 'Undecided'), ('REJECTED', 'Rejected'), ('ACCEPTED', 'Accepted')], default='UNDECIDED', max_length=10)), + ('reason', models.CharField(max_length=255)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/rota/migrations/0002_rename_userrotadetails_userrotadetail.py b/rota/migrations/0002_rename_userrotadetails_userrotadetail.py new file mode 100644 index 00000000..708b9047 --- /dev/null +++ b/rota/migrations/0002_rename_userrotadetails_userrotadetail.py @@ -0,0 +1,20 @@ +# Generated by Django 4.1.4 on 2023-12-12 14:26 + +from django.conf import settings +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('generic', '0009_modality_short_code_alter_modality_modality'), + ('rota', '0001_initial'), + ] + + operations = [ + migrations.RenameModel( + old_name='UserRotaDetails', + new_name='UserRotaDetail', + ), + ] diff --git a/rota/migrations/__init__.py b/rota/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/rota/models.py b/rota/models.py new file mode 100644 index 00000000..49c5cf91 --- /dev/null +++ b/rota/models.py @@ -0,0 +1,80 @@ +from django.db import models + +# Create your models here. +from django.contrib.postgres.fields import DateRangeField +from django.conf import settings + +from generic.models import Site +from django.core.validators import MaxValueValidator, MinValueValidator + +class OutOfProgrameEvent(models.Model): + date_range = DateRangeField(help_text="The range of the out of programe event") + end_date = models.DateField() + reason = models.CharField(max_length=255) + + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + +class LeaveRequest(models.Model): + date_range = DateRangeField(help_text="The range of the leave request") + + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + + LEAVE_STATUS = ( + ("UNDECIDED", "Undecided"), + ("REJECTED", "Rejected" ), + ("ACCEPTED", "Accepted" ) + ) + + status = models.CharField(max_length=10, choices=LEAVE_STATUS, default="UNDECIDED") + + reason = models.CharField(max_length=255) + + def __str__(self) -> str: + return f"{self.date_range} / {self.reason} / {self.status}" + +class MultiLeaveRequest(models.Model): + date_range = DateRangeField(help_text="The range of the leave request") + + users = models.ManyToManyField(settings.AUTH_USER_MODEL) + + reason = models.CharField(max_length=255) + + def __str__(self) -> str: + return f"{self.date_range} / {self.reason}" + +class RotaRotation(models.Model): + name = models.CharField(max_length=100, help_text="Name of the rotation") + + def __str__(self): + return self.name + + +class Rota(models.Model): + start_date = models.DateField(help_text="The rota start date") + weeks_to_rota = models.IntegerField(default=26, help_text="The number of (whole) weeks the rota cycle runs for") + + rotations = models.ManyToManyField(RotaRotation, help_text="The rotations that are in the rota") + + def __str__(self): + return f"{self.start_date} : {self.weeks_to_rota} weeks" + + +class UserRotaDetail(models.Model): + user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + + rotation = models.ForeignKey(RotaRotation, on_delete=models.SET_NULL, null=True) + + proc_site = models.ForeignKey(Site, on_delete=models.SET_NULL, null=True) + + end_date = models.DateField(blank=True, null=True, help_text="The date the user should be roted up until, for example their CCT date") + start_date = models.DateField(blank=True, null=True, help_text="The date the user should be roted from, for example if they join part way through a rota cycle") + + full_time_equivalence = models.IntegerField(default=100, validators=[MaxValueValidator(100), MinValueValidator(0)], help_text="Percentage of FTE, 100 = Full Time") + + nwd_monday = models.BooleanField(default=False) + nwd_tuesday = models.BooleanField(default=False) + nwd_wednesday = models.BooleanField(default=False) + nwd_thursday = models.BooleanField(default=False) + nwd_friday = models.BooleanField(default=False) + + diff --git a/rota/tests.py b/rota/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/rota/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/rota/urls.py b/rota/urls.py new file mode 100644 index 00000000..196a1fef --- /dev/null +++ b/rota/urls.py @@ -0,0 +1,12 @@ + +from django.urls import path, include + +from . import views + + +app_name = "rota" +urlpatterns = [ + path( + "rota/user_details/