From f63722f12550973b130700597749b6eaff790545 Mon Sep 17 00:00:00 2001 From: ankitamk14 Date: Wed, 1 May 2024 16:59:57 +0530 Subject: [PATCH 1/2] modified models --- SchoolInterface/settings.py | 1 + accounts/migrations/0001_initial.py | 1260 +++++++++++++++-- ...lter_classcoordinator_classval_and_more.py | 23 - .../migrations/0002_auto_20240501_1530.py | 39 + .../migrations/0003_auto_20240501_1530.py | 59 + .../0003_messagetype_message_condition.py | 48 - ...ation_pincode_alter_user_email_and_more.py | 29 - accounts/models.py | 265 ++-- spoken/__init__.py | 0 spoken/admin.py | 3 + spoken/apps.py | 6 + spoken/migrations/0001_initial.py | 165 +++ spoken/migrations/__init__.py | 0 spoken/models.py | 28 + spoken/tests.py | 3 + spoken/views.py | 3 + 16 files changed, 1600 insertions(+), 332 deletions(-) delete mode 100644 accounts/migrations/0002_alter_classcoordinator_classval_and_more.py create mode 100644 accounts/migrations/0002_auto_20240501_1530.py create mode 100644 accounts/migrations/0003_auto_20240501_1530.py delete mode 100644 accounts/migrations/0003_messagetype_message_condition.py delete mode 100644 accounts/migrations/0004_alter_location_pincode_alter_user_email_and_more.py create mode 100644 spoken/__init__.py create mode 100644 spoken/admin.py create mode 100644 spoken/apps.py create mode 100644 spoken/migrations/0001_initial.py create mode 100644 spoken/migrations/__init__.py create mode 100644 spoken/models.py create mode 100644 spoken/tests.py create mode 100644 spoken/views.py diff --git a/SchoolInterface/settings.py b/SchoolInterface/settings.py index d2ab73e..cbc2ff5 100644 --- a/SchoolInterface/settings.py +++ b/SchoolInterface/settings.py @@ -46,6 +46,7 @@ 'rest_framework', 'corsheaders', 'rest_framework_simplejwt.token_blacklist', + 'spoken', ] MIDDLEWARE = [ diff --git a/accounts/migrations/0001_initial.py b/accounts/migrations/0001_initial.py index f6420ba..aa41be9 100644 --- a/accounts/migrations/0001_initial.py +++ b/accounts/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.1 on 2023-05-25 12:14 +# Generated by Django 4.2.1 on 2024-05-01 09:59 from django.conf import settings import django.contrib.auth.models @@ -10,225 +10,1195 @@ class Migration(migrations.Migration): - initial = True dependencies = [ - ('auth', '0012_alter_user_first_name_max_length'), - ('common', '0001_initial'), + ("auth", "0012_alter_user_first_name_max_length"), + ("common", "0001_initial"), ] operations = [ migrations.CreateModel( - name='User', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('password', models.CharField(max_length=128, verbose_name='password')), - ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), - ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), - ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), - ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), - ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), - ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), - ('email', models.EmailField(blank=True, max_length=254, null=True, unique=True)), - ('first_name', models.CharField(max_length=150, verbose_name='first name')), - ('last_name', models.CharField(max_length=150, verbose_name='last name')), - ('phone', models.CharField(max_length=20, validators=[django.core.validators.RegexValidator(message='Enter a valid phone/mobile number', regex='^\\+?[0-9]+-?[0-9]{6,}$')])), - ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), - ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), + name="User", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("password", models.CharField(max_length=128, verbose_name="password")), + ( + "last_login", + models.DateTimeField( + blank=True, null=True, verbose_name="last login" + ), + ), + ( + "is_superuser", + models.BooleanField( + default=False, + help_text="Designates that this user has all permissions without explicitly assigning them.", + verbose_name="superuser status", + ), + ), + ( + "username", + models.CharField( + error_messages={ + "unique": "A user with that username already exists." + }, + help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.", + max_length=150, + unique=True, + validators=[ + django.contrib.auth.validators.UnicodeUsernameValidator() + ], + verbose_name="username", + ), + ), + ( + "is_staff", + models.BooleanField( + default=False, + help_text="Designates whether the user can log into this admin site.", + verbose_name="staff status", + ), + ), + ( + "is_active", + models.BooleanField( + default=True, + help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.", + verbose_name="active", + ), + ), + ( + "date_joined", + models.DateTimeField( + default=django.utils.timezone.now, verbose_name="date joined" + ), + ), + ("email", models.EmailField(max_length=254, null=True, unique=True)), + ( + "first_name", + models.CharField(max_length=150, verbose_name="first name"), + ), + ( + "last_name", + models.CharField(max_length=150, verbose_name="last name"), + ), + ( + "phone", + models.CharField( + max_length=20, + null=True, + validators=[ + django.core.validators.RegexValidator( + message="Enter a valid mobile number", + regex="[1-9][0-9]{10}$", + ) + ], + ), + ), + ( + "groups", + models.ManyToManyField( + blank=True, + help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", + related_name="user_set", + related_query_name="user", + to="auth.group", + verbose_name="groups", + ), + ), + ( + "user_permissions", + models.ManyToManyField( + blank=True, + help_text="Specific permissions for this user.", + related_name="user_set", + related_query_name="user", + to="auth.permission", + verbose_name="user permissions", + ), + ), ], options={ - 'verbose_name': 'user', - 'verbose_name_plural': 'users', - 'abstract': False, + "verbose_name": "user", + "verbose_name_plural": "users", + "abstract": False, }, managers=[ - ('objects', django.contrib.auth.models.UserManager()), + ("objects", django.contrib.auth.models.UserManager()), ], ), migrations.CreateModel( - name='Location', + name="ClassName", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('address', models.TextField()), - ('pincode', models.CharField(max_length=6)), - ('updated', models.DateField(auto_now=True)), - ('city', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='common.city')), - ('district', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='common.district')), - ('state', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='common.state')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.IntegerField()), ], ), migrations.CreateModel( - name='Organisation', + name="Context", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name_of_association', models.CharField(max_length=200, unique=True)), - ('date_of_association', models.DateField()), - ('type', models.CharField(choices=[('Central Government', 'Central Government'), ('State Government', 'State Government'), ('Public Company', 'Public Company'), ('Private Company', 'Private Company'), ('NGO', 'NGO'), ('Foreign', 'Foreign')], max_length=100)), - ('updated', models.DateField(auto_now=True)), - ('is_active', models.BooleanField(default=True)), - ('added_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='associated_organisation', to=settings.AUTH_USER_MODEL)), - ('location', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='accounts.location')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=200)), ], - options={ - 'ordering': ['name_of_association', '-date_of_association'], - }, ), migrations.CreateModel( - name='Parent', + name="Group", fields=[ - ('user_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "name", + models.CharField(max_length=150, unique=True, verbose_name="name"), + ), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now=True)), + ( + "added_by", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), ], - options={ - 'ordering': ['first_name', 'last_name'], - }, - bases=('accounts.user',), - managers=[ - ('objects', django.contrib.auth.models.UserManager()), + ), + migrations.CreateModel( + name="Location", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("address", models.TextField()), + ( + "pincode", + models.CharField( + max_length=6, + validators=[ + django.core.validators.RegexValidator( + message="Enter a valid pincode", regex="^\\d{6}$" + ) + ], + ), + ), + ("updated", models.DateField(auto_now=True)), + ( + "city", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, to="common.city" + ), + ), + ( + "district", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="common.district", + ), + ), + ( + "state", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, to="common.state" + ), + ), + ], + ), + migrations.CreateModel( + name="MessageType", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "messagetype", + models.CharField( + choices=[ + ("Single Message", "Single Message"), + ("Bulk Message", "Bulk Message"), + ], + max_length=100, + ), + ), ], ), migrations.CreateModel( - name='School', + name="Organisation", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name_of_association', models.CharField(max_length=200, unique=True)), - ('date_of_association', models.DateField()), - ('type', models.CharField(choices=[('Central Government Funded', 'Central Government Funded'), ('State Government Funded', 'State Government Funded'), ('Public Company Funded', 'Public Company Funded'), ('Private Company Funded', 'Private Company Funded'), ('NGO Funded', 'NGO Funded'), ('Foreign Funded', 'Foreign Funded'), ('Self-Funded', 'Self-Funded')], max_length=100)), - ('updated', models.DateField(auto_now=True)), - ('is_active', models.BooleanField(default=True)), - ('added_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='school_added', to=settings.AUTH_USER_MODEL)), - ('location', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='accounts.location')), - ('organisation', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='accounts.organisation')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name_of_association", models.CharField(max_length=200, unique=True)), + ("date_of_association", models.DateField()), + ( + "status", + models.CharField( + choices=[ + ("pending_approval", "pending approval"), + ("active", "active"), + ("inactive", "inactive"), + ("rejected", "rejected"), + ], + default="pending_approval", + max_length=100, + ), + ), + ("created", models.DateField(auto_now_add=True)), + ("updated", models.DateField(auto_now=True)), + ( + "added_by", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="associated_organisation", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "approved_by", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "location", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.location", + ), + ), ], options={ - 'ordering': ['name_of_association', '-date_of_association'], + "ordering": ["name_of_association", "-date_of_association"], }, ), migrations.CreateModel( - name='Profile', + name="OrganisationType", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('dob', models.DateField(help_text='YYYY-MM-DD')), - ('gender', models.CharField(choices=[('M', 'Male'), ('F', 'Female'), ('O', 'Other'), ('NA', 'Not applicable')], max_length=2)), - ('updated', models.DateField(auto_now=True)), - ('location', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='accounts.location')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='profile_info', to=settings.AUTH_USER_MODEL)), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=200)), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now=True)), ], ), migrations.CreateModel( - name='Payment', + name="Parent", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('date_of_payment', models.DateField()), - ('amount', models.IntegerField()), - ('utr', models.CharField(max_length=200, unique=True)), - ('receipt', models.FileField(upload_to='receipts/')), - ('expiry_date', models.DateField()), - ('status', models.CharField(choices=[('IN_PROCESS', 'IN_PROCESS'), ('COMPLETED', 'COMPLETED')], max_length=50)), - ('added_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), - ('organisation', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='accounts.organisation')), - ('school', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='accounts.school')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "status", + models.CharField( + choices=[ + ("pending_approval", "pending approval"), + ("active", "active"), + ("inactive", "inactive"), + ("rejected", "rejected"), + ], + default="pending_approval", + max_length=100, + ), + ), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now_add=True)), + ( + "approved_by", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="approved_parent", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="user_parent", + to=settings.AUTH_USER_MODEL, + ), + ), ], - options={ - 'ordering': ['date_of_payment'], - }, ), migrations.CreateModel( - name='TrainingTeam', + name="Permission", fields=[ - ('user_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)), - ('profile', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='accounts.profile')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=255, verbose_name="name")), + ("codename", models.CharField(max_length=100, verbose_name="codename")), + ], + ), + migrations.CreateModel( + name="School", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name_of_association", models.CharField(max_length=200, unique=True)), + ("date_of_association", models.DateField()), + ("is_active", models.BooleanField(default=True)), + ( + "status", + models.CharField( + choices=[ + ("pending_approval", "pending approval"), + ("active", "active"), + ("inactive", "inactive"), + ("rejected", "rejected"), + ], + default="pending_approval", + max_length=100, + ), + ), + ("created", models.DateField(auto_now_add=True)), + ("updated", models.DateField(auto_now=True)), + ( + "added_by", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="school_added", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "approved_by", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "location", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.location", + ), + ), + ( + "organisation", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to="accounts.organisation", + ), + ), ], options={ - 'verbose_name': 'Training Team', - 'verbose_name_plural': 'Training Team', - 'ordering': ['first_name', 'last_name'], + "ordering": ["name_of_association", "-date_of_association"], }, - bases=('accounts.user',), - managers=[ - ('objects', django.contrib.auth.models.UserManager()), + ), + migrations.CreateModel( + name="SchoolType", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=200)), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now=True)), ], ), migrations.CreateModel( - name='Teacher', + name="Section", fields=[ - ('user_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)), - ('unique_id', models.CharField(max_length=50)), - ('profile', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='accounts.profile')), - ('school', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='accounts.school')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=50)), ], - options={ - 'ordering': ['first_name', 'last_name'], - }, - bases=('accounts.user',), - managers=[ - ('objects', django.contrib.auth.models.UserManager()), + ), + migrations.CreateModel( + name="UserGroup", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "status", + models.CharField( + choices=[ + ("pending_approval", "pending approval"), + ("active", "active"), + ("inactive", "inactive"), + ("rejected", "rejected"), + ], + default="pending_approval", + max_length=100, + ), + ), + ( + "approved_by", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "city", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="user_group", + to="common.city", + ), + ), + ( + "classname", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="user_group", + to="accounts.classname", + ), + ), + ( + "district", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="user_group", + to="common.district", + ), + ), + ( + "group", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, to="accounts.group" + ), + ), + ( + "organisation", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="user_group", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "school", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="user_group", + to="accounts.school", + ), + ), + ( + "section", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="user_group", + to="accounts.section", + ), + ), + ( + "state", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="user_group", + to="common.state", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="user_groups", + to=settings.AUTH_USER_MODEL, + ), + ), ], ), migrations.CreateModel( - name='Student', + name="Teacher", fields=[ - ('user_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)), - ('unique_id', models.CharField(max_length=50)), - ('current_class', models.IntegerField(choices=[(1, 'Class 1'), (2, 'Class 2'), (3, 'Class 3'), (4, 'Class 4'), (5, 'Class 5'), (6, 'Class 6'), (7, 'Class 7'), (8, 'Class 8'), (9, 'Class 9'), (10, 'Class 10')])), - ('division', models.CharField(max_length=50)), - ('_parent', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='children', to='accounts.parent')), - ('_teacher', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='students', to='accounts.teacher')), - ('preferred_lang', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='common.language')), - ('profile', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='accounts.profile')), - ('school', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='accounts.school')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("unique_id", models.CharField(max_length=50)), + ( + "status", + models.CharField( + choices=[ + ("pending_approval", "pending approval"), + ("active", "active"), + ("inactive", "inactive"), + ("rejected", "rejected"), + ], + default="pending_approval", + max_length=100, + ), + ), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now_add=True)), + ( + "approved_by", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="approved_teachers", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "school", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.school", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="teacher_user", + to=settings.AUTH_USER_MODEL, + ), + ), ], - options={ - 'ordering': ['first_name', 'last_name'], - }, - bases=('accounts.user',), - managers=[ - ('objects', django.contrib.auth.models.UserManager()), + ), + migrations.CreateModel( + name="Student", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("unique_id", models.CharField(max_length=100)), + ( + "current_class", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.classname", + ), + ), + ( + "division", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.section", + ), + ), + ( + "parent", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + related_name="children", + to="accounts.parent", + ), + ), + ( + "preferred_lang", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="common.language", + ), + ), + ( + "school", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.school", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), ], ), migrations.CreateModel( - name='SchoolCoordinator', + name="SchoolCoordinator", fields=[ - ('user_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)), - ('profile', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='accounts.profile')), - ('school', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='accounts.school')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "status", + models.CharField( + choices=[ + ("pending_approval", "pending approval"), + ("active", "active"), + ("inactive", "inactive"), + ("rejected", "rejected"), + ], + default="pending_approval", + max_length=100, + ), + ), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now_add=True)), + ( + "approved_by", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "school", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.school", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="school_coordinator", + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ - 'verbose_name': 'School Coordinator', - 'verbose_name_plural': 'School Coordinators', - 'ordering': ['first_name', 'last_name'], + "verbose_name": "School Coordinator", + "verbose_name_plural": "School Coordinators", }, - bases=('accounts.user',), - managers=[ - ('objects', django.contrib.auth.models.UserManager()), + ), + migrations.AddField( + model_name="school", + name="type", + field=models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, to="accounts.schooltype" + ), + ), + migrations.CreateModel( + name="Profile", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("dob", models.DateField(help_text="YYYY-MM-DD")), + ( + "gender", + models.CharField( + choices=[("M", "Male"), ("F", "Female"), ("O", "Other")], + max_length=2, + ), + ), + ("updated", models.DateField(auto_now=True)), + ( + "location", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.location", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="profile_info", + to=settings.AUTH_USER_MODEL, + ), + ), ], ), migrations.CreateModel( - name='ClassCoordinator', + name="Payment", fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('classVal', models.IntegerField(choices=[(1, 'Class 1'), (2, 'Class 2'), (3, 'Class 3'), (4, 'Class 4'), (5, 'Class 5'), (6, 'Class 6'), (7, 'Class 7'), (8, 'Class 8'), (9, 'Class 9'), (10, 'Class 10')])), - ('teacher', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='accounts.teacher')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("date_of_payment", models.DateField()), + ("amount", models.IntegerField()), + ("utr", models.CharField(max_length=200, unique=True)), + ("receipt", models.FileField(upload_to="receipts/")), + ("expiry_date", models.DateField()), + ( + "status", + models.CharField( + choices=[ + ("IN_PROCESS", "IN_PROCESS"), + ("COMPLETED", "COMPLETED"), + ], + max_length=50, + ), + ), + ( + "added_by", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "organisation", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.organisation", + ), + ), + ( + "school", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.school", + ), + ), ], options={ - 'ordering': ['teacher__first_name', 'teacher__last_name'], + "ordering": ["date_of_payment"], }, ), migrations.CreateModel( - name='CentralCoordinator', + name="OrganisationCoordinator", fields=[ - ('user_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)), - ('organisation', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='accounts.organisation')), - ('profile', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='accounts.profile')), + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "status", + models.CharField( + choices=[ + ("pending_approval", "pending approval"), + ("active", "active"), + ("inactive", "inactive"), + ("rejected", "rejected"), + ], + default="pending_approval", + max_length=100, + ), + ), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now_add=True)), + ( + "approved_by", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "organisation", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.organisation", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="org_coordinator", + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ - 'verbose_name': 'Central Coordinator', - 'verbose_name_plural': 'Central Coordinators', - 'ordering': ['first_name', 'last_name'], + "verbose_name": "Organisation Coordinator", + "verbose_name_plural": "Organisation Coordinators", }, - bases=('accounts.user',), - managers=[ - ('objects', django.contrib.auth.models.UserManager()), + ), + migrations.AddField( + model_name="organisation", + name="type", + field=models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.organisationtype", + ), + ), + migrations.CreateModel( + name="Message", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("message", models.CharField(max_length=500)), + ( + "message_type", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="message_type", + to="accounts.messagetype", + ), + ), + ( + "receiver", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="received_messages", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "receiver_role", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="receiver_role", + to="accounts.group", + ), + ), + ( + "sender", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="sent_messages", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "sender_role", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="sender_role", + to="accounts.group", + ), + ), + ], + ), + migrations.CreateModel( + name="GroupPermissions", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now=True)), + ( + "added_by", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "group", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, to="accounts.group" + ), + ), + ( + "permission", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.permission", + ), + ), + ], + ), + migrations.CreateModel( + name="ClassTeacher", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "status", + models.CharField( + choices=[ + ("pending_approval", "pending approval"), + ("active", "active"), + ("inactive", "inactive"), + ("rejected", "rejected"), + ], + default="pending_approval", + max_length=100, + ), + ), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now_add=True)), + ( + "approved_by", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "class_value", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.classname", + ), + ), + ( + "school", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.school", + ), + ), + ( + "section", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.section", + ), + ), + ( + "teacher", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="class_teacher", + to="accounts.teacher", + ), + ), + ], + ), + migrations.CreateModel( + name="ClassCoordinator", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "status", + models.CharField( + choices=[ + ("pending_approval", "pending approval"), + ("active", "active"), + ("inactive", "inactive"), + ("rejected", "rejected"), + ], + max_length=100, + ), + ), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now_add=True)), + ( + "approved_by", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "class_value", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.classname", + ), + ), + ( + "school", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.school", + ), + ), + ( + "section", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="accounts.section", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="class_coordinator", + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + migrations.CreateModel( + name="Condition", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("single_msg", models.BooleanField(default=False)), + ("bulk_msg", models.BooleanField(default=False)), + ( + "receiver", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="receiver", + to="accounts.group", + ), + ), + ( + "sender", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="sender", + to="accounts.group", + ), + ), ], + options={ + "unique_together": {("sender", "receiver")}, + }, ), ] diff --git a/accounts/migrations/0002_alter_classcoordinator_classval_and_more.py b/accounts/migrations/0002_alter_classcoordinator_classval_and_more.py deleted file mode 100644 index d76b9e2..0000000 --- a/accounts/migrations/0002_alter_classcoordinator_classval_and_more.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 4.2.1 on 2023-06-20 05:37 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='classcoordinator', - name='classVal', - field=models.IntegerField(choices=[(1, 'Class 1'), (2, 'Class 2'), (3, 'Class 3'), (4, 'Class 4'), (5, 'Class 5'), (6, 'Class 6'), (7, 'Class 7'), (8, 'Class 8'), (9, 'Class 9'), (10, 'Class 10'), (11, 'Class 11'), (12, 'Class 12')]), - ), - migrations.AlterField( - model_name='student', - name='current_class', - field=models.IntegerField(choices=[(1, 'Class 1'), (2, 'Class 2'), (3, 'Class 3'), (4, 'Class 4'), (5, 'Class 5'), (6, 'Class 6'), (7, 'Class 7'), (8, 'Class 8'), (9, 'Class 9'), (10, 'Class 10'), (11, 'Class 11'), (12, 'Class 12')]), - ), - ] diff --git a/accounts/migrations/0002_auto_20240501_1530.py b/accounts/migrations/0002_auto_20240501_1530.py new file mode 100644 index 0000000..7c016a2 --- /dev/null +++ b/accounts/migrations/0002_auto_20240501_1530.py @@ -0,0 +1,39 @@ +# Generated by Django 4.2.1 on 2024-05-01 07:44 + +from django.db import migrations + +def populate_classes(apps, schema_editor): + MAX_CLASS = 12 + CLASS_CHOICES = [i for i in range(1,MAX_CLASS+1)] + ClassName = apps.get_model('accounts', 'ClassName') + for val in CLASS_CHOICES: + ClassName.objects.create(name=val) + +def populate_organisation_type(apps, schema_editor): + ORGANISATION_TYPE = [ 'Central Government', 'State Government', 'Public Company', 'Private Company', 'NGO', 'Foreign' ] + OrganisationType = apps.get_model('accounts', 'OrganisationType') + for type in ORGANISATION_TYPE: + OrganisationType.objects.create(name=type) + +def populate_school_type(apps, schema_editor): + SCHOOL_TYPE = [ 'Central Government Funded', 'State Government Funded', + 'Public Company Funded', 'Private Company Funded', 'NGO Funded', 'Foreign Funded', 'Self-Funded'] + SchoolType = apps.get_model('accounts', 'SchoolType') + for type in SCHOOL_TYPE: + SchoolType.objects.create(name=type) + +def populated_context(apps, schema_editor): + CONTEXTS = [ + 'organisation', 'state', 'district', 'city', 'school', 'class', 'section' + ] + Context = apps.get_model('accounts', 'Context') + for val in CONTEXTS: + Context.objects.create(name = val) + +class Migration(migrations.Migration): + dependencies = [ + ("accounts", "0001_initial"), + ] + + operations = [migrations.RunPython(populate_classes), migrations.RunPython(populate_organisation_type), + migrations.RunPython(populate_school_type)] diff --git a/accounts/migrations/0003_auto_20240501_1530.py b/accounts/migrations/0003_auto_20240501_1530.py new file mode 100644 index 0000000..e022335 --- /dev/null +++ b/accounts/migrations/0003_auto_20240501_1530.py @@ -0,0 +1,59 @@ +# Generated by Django 4.2.1 on 2024-05-01 10:00 + +from django.db import migrations + +def populate_permissions(apps, schema_editor): + PERMISSIONS = [ + #Training - Students + ('can add student training', 'can_add_student_training'), + ('can edit student training', 'can_edit_student_training'), + ('can view student training', 'can_view_student_training'), + ('can delete student training', 'can_delete_student_training'), + ('can approve student training', 'can_approve_student_training'), + + #Test - Students + ('can add student test', 'can_add_student_test'), + ('can edit student test', 'can_edit_student_test'), + ('can view student test', 'can_view_student_test'), + ('can delete student test', 'can_delete_student_test'), + ('can approve student test', 'can_approve_student_test'), + + #Role Assignment + ('can assign role', 'can_assign_role'), + + #Reports + ('can view organization report', 'can_view_organization_report'), + ('can view state report', 'can_view_state_report'), + ('can view district report', 'can_view_district_report'), + ('can view city report', 'can_view_city_report'), + ('can view school report', 'can_view_school_report'), + + #Bulk School Registration + ('allow bulk school registration', 'allow_bulk_school_registration'), + + #Training - Teachers + ('can add teacher training', 'can_add_teacher_training'), + ('can edit teacher training', 'can_edit_teacher_training'), + ('can view teacher training', 'can_view_teacher_training'), + ('can delete teacher training', 'can_delete_teacher_training'), + ('can approve teacher training', 'can_approve_teacher_training'), + + #Test - Teachers + ('can add teacher test', 'can_add_teacher_test'), + ('can edit teacher test', 'can_edit_teacher_test'), + ('can view teacher test', 'can_view_teacher_test'), + ('can delete teacher test', 'can_delete_teacher_test'), + ('can approve teacher test', 'can_approve_teacher_test'), + + ] + Permission = apps.get_model('accounts', 'Permission') + for name, codename in PERMISSIONS: + Permission.objects.create(name=name, codename=codename) + + +class Migration(migrations.Migration): + dependencies = [ + ("accounts", "0002_auto_20240501_1530"), + ] + + operations = [migrations.RunPython(populate_permissions)] diff --git a/accounts/migrations/0003_messagetype_message_condition.py b/accounts/migrations/0003_messagetype_message_condition.py deleted file mode 100644 index 8db6f79..0000000 --- a/accounts/migrations/0003_messagetype_message_condition.py +++ /dev/null @@ -1,48 +0,0 @@ -# Generated by Django 4.2.1 on 2023-06-23 11:57 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('auth', '0012_alter_user_first_name_max_length'), - ('accounts', '0002_alter_classcoordinator_classval_and_more'), - ] - - operations = [ - migrations.CreateModel( - name='MessageType', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('messagetype', models.CharField(choices=[('Single Message', 'Single Message'), ('Bulk Message', 'Bulk Message')], max_length=100)), - ], - ), - migrations.CreateModel( - name='Message', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('message', models.CharField(max_length=500)), - ('message_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='message_type', to='accounts.messagetype')), - ('receiver', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='received_messages', to=settings.AUTH_USER_MODEL)), - ('receiver_role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='receiver_role', to='auth.group')), - ('sender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sent_messages', to=settings.AUTH_USER_MODEL)), - ('sender_role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sender_role', to='auth.group')), - ], - ), - migrations.CreateModel( - name='Condition', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('single_msg', models.BooleanField(default=False)), - ('bulk_msg', models.BooleanField(default=False)), - ('receiver', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='receiver', to='auth.group')), - ('sender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sender', to='auth.group')), - ], - options={ - 'unique_together': {('sender', 'receiver')}, - }, - ), - ] diff --git a/accounts/migrations/0004_alter_location_pincode_alter_user_email_and_more.py b/accounts/migrations/0004_alter_location_pincode_alter_user_email_and_more.py deleted file mode 100644 index f8223b6..0000000 --- a/accounts/migrations/0004_alter_location_pincode_alter_user_email_and_more.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 4.2.1 on 2023-07-10 06:41 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0003_messagetype_message_condition'), - ] - - operations = [ - migrations.AlterField( - model_name='location', - name='pincode', - field=models.CharField(max_length=6, validators=[django.core.validators.RegexValidator(message='Enter a valid pincode', regex='^\\d{6}$')]), - ), - migrations.AlterField( - model_name='user', - name='email', - field=models.EmailField(max_length=254, null=True, unique=True), - ), - migrations.AlterField( - model_name='user', - name='phone', - field=models.CharField(max_length=20, null=True, validators=[django.core.validators.RegexValidator(message='Enter a valid phone/mobile number', regex='^(\\+[1-9][0-9]*-)?[1-9][0-9]{6,}$')]), - ), - ] diff --git a/accounts/models.py b/accounts/models.py index c0e78c0..a05ad09 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -2,24 +2,64 @@ from django.contrib.auth.models import AbstractUser from django.core.validators import RegexValidator from django.utils.translation import gettext_lazy as _ +from django.utils import timezone from django.contrib.auth.models import Group from common.models import State, District, City, Language -MAX_CLASS = 12 -CLASS_CHOICES = [(i, f"Class {i}") for i in range(1, MAX_CLASS+1)] - +APPROVAL_STATUS = [ + ('pending_approval', 'pending approval'), + ('active', 'active'), + ('inactive', 'inactive'), + ('rejected', 'rejected') + ] class User(AbstractUser): - phone_regex = RegexValidator(regex=r'^(\+[1-9][0-9]*-)?[1-9][0-9]{6,}$', - message='Enter a valid phone/mobile number') + """ + Custom user model extending Django's AbstractUser. + This custom user model retains the core functionality of Django's built-in user model + while adding specific constraints: + - Email is unique, ensuring each user has a distinct email address. + - First name and last name are required fields, ensuring non-null values. + """ + mobile_regex = RegexValidator(regex=r'[1-9][0-9]{10}$', + message='Enter a valid mobile number') email = models.EmailField(unique=True, null=True) first_name = models.CharField(_("first name"), max_length=150, blank=False, null=False) last_name = models.CharField(_("last name"), max_length=150, blank=False, null=False) - phone = models.CharField(max_length=20, null=True, validators=[phone_regex]) + phone = models.CharField(max_length=20, null=True, validators=[mobile_regex]) + +class Permission(models.Model): + """ + The permissions system provides a way to assign permissions to groups. + """ + name = models.CharField(_("name"), max_length=255) + codename = models.CharField(_("codename"), max_length=100) + +class Group(models.Model): + """ + Groups are a generic way of categorizing users to apply permissions, or + some other label, to those users. A user can belong to any number of + groups. A user in a group automatically has all the permissions granted to that + group. + """ + name = models.CharField(_("name"), max_length=150, unique=True) + added_by = models.ForeignKey(User, on_delete=models.PROTECT) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + +class GroupPermissions(models.Model): + """ + Model representing permissions associated with a group. + """ + group = models.ForeignKey(Group, on_delete=models.PROTECT) + permission = models.ForeignKey(Permission, on_delete=models.PROTECT) + added_by = models.ForeignKey(User, on_delete=models.PROTECT) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) class Location(models.Model): @@ -45,8 +85,7 @@ class Profile(models.Model): """ Profile information for users """ - GENDER_CHOICES = [('M', 'Male'), ('F', 'Female'), ('O', 'Other'), - ('NA', 'Not applicable')] # 'NA' in case of organisation & school + GENDER_CHOICES = [('M', 'Male'), ('F', 'Female'), ('O', 'Other')] user = models.ForeignKey(User, on_delete=models.PROTECT, related_name='profile_info') @@ -55,54 +94,52 @@ class Profile(models.Model): location = models.ForeignKey(Location, on_delete=models.PROTECT) updated = models.DateField(auto_now=True) +class OrganisationType(models.Model): + name = models.CharField(max_length=200) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) -class Organisation(models.Model): - ASSOCIATION_CHOICES = [ - ('Central Government', 'Central Government'), - ('State Government', 'State Government'), - ('Public Company', 'Public Company'), - ('Private Company', 'Private Company'), - ('NGO', 'NGO'), - ('Foreign', 'Foreign'), - ] +class Organisation(models.Model): added_by = models.ForeignKey(User, on_delete=models.PROTECT, related_name='associated_organisation') name_of_association = models.CharField(max_length=200, unique=True) date_of_association = models.DateField() - type = models.CharField(max_length=100, choices=ASSOCIATION_CHOICES) - updated = models.DateField(auto_now=True) - is_active = models.BooleanField(default=True) + type = models.ForeignKey(OrganisationType, on_delete=models.PROTECT) location = models.ForeignKey(Location, on_delete=models.PROTECT) - + status = models.CharField(choices=APPROVAL_STATUS, max_length=100, default="pending_approval") + approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True) + created = models.DateField(auto_now_add=True) + updated = models.DateField(auto_now=True) + + class Meta: ordering = ['name_of_association', '-date_of_association'] def __str__(self): return self.name_of_association +class SchoolType(models.Model): + name = models.CharField(max_length=200) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) class School(models.Model): - TYPE_CHOICES = [ - ('Central Government Funded', 'Central Government Funded'), - ('State Government Funded', 'State Government Funded'), - ('Public Company Funded', 'Public Company Funded'), - ('Private Company Funded', 'Private Company Funded'), - ('NGO Funded', 'NGO Funded'), - ('Foreign Funded', 'Foreign Funded'), - ('Self-Funded', 'Self-Funded'), - ] - added_by = models.ForeignKey(User, on_delete=models.PROTECT, related_name='school_added') name_of_association = models.CharField(max_length=200, unique=True) date_of_association = models.DateField() - type = models.CharField(max_length=100, choices=TYPE_CHOICES) + type = models.ForeignKey(SchoolType, on_delete=models.PROTECT) organisation = models.ForeignKey(Organisation, on_delete=models.PROTECT, null=True, blank=True) - updated = models.DateField(auto_now=True) + is_active = models.BooleanField(default=True) location = models.ForeignKey(Location, on_delete=models.PROTECT) + status = models.CharField(choices=APPROVAL_STATUS, max_length=100, default="pending_approval") + approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True) + created = models.DateField(auto_now_add=True) + updated = models.DateField(auto_now=True) + class Meta: ordering = ['name_of_association', '-date_of_association'] @@ -129,93 +166,147 @@ class Meta: def __str__(self): return f"{self.school.name_of_association} - {self.date_of_payment}" - -class TrainingTeam(User): - profile = models.ForeignKey(Profile, on_delete=models.PROTECT, null=True, blank=False) - - class Meta: - ordering = ['first_name', 'last_name'] - verbose_name = 'Training Team' - verbose_name_plural = 'Training Team' - - def __str__(self): - return f"{self.username}" - - -class CentralCoordinator(User): - profile = models.ForeignKey(Profile, on_delete=models.PROTECT, null=True, blank=False) +class OrganisationCoordinator(models.Model): + """ + An organisation coordinator is a user assigned to coordinate activities within a specific organisation. + Each coordinator is associated with a user account and an organisation. + """ + user = models.ForeignKey(User, on_delete=models.PROTECT, null=False, blank=False, related_name="org_coordinator") organisation = models.ForeignKey(Organisation, on_delete=models.PROTECT) + approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True) + status = models.CharField(choices=APPROVAL_STATUS, max_length=100, default="pending_approval") + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now_add=True) class Meta: - ordering = ['first_name', 'last_name'] - verbose_name = 'Central Coordinator' - verbose_name_plural = 'Central Coordinators' + verbose_name = 'Organisation Coordinator' + verbose_name_plural = 'Organisation Coordinators' def __str__(self): - return f"{self.username}" + return f"{self.user} - {self.organisation}" -class SchoolCoordinator(User): - profile = models.ForeignKey(Profile, on_delete=models.PROTECT, null=True, blank=False) +class SchoolCoordinator(models.Model): + """ + An school coordinator is a user assigned to coordinate activities within a specific school. + Each coordinator is associated with a user account and a school. + """ + user = models.ForeignKey(User, on_delete=models.PROTECT, null=False, blank=False, related_name="school_coordinator") school = models.ForeignKey(School, on_delete=models.PROTECT) + status = models.CharField(choices=APPROVAL_STATUS, max_length=100, default="pending_approval") + approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now_add=True) class Meta: - ordering = ['first_name', 'last_name'] verbose_name = 'School Coordinator' verbose_name_plural = 'School Coordinators' def __str__(self): - return f"{self.username}" + return f"{self.user} - {self.school}" -class Teacher(User): - profile = models.ForeignKey(Profile, on_delete=models.PROTECT, null=True, blank=False) + +class Teacher(models.Model): + user = models.ForeignKey(User, on_delete=models.PROTECT, null=False, blank=False, related_name="teacher_user") school = models.ForeignKey(School, on_delete=models.PROTECT) unique_id = models.CharField(max_length=50) - - class Meta: - ordering = ['first_name', 'last_name'] + status = models.CharField(choices=APPROVAL_STATUS, max_length=100, default="pending_approval") + approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True, related_name="approved_teachers") + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now_add=True) def __str__(self): - return f"{self.username}" + return f"{self.user}" -class Parent(User): +class Parent(models.Model): + user = models.ForeignKey(User, on_delete=models.PROTECT, null=False, blank=False, related_name="user_parent") + status = models.CharField(choices=APPROVAL_STATUS, max_length=100, default="pending_approval") + approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True, related_name="approved_parent") + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return f"{self.user}" - class Meta: - ordering = ['first_name', 'last_name'] +class ClassName(models.Model): + name = models.IntegerField() - def __str__(self): - return f"{self.username}" +class Section(models.Model): + name = models.CharField(max_length=50) -class Student(User): - profile = models.ForeignKey(Profile, on_delete=models.PROTECT, null=True, blank=False) +class ClassCoordinator(models.Model): + """ + An class coordinator is a user assigned to coordinate activities within a specific class & section. + Each coordinator is associated with a user account, school, class & section. + """ + user = models.ForeignKey(User, on_delete=models.PROTECT, related_name="class_coordinator") + school = models.ForeignKey(School, on_delete=models.PROTECT) + class_value = models.ForeignKey(ClassName, on_delete=models.PROTECT) + section = models.ForeignKey(Section, on_delete=models.PROTECT) + status = models.CharField(choices=APPROVAL_STATUS, max_length=100) + approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now_add=True) + +class Student(models.Model): + user = models.ForeignKey(User, on_delete=models.PROTECT, null=False, blank=False) school = models.ForeignKey(School, on_delete=models.PROTECT) - unique_id = models.CharField(max_length=50) # Enrolment ID / Any other unique ID + unique_id = models.CharField(max_length=100) # Enrolment ID / Any other unique ID preferred_lang = models.ForeignKey(Language, on_delete=models.PROTECT) - current_class = models.IntegerField(choices=CLASS_CHOICES) - division = models.CharField(max_length=50) - _teacher = models.ForeignKey(Teacher, on_delete=models.PROTECT, related_name='students') - _parent = models.ForeignKey(Parent, on_delete=models.PROTECT, related_name='children') - - class Meta: - ordering = ['first_name', 'last_name'] + current_class = models.ForeignKey(ClassName, on_delete=models.PROTECT) + division = models.ForeignKey(Section, on_delete=models.PROTECT) + parent = models.ForeignKey(Parent, on_delete=models.PROTECT, related_name='children', null=True, blank=True) def __str__(self): return f"{self.username} - {self.school.name_of_association}" +class ClassTeacher(models.Model): + """ + This model provides mapping of a teacher for a school, class & section. + """ + teacher = models.ForeignKey(Teacher, on_delete=models.PROTECT, related_name="class_teacher") + school = models.ForeignKey(School, on_delete=models.PROTECT) + class_value = models.ForeignKey(ClassName, on_delete=models.PROTECT) + section = models.ForeignKey(Section, on_delete=models.PROTECT) + status = models.CharField(choices=APPROVAL_STATUS, max_length=100, default="pending_approval") + approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now_add=True) + +class Context(models.Model): + """ + Defines the context or level for the group to operate on. + For example, the organisation coordinator with context of 'organisation' + will have access to resources and activities at the organization level, + allowing them to manage and oversee operations within + a specific organization. + """ + name = models.CharField(max_length=200) -class ClassCoordinator(models.Model): - teacher = models.ForeignKey(Teacher, on_delete=models.PROTECT) - classVal = models.IntegerField(choices=CLASS_CHOICES) - - class Meta: - ordering = ['teacher__first_name', 'teacher__last_name'] - - def __str__(self): - return f"{self.teacher.username} - {self.classVal}" - +class UserGroup(models.Model): + """ + This model stores mappings between users and groups for dynamic roles exclusively. + It contains information regarding the contextual resource ID associated with the group. + For example, if the training team creates a role such as 'School Test Reporter' with the school context, + this table will record the user assigned to this group and the corresponding + school ID in the 'school' column. + When the value is set to 0 in a context column, it signifies access to all resources within that context. + For instance, a school value of 0 indicates that the user has access to test reports of all schools. + """ + user = models.ForeignKey(User, on_delete=models.PROTECT, related_name="user_groups") + group = models.ForeignKey(Group, on_delete=models.PROTECT) + organisation = models.ForeignKey(User, on_delete=models.PROTECT, related_name="user_group") + state = models.ForeignKey(State, on_delete=models.PROTECT, related_name="user_group") + district = models.ForeignKey(District, on_delete=models.PROTECT, related_name="user_group") + city = models.ForeignKey(City, on_delete=models.PROTECT, related_name="user_group") + school = models.ForeignKey(School, on_delete=models.PROTECT, related_name="user_group") + classname = models.ForeignKey(ClassName, on_delete=models.PROTECT, related_name="user_group") + section = models.ForeignKey(Section, on_delete=models.PROTECT, related_name="user_group") + status = models.CharField(choices=APPROVAL_STATUS, max_length=100, default="pending_approval") + approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True) class Condition(models.Model): sender = models.ForeignKey(Group, on_delete=models.CASCADE, related_name='sender') diff --git a/spoken/__init__.py b/spoken/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/spoken/admin.py b/spoken/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/spoken/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/spoken/apps.py b/spoken/apps.py new file mode 100644 index 0000000..de1bdaf --- /dev/null +++ b/spoken/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class SpokenConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "spoken" diff --git a/spoken/migrations/0001_initial.py b/spoken/migrations/0001_initial.py new file mode 100644 index 0000000..f871d63 --- /dev/null +++ b/spoken/migrations/0001_initial.py @@ -0,0 +1,165 @@ +# Generated by Django 4.2.1 on 2024-05-01 09:59 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("common", "0001_initial"), + ] + + operations = [ + migrations.CreateModel( + name="StateCoordinator", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "status", + models.CharField( + choices=[ + ("pending_approval", "pending approval"), + ("active", "active"), + ("inactive", "inactive"), + ("rejected", "rejected"), + ], + max_length=100, + ), + ), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now_add=True)), + ( + "approved_by", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "state", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, to="common.state" + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="state_coord", + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + migrations.CreateModel( + name="NationalCoordinator", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "status", + models.CharField( + choices=[ + ("pending_approval", "pending approval"), + ("active", "active"), + ("inactive", "inactive"), + ("rejected", "rejected"), + ], + max_length=100, + ), + ), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now_add=True)), + ( + "approved_by", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="national_coord", + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + migrations.CreateModel( + name="DistrictCoordinator", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "status", + models.CharField( + choices=[ + ("pending_approval", "pending approval"), + ("active", "active"), + ("inactive", "inactive"), + ("rejected", "rejected"), + ], + max_length=100, + ), + ), + ("created", models.DateTimeField(auto_now_add=True)), + ("updated", models.DateTimeField(auto_now_add=True)), + ( + "approved_by", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.PROTECT, + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "district", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + to="common.district", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="district_coord", + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + ] diff --git a/spoken/migrations/__init__.py b/spoken/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/spoken/models.py b/spoken/models.py new file mode 100644 index 0000000..7e13760 --- /dev/null +++ b/spoken/models.py @@ -0,0 +1,28 @@ +from django.db import models +from accounts.models import User, APPROVAL_STATUS +from common.models import State, District + +class NationalCoordinator(models.Model): + user = models.ForeignKey(User, on_delete=models.PROTECT, related_name="national_coord") + status = models.CharField(choices=APPROVAL_STATUS, max_length=100) + approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now_add=True) + + +class StateCoordinator(models.Model): + user = models.ForeignKey(User, on_delete=models.PROTECT, related_name="state_coord") + state = models.ForeignKey(State, on_delete=models.PROTECT) + status = models.CharField(choices=APPROVAL_STATUS, max_length=100) + approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now_add=True) + +class DistrictCoordinator(models.Model): + user = models.ForeignKey(User, on_delete=models.PROTECT, related_name="district_coord") + district = models.ForeignKey(District, on_delete=models.PROTECT) + status = models.CharField(choices=APPROVAL_STATUS, max_length=100) + approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now_add=True) + diff --git a/spoken/tests.py b/spoken/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/spoken/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/spoken/views.py b/spoken/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/spoken/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. From 4f82d6b62cc11615f5dcdf10a87c3e8717b0928f Mon Sep 17 00:00:00 2001 From: ankitamk14 Date: Thu, 9 May 2024 15:04:27 +0530 Subject: [PATCH 2/2] added new models --- accounts/models.py | 106 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 22 deletions(-) diff --git a/accounts/models.py b/accounts/models.py index a05ad09..7f88d23 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -7,6 +7,7 @@ from common.models import State, District, City, Language +# Constants APPROVAL_STATUS = [ ('pending_approval', 'pending approval'), ('active', 'active'), @@ -94,25 +95,28 @@ class Profile(models.Model): location = models.ForeignKey(Location, on_delete=models.PROTECT) updated = models.DateField(auto_now=True) +""" +Static roles section: Following models define the static roles. +""" + class OrganisationType(models.Model): name = models.CharField(max_length=200) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) - class Organisation(models.Model): added_by = models.ForeignKey(User, on_delete=models.PROTECT, related_name='associated_organisation') name_of_association = models.CharField(max_length=200, unique=True) date_of_association = models.DateField() type = models.ForeignKey(OrganisationType, on_delete=models.PROTECT) + organisation = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True) location = models.ForeignKey(Location, on_delete=models.PROTECT) status = models.CharField(choices=APPROVAL_STATUS, max_length=100, default="pending_approval") approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True) created = models.DateField(auto_now_add=True) updated = models.DateField(auto_now=True) - class Meta: ordering = ['name_of_association', '-date_of_association'] @@ -148,23 +152,24 @@ def __str__(self): return self.name_of_association -class Payment(models.Model): - PAYMENT_CHOICES = [('IN_PROCESS', 'IN_PROCESS'), ('COMPLETED', 'COMPLETED'),] - date_of_payment = models.DateField() - amount = models.IntegerField() - utr = models.CharField(max_length=200, unique=True) - receipt = models.FileField(upload_to='receipts/') - expiry_date = models.DateField() # payment expiry - status = models.CharField(max_length=50, choices=PAYMENT_CHOICES) - school = models.ForeignKey(School, on_delete=models.PROTECT) +class OrganisationAuthority(models.Model): + """ + The 'organization authority' is the highest role within an organization's hierarchy of roles. + Users holding this role has access to all activities and resources within the organization. + """ + user = models.ForeignKey(User, on_delete=models.PROTECT, null=False, blank=False, related_name="org_auth") organisation = models.ForeignKey(Organisation, on_delete=models.PROTECT) - added_by = models.ForeignKey(User, on_delete=models.PROTECT) + approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True) + status = models.CharField(choices=APPROVAL_STATUS, max_length=100, default="pending_approval") + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now_add=True) class Meta: - ordering = ['date_of_payment'] + verbose_name = 'Organisation Authority' + verbose_name_plural = 'Organisation Authority' def __str__(self): - return f"{self.school.name_of_association} - {self.date_of_payment}" + return f"{self.user} - {self.organisation}" class OrganisationCoordinator(models.Model): """ @@ -185,6 +190,25 @@ class Meta: def __str__(self): return f"{self.user} - {self.organisation}" +class SchoolAuthority(models.Model): + """ + The 'school authority' is the highest role within a school's hierarchy of roles. + Users holding this role has access to all activities and resources within the school. + """ + user = models.ForeignKey(User, on_delete=models.PROTECT, null=False, blank=False, related_name="school_auth") + school = models.ForeignKey(School, on_delete=models.PROTECT) + status = models.CharField(choices=APPROVAL_STATUS, max_length=100, default="pending_approval") + approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True) + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now_add=True) + + class Meta: + verbose_name = 'School Coordinator' + verbose_name_plural = 'School Coordinators' + + def __str__(self): + return f"{self.user} - {self.school}" + class SchoolCoordinator(models.Model): """ @@ -236,7 +260,6 @@ class ClassName(models.Model): class Section(models.Model): name = models.CharField(max_length=50) - class ClassCoordinator(models.Model): """ An class coordinator is a user assigned to coordinate activities within a specific class & section. @@ -276,6 +299,15 @@ class ClassTeacher(models.Model): created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now_add=True) +""" +Static roles section ends. +""" + + +""" +Dynamic roles section: Following models define the dynamic roles. +""" + class Context(models.Model): """ Defines the context or level for the group to operate on. @@ -308,15 +340,14 @@ class UserGroup(models.Model): status = models.CharField(choices=APPROVAL_STATUS, max_length=100, default="pending_approval") approved_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True) -class Condition(models.Model): - sender = models.ForeignKey(Group, on_delete=models.CASCADE, related_name='sender') - receiver = models.ForeignKey(Group, on_delete=models.CASCADE, related_name='receiver') - single_msg = models.BooleanField(default=False) - bulk_msg = models.BooleanField(default=False) - class Meta: - unique_together = ['sender', 'receiver'] +""" +Dynamic roles section ends. +""" +""" +Message section: Following models define the message models. +""" class MessageType(models.Model): TYPE_CHOICES = [ @@ -345,3 +376,34 @@ class Message(models.Model): MessageType, on_delete=models.CASCADE, related_name='message_type' ) + +class Condition(models.Model): + sender = models.ForeignKey(Group, on_delete=models.CASCADE, related_name='sender') + receiver = models.ForeignKey(Group, on_delete=models.CASCADE, related_name='receiver') + single_msg = models.BooleanField(default=False) + bulk_msg = models.BooleanField(default=False) + + class Meta: + unique_together = ['sender', 'receiver'] + +""" +Message section ends. +""" + +class Payment(models.Model): + PAYMENT_CHOICES = [('IN_PROCESS', 'IN_PROCESS'), ('COMPLETED', 'COMPLETED'),] + date_of_payment = models.DateField() + amount = models.IntegerField() + utr = models.CharField(max_length=200, unique=True) + receipt = models.FileField(upload_to='receipts/') + expiry_date = models.DateField() # payment expiry + status = models.CharField(max_length=50, choices=PAYMENT_CHOICES) + school = models.ForeignKey(School, on_delete=models.PROTECT) + organisation = models.ForeignKey(Organisation, on_delete=models.PROTECT) + added_by = models.ForeignKey(User, on_delete=models.PROTECT) + + class Meta: + ordering = ['date_of_payment'] + + def __str__(self): + return f"{self.school.name_of_association} - {self.date_of_payment}" \ No newline at end of file