mirror of
https://github.com/lemeow125/DocManagerBackend.git
synced 2025-01-18 17:13:00 +08:00
Finish up questionnaire app
This commit is contained in:
parent
8bd8df9042
commit
b0a9b6b6f0
13 changed files with 558 additions and 25 deletions
|
@ -18,5 +18,4 @@ class IsHead(BasePermission):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def has_permission(self, request, view):
|
def has_permission(self, request, view):
|
||||||
print(request.user.role)
|
|
||||||
return bool(request.user and request.user.role == "head")
|
return bool(request.user and request.user.role == "head")
|
||||||
|
|
|
@ -25,12 +25,8 @@ class CustomUserRegistrationSerializer(serializers.ModelSerializer):
|
||||||
password = serializers.CharField(
|
password = serializers.CharField(
|
||||||
write_only=True, style={"input_type": "password", "placeholder": "Password"}
|
write_only=True, style={"input_type": "password", "placeholder": "Password"}
|
||||||
)
|
)
|
||||||
first_name = serializers.CharField(
|
first_name = serializers.CharField(required=True)
|
||||||
required=True, allow_blank=False, allow_null=False
|
last_name = serializers.CharField(required=True)
|
||||||
)
|
|
||||||
last_name = serializers.CharField(
|
|
||||||
required=True, allow_blank=False, allow_null=False
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CustomUser
|
model = CustomUser
|
||||||
|
|
|
@ -13,6 +13,7 @@ urlpatterns = [
|
||||||
path("accounts/", include("accounts.urls")),
|
path("accounts/", include("accounts.urls")),
|
||||||
path("documents/", include("documents.urls")),
|
path("documents/", include("documents.urls")),
|
||||||
path("requests/", include("document_requests.urls")),
|
path("requests/", include("document_requests.urls")),
|
||||||
|
path("questionnaires/", include("questionnaires.urls")),
|
||||||
path("admin/", admin.site.urls),
|
path("admin/", admin.site.urls),
|
||||||
path("schema/", SpectacularAPIView.as_view(), name="schema"),
|
path("schema/", SpectacularAPIView.as_view(), name="schema"),
|
||||||
path(
|
path(
|
||||||
|
|
|
@ -92,6 +92,7 @@ INSTALLED_APPS = [
|
||||||
"accounts",
|
"accounts",
|
||||||
"documents",
|
"documents",
|
||||||
"document_requests",
|
"document_requests",
|
||||||
|
"questionnaires",
|
||||||
"django_cleanup.apps.CleanupConfig",
|
"django_cleanup.apps.CleanupConfig",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Generated by Django 5.1.3 on 2024-11-24 02:12
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("document_requests", "0001_initial"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="documentrequest",
|
||||||
|
name="type",
|
||||||
|
field=models.CharField(
|
||||||
|
choices=[("softcopy", "Softcopy"), ("hardcopy", "Hardcopy")],
|
||||||
|
default="softcopy",
|
||||||
|
max_length=16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -25,4 +25,9 @@ class DocumentRequest(models.Model):
|
||||||
|
|
||||||
status = models.CharField(max_length=32, choices=STATUS_CHOICES, default="pending")
|
status = models.CharField(max_length=32, choices=STATUS_CHOICES, default="pending")
|
||||||
|
|
||||||
# TODO: Add request type (Softcopy/Hardcopy)
|
TYPE_CHOICES = (
|
||||||
|
("softcopy", "Softcopy"),
|
||||||
|
("hardcopy", "Hardcopy"),
|
||||||
|
)
|
||||||
|
|
||||||
|
type = models.CharField(max_length=16, choices=TYPE_CHOICES, default="softcopy")
|
||||||
|
|
|
@ -10,6 +10,7 @@ class DocumentRequestUnitCreationSerializer(serializers.ModelSerializer):
|
||||||
document = serializers.SlugRelatedField(
|
document = serializers.SlugRelatedField(
|
||||||
many=False, slug_field="id", queryset=Document.objects.all(), required=True
|
many=False, slug_field="id", queryset=Document.objects.all(), required=True
|
||||||
)
|
)
|
||||||
|
copies = serializers.IntegerField(min_value=1)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = DocumentRequestUnit
|
model = DocumentRequestUnit
|
||||||
|
@ -21,12 +22,13 @@ class DocumentRequestCreationSerializer(serializers.ModelSerializer):
|
||||||
many=False, slug_field="id", queryset=CustomUser.objects.all(), required=False
|
many=False, slug_field="id", queryset=CustomUser.objects.all(), required=False
|
||||||
)
|
)
|
||||||
documents = DocumentRequestUnitCreationSerializer(many=True, required=True)
|
documents = DocumentRequestUnitCreationSerializer(many=True, required=True)
|
||||||
college = serializers.CharField(allow_blank=False)
|
college = serializers.CharField(max_length=64)
|
||||||
purpose = serializers.CharField(max_length=512, allow_blank=False)
|
purpose = serializers.CharField(max_length=512)
|
||||||
|
type = serializers.ChoiceField(choices=DocumentRequest.TYPE_CHOICES, required=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = DocumentRequest
|
model = DocumentRequest
|
||||||
fields = ["requester", "college", "purpose", "documents"]
|
fields = ["requester", "college", "type", "purpose", "documents"]
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
user = self.context["request"].user
|
user = self.context["request"].user
|
||||||
|
@ -71,18 +73,30 @@ class DocumentRequestUnitWithFileSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
class DocumentRequestSerializer(serializers.ModelSerializer):
|
class DocumentRequestSerializer(serializers.ModelSerializer):
|
||||||
documents = serializers.SerializerMethodField()
|
documents = serializers.SerializerMethodField()
|
||||||
college = serializers.CharField(allow_blank=False)
|
purpose = serializers.CharField(max_length=512)
|
||||||
purpose = serializers.CharField(max_length=512, allow_blank=False)
|
date_requested = serializers.DateTimeField(
|
||||||
|
format="%m-%d-%Y %I:%M %p", read_only=True
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = DocumentRequest
|
model = DocumentRequest
|
||||||
fields = ["id", "requester", "college",
|
fields = [
|
||||||
"purpose", "documents", "status"]
|
"id",
|
||||||
|
"requester",
|
||||||
|
"college",
|
||||||
|
"type",
|
||||||
|
"purpose",
|
||||||
|
"date_requested",
|
||||||
|
"documents",
|
||||||
|
"status",
|
||||||
|
]
|
||||||
read_only_fields = [
|
read_only_fields = [
|
||||||
"id",
|
"id",
|
||||||
"requester",
|
"requester",
|
||||||
"college",
|
"college",
|
||||||
|
"type",
|
||||||
"purpose",
|
"purpose",
|
||||||
|
"date_requested",
|
||||||
"documents",
|
"documents",
|
||||||
"status",
|
"status",
|
||||||
]
|
]
|
||||||
|
@ -109,7 +123,7 @@ class DocumentRequestUpdateSerializer(serializers.ModelSerializer):
|
||||||
if instance.status == "denied":
|
if instance.status == "denied":
|
||||||
raise serializers.ValidationError(
|
raise serializers.ValidationError(
|
||||||
{
|
{
|
||||||
"error": "Denied requests cannot be updated. It is advised you create a new request and approve it from there"
|
"error": "Denied requests cannot be updated. You should instead create a new request and approve it from there"
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
elif validated_data["status"] == instance.status:
|
elif validated_data["status"] == instance.status:
|
||||||
|
@ -120,10 +134,12 @@ class DocumentRequestUpdateSerializer(serializers.ModelSerializer):
|
||||||
representation = super().update(instance, validated_data)
|
representation = super().update(instance, validated_data)
|
||||||
|
|
||||||
# Send an email on request status update
|
# Send an email on request status update
|
||||||
email = RequestUpdateEmail()
|
try:
|
||||||
email.context = {
|
email = RequestUpdateEmail()
|
||||||
"request_status": instance.status
|
email.context = {"request_status": instance.status}
|
||||||
}
|
email.send(to=[instance.requester.email])
|
||||||
email.send(to=[instance.requester.email])
|
except:
|
||||||
|
# Silence out errors if email sending fails
|
||||||
|
pass
|
||||||
|
|
||||||
return representation
|
return representation
|
||||||
|
|
|
@ -4,7 +4,6 @@ from .models import Document
|
||||||
|
|
||||||
class DocumentUploadSerializer(serializers.ModelSerializer):
|
class DocumentUploadSerializer(serializers.ModelSerializer):
|
||||||
# For staff document uploads
|
# For staff document uploads
|
||||||
file = serializers.FileField()
|
|
||||||
date_uploaded = serializers.DateTimeField(
|
date_uploaded = serializers.DateTimeField(
|
||||||
format="%m-%d-%Y %I:%M %p", read_only=True
|
format="%m-%d-%Y %I:%M %p", read_only=True
|
||||||
)
|
)
|
||||||
|
|
259
docmanager_backend/questionnaires/migrations/0001_initial.py
Normal file
259
docmanager_backend/questionnaires/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,259 @@
|
||||||
|
# Generated by Django 5.1.3 on 2024-11-24 02:27
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Questionnaire",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"client_type",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("citizen", "Citizen"),
|
||||||
|
("business", "Business"),
|
||||||
|
("government", "Government (Employee or Another Agency)"),
|
||||||
|
],
|
||||||
|
max_length=32,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"date_submitted",
|
||||||
|
models.DateTimeField(
|
||||||
|
default=django.utils.timezone.now, editable=False
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sex",
|
||||||
|
models.CharField(
|
||||||
|
choices=[("male", "Male"), ("female", "Female")], max_length=16
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("age", models.IntegerField()),
|
||||||
|
("region_of_residence", models.CharField(max_length=64)),
|
||||||
|
("service_availed", models.CharField(max_length=64)),
|
||||||
|
(
|
||||||
|
"i_am_a",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("faculty", "Faculty"),
|
||||||
|
("non-teaching staff", "Non-Teaching Staff"),
|
||||||
|
("student", "Student"),
|
||||||
|
("guardian", "Guardian/Parent of Student"),
|
||||||
|
("alumna", "Alumna"),
|
||||||
|
("other", "Other"),
|
||||||
|
],
|
||||||
|
max_length=32,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"i_am_a_other",
|
||||||
|
models.CharField(blank=True, max_length=64, null=True),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"q1_answer",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("1", "I know what a CC is and I saw this office's CC"),
|
||||||
|
(
|
||||||
|
"2",
|
||||||
|
"I know what a CC is but I did NOT see this office's CC",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"3",
|
||||||
|
"I learned of the CC only when I saw this office's CC",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"4",
|
||||||
|
"I do not know what a CC is and I did not see one in this office",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
max_length=64,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"q2_answer",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("1", "Easy to see"),
|
||||||
|
("2", "Somewhat easy to see"),
|
||||||
|
("3", "Difficult to see"),
|
||||||
|
("4", "Not visible at all"),
|
||||||
|
("5", "N/A"),
|
||||||
|
],
|
||||||
|
max_length=64,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"q3_answer",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("1", "Helped very much"),
|
||||||
|
("2", "Somewhat helped"),
|
||||||
|
("3", "Did not help"),
|
||||||
|
("4", "N/A"),
|
||||||
|
],
|
||||||
|
max_length=64,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sqd0_answer",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("1", "Strongly disagree"),
|
||||||
|
("2", "Disagree"),
|
||||||
|
("3", "Neither Agree nor Disagree"),
|
||||||
|
("4", "Agree"),
|
||||||
|
("5", "Strongly Agree"),
|
||||||
|
("6", "N/A"),
|
||||||
|
],
|
||||||
|
max_length=16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sqd1_answer",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("1", "Strongly disagree"),
|
||||||
|
("2", "Disagree"),
|
||||||
|
("3", "Neither Agree nor Disagree"),
|
||||||
|
("4", "Agree"),
|
||||||
|
("5", "Strongly Agree"),
|
||||||
|
("6", "N/A"),
|
||||||
|
],
|
||||||
|
max_length=16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sqd2_answer",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("1", "Strongly disagree"),
|
||||||
|
("2", "Disagree"),
|
||||||
|
("3", "Neither Agree nor Disagree"),
|
||||||
|
("4", "Agree"),
|
||||||
|
("5", "Strongly Agree"),
|
||||||
|
("6", "N/A"),
|
||||||
|
],
|
||||||
|
max_length=16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sqd3_answer",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("1", "Strongly disagree"),
|
||||||
|
("2", "Disagree"),
|
||||||
|
("3", "Neither Agree nor Disagree"),
|
||||||
|
("4", "Agree"),
|
||||||
|
("5", "Strongly Agree"),
|
||||||
|
("6", "N/A"),
|
||||||
|
],
|
||||||
|
max_length=16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sqd4_answer",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("1", "Strongly disagree"),
|
||||||
|
("2", "Disagree"),
|
||||||
|
("3", "Neither Agree nor Disagree"),
|
||||||
|
("4", "Agree"),
|
||||||
|
("5", "Strongly Agree"),
|
||||||
|
("6", "N/A"),
|
||||||
|
],
|
||||||
|
max_length=16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sqd5_answer",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("1", "Strongly disagree"),
|
||||||
|
("2", "Disagree"),
|
||||||
|
("3", "Neither Agree nor Disagree"),
|
||||||
|
("4", "Agree"),
|
||||||
|
("5", "Strongly Agree"),
|
||||||
|
("6", "N/A"),
|
||||||
|
],
|
||||||
|
max_length=16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sqd6_answer",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("1", "Strongly disagree"),
|
||||||
|
("2", "Disagree"),
|
||||||
|
("3", "Neither Agree nor Disagree"),
|
||||||
|
("4", "Agree"),
|
||||||
|
("5", "Strongly Agree"),
|
||||||
|
("6", "N/A"),
|
||||||
|
],
|
||||||
|
max_length=16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sqd7_answer",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("1", "Strongly disagree"),
|
||||||
|
("2", "Disagree"),
|
||||||
|
("3", "Neither Agree nor Disagree"),
|
||||||
|
("4", "Agree"),
|
||||||
|
("5", "Strongly Agree"),
|
||||||
|
("6", "N/A"),
|
||||||
|
],
|
||||||
|
max_length=16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"sqd8_answer",
|
||||||
|
models.CharField(
|
||||||
|
choices=[
|
||||||
|
("1", "Strongly disagree"),
|
||||||
|
("2", "Disagree"),
|
||||||
|
("3", "Neither Agree nor Disagree"),
|
||||||
|
("4", "Agree"),
|
||||||
|
("5", "Strongly Agree"),
|
||||||
|
("6", "N/A"),
|
||||||
|
],
|
||||||
|
max_length=16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"extra_suggestions",
|
||||||
|
models.TextField(blank=True, max_length=512, null=True),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"client",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,3 +1,113 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.utils.timezone import now
|
||||||
|
|
||||||
# Create your models here.
|
|
||||||
|
class Questionnaire(models.Model):
|
||||||
|
# Personal Information
|
||||||
|
# Email address is derived from the user and is no longer optional
|
||||||
|
client = models.ForeignKey("accounts.CustomUser", on_delete=models.CASCADE)
|
||||||
|
CLIENT_TYPE_CHOICES = (
|
||||||
|
("citizen", "Citizen"),
|
||||||
|
("business", "Business"),
|
||||||
|
("government", "Government (Employee or Another Agency)"),
|
||||||
|
)
|
||||||
|
client_type = models.CharField(
|
||||||
|
max_length=32, choices=CLIENT_TYPE_CHOICES, null=False, blank=False
|
||||||
|
)
|
||||||
|
|
||||||
|
date_submitted = models.DateTimeField(default=now, editable=False)
|
||||||
|
SEX_CHOICES = (
|
||||||
|
("male", "Male"),
|
||||||
|
("female", "Female"),
|
||||||
|
)
|
||||||
|
sex = models.CharField(
|
||||||
|
max_length=16, choices=SEX_CHOICES, null=False, blank=False)
|
||||||
|
age = models.IntegerField(null=False, blank=False)
|
||||||
|
region_of_residence = models.CharField(
|
||||||
|
max_length=64, null=False, blank=False)
|
||||||
|
service_availed = models.CharField(max_length=64, null=False, blank=False)
|
||||||
|
I_AM_I_CHOICES = (
|
||||||
|
("faculty", "Faculty"),
|
||||||
|
("non-teaching staff", "Non-Teaching Staff"),
|
||||||
|
("student", "Student"),
|
||||||
|
("guardian", "Guardian/Parent of Student"),
|
||||||
|
("alumna", "Alumna"),
|
||||||
|
("other", "Other"),
|
||||||
|
)
|
||||||
|
i_am_a = models.CharField(
|
||||||
|
max_length=32, choices=I_AM_I_CHOICES, null=False, blank=False
|
||||||
|
)
|
||||||
|
# This is filled up if i_am_a=other
|
||||||
|
i_am_a_other = models.CharField(max_length=64, null=True, blank=True)
|
||||||
|
|
||||||
|
# CC Questions
|
||||||
|
Q1_CHOICES = (
|
||||||
|
("1", "I know what a CC is and I saw this office's CC"),
|
||||||
|
("2", "I know what a CC is but I did NOT see this office's CC"),
|
||||||
|
("3", "I learned of the CC only when I saw this office's CC"),
|
||||||
|
("4", "I do not know what a CC is and I did not see one in this office"),
|
||||||
|
)
|
||||||
|
q1_answer = models.CharField(
|
||||||
|
max_length=64, choices=Q1_CHOICES, null=False, blank=False
|
||||||
|
)
|
||||||
|
|
||||||
|
Q2_CHOICES = (
|
||||||
|
("1", "Easy to see"),
|
||||||
|
("2", "Somewhat easy to see"),
|
||||||
|
("3", "Difficult to see"),
|
||||||
|
("4", "Not visible at all"),
|
||||||
|
("5", "N/A"),
|
||||||
|
)
|
||||||
|
q2_answer = models.CharField(
|
||||||
|
max_length=64, choices=Q2_CHOICES, null=False, blank=False
|
||||||
|
)
|
||||||
|
|
||||||
|
Q3_CHOICES = (
|
||||||
|
("1", "Helped very much"),
|
||||||
|
("2", "Somewhat helped"),
|
||||||
|
("3", "Did not help"),
|
||||||
|
("4", "N/A"),
|
||||||
|
)
|
||||||
|
q3_answer = models.CharField(
|
||||||
|
max_length=64, choices=Q3_CHOICES, null=False, blank=False
|
||||||
|
)
|
||||||
|
|
||||||
|
# SQD Questions
|
||||||
|
SQD_CHOICES = (
|
||||||
|
("1", "Strongly disagree"),
|
||||||
|
("2", "Disagree"),
|
||||||
|
("3", "Neither Agree nor Disagree"),
|
||||||
|
("4", "Agree"),
|
||||||
|
("5", "Strongly Agree"),
|
||||||
|
("6", "N/A"),
|
||||||
|
)
|
||||||
|
|
||||||
|
sqd0_answer = models.CharField(
|
||||||
|
max_length=16, choices=SQD_CHOICES, null=False, blank=False
|
||||||
|
)
|
||||||
|
sqd1_answer = models.CharField(
|
||||||
|
max_length=16, choices=SQD_CHOICES, null=False, blank=False
|
||||||
|
)
|
||||||
|
sqd2_answer = models.CharField(
|
||||||
|
max_length=16, choices=SQD_CHOICES, null=False, blank=False
|
||||||
|
)
|
||||||
|
sqd3_answer = models.CharField(
|
||||||
|
max_length=16, choices=SQD_CHOICES, null=False, blank=False
|
||||||
|
)
|
||||||
|
sqd4_answer = models.CharField(
|
||||||
|
max_length=16, choices=SQD_CHOICES, null=False, blank=False
|
||||||
|
)
|
||||||
|
sqd5_answer = models.CharField(
|
||||||
|
max_length=16, choices=SQD_CHOICES, null=False, blank=False
|
||||||
|
)
|
||||||
|
sqd6_answer = models.CharField(
|
||||||
|
max_length=16, choices=SQD_CHOICES, null=False, blank=False
|
||||||
|
)
|
||||||
|
sqd7_answer = models.CharField(
|
||||||
|
max_length=16, choices=SQD_CHOICES, null=False, blank=False
|
||||||
|
)
|
||||||
|
sqd8_answer = models.CharField(
|
||||||
|
max_length=16, choices=SQD_CHOICES, null=False, blank=False
|
||||||
|
)
|
||||||
|
|
||||||
|
extra_suggestions = models.TextField(max_length=512, null=True, blank=True)
|
||||||
|
|
90
docmanager_backend/questionnaires/serializers.py
Normal file
90
docmanager_backend/questionnaires/serializers.py
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
from accounts.models import CustomUser
|
||||||
|
from .models import Questionnaire
|
||||||
|
|
||||||
|
|
||||||
|
class QuestionnaireSerializer(serializers.ModelSerializer):
|
||||||
|
client = serializers.SlugRelatedField(
|
||||||
|
many=False, slug_field="id", queryset=CustomUser.objects.all(), required=False
|
||||||
|
)
|
||||||
|
client_type = serializers.ChoiceField(
|
||||||
|
choices=Questionnaire.CLIENT_TYPE_CHOICES)
|
||||||
|
|
||||||
|
date_submitted = serializers.DateTimeField(
|
||||||
|
format="%m-%d-%Y %I:%M %p", read_only=True
|
||||||
|
)
|
||||||
|
sex = serializers.ChoiceField(choices=Questionnaire.SEX_CHOICES)
|
||||||
|
age = serializers.IntegerField(min_value=1)
|
||||||
|
region_of_residence = serializers.CharField(max_length=64)
|
||||||
|
service_availed = serializers.CharField(max_length=64)
|
||||||
|
i_am_a = serializers.ChoiceField(choices=Questionnaire.I_AM_I_CHOICES)
|
||||||
|
i_am_a_type_other = serializers.CharField(required=False)
|
||||||
|
q1_answer = serializers.ChoiceField(choices=Questionnaire.Q1_CHOICES)
|
||||||
|
q2_answer = serializers.ChoiceField(choices=Questionnaire.Q2_CHOICES)
|
||||||
|
q3_answer = serializers.ChoiceField(choices=Questionnaire.Q3_CHOICES)
|
||||||
|
sqd0_answer = serializers.ChoiceField(choices=Questionnaire.SQD_CHOICES)
|
||||||
|
sqd1_answer = serializers.ChoiceField(choices=Questionnaire.SQD_CHOICES)
|
||||||
|
sqd3_answer = serializers.ChoiceField(choices=Questionnaire.SQD_CHOICES)
|
||||||
|
sqd4_answer = serializers.ChoiceField(choices=Questionnaire.SQD_CHOICES)
|
||||||
|
sqd5_answer = serializers.ChoiceField(choices=Questionnaire.SQD_CHOICES)
|
||||||
|
sqd6_answer = serializers.ChoiceField(choices=Questionnaire.SQD_CHOICES)
|
||||||
|
sqd7_answer = serializers.ChoiceField(choices=Questionnaire.SQD_CHOICES)
|
||||||
|
sqd8_answer = serializers.ChoiceField(choices=Questionnaire.SQD_CHOICES)
|
||||||
|
extra_suggestions = serializers.CharField(max_length=512, required=False)
|
||||||
|
|
||||||
|
def to_representation(self, instance):
|
||||||
|
representation = super().to_representation(instance)
|
||||||
|
representation["client"] = instance.client.email
|
||||||
|
return super().to_representation(instance)
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
user = self.context["request"].user
|
||||||
|
# Set questionnaire user to the one who sent the HTTP request to prevent spoofing
|
||||||
|
validated_data["client"] = user
|
||||||
|
|
||||||
|
if (
|
||||||
|
validated_data["client_type"] == "other"
|
||||||
|
and not validated_data["client_type_other"]
|
||||||
|
):
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
{"error": "Missing description for client type: Other"}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create the instance without calling super().create()
|
||||||
|
instance = self.Meta.model(**validated_data)
|
||||||
|
|
||||||
|
# Explicitly set the client_type attribute
|
||||||
|
instance.client_type = validated_data.get("client_type")
|
||||||
|
|
||||||
|
# Save the instance
|
||||||
|
instance.save()
|
||||||
|
return instance
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Questionnaire
|
||||||
|
fields = [
|
||||||
|
"id",
|
||||||
|
"client",
|
||||||
|
"client_type",
|
||||||
|
"date_submitted",
|
||||||
|
"sex",
|
||||||
|
"age",
|
||||||
|
"region_of_residence",
|
||||||
|
"service_availed",
|
||||||
|
"i_am_a",
|
||||||
|
"i_am_a_type_other",
|
||||||
|
"q1_answer",
|
||||||
|
"q2_answer",
|
||||||
|
"q3_answer",
|
||||||
|
"sqd0_answer",
|
||||||
|
"sqd1_answer",
|
||||||
|
"sqd2_answer",
|
||||||
|
"sqd3_answer",
|
||||||
|
"sqd4_answer",
|
||||||
|
"sqd5_answer",
|
||||||
|
"sqd6_answer",
|
||||||
|
"sqd7_answer",
|
||||||
|
"sqd8_answer",
|
||||||
|
"extra_suggestions",
|
||||||
|
]
|
||||||
|
read_only_fields = ["id", "date_submitted"]
|
10
docmanager_backend/questionnaires/urls.py
Normal file
10
docmanager_backend/questionnaires/urls.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from django.urls import include, path
|
||||||
|
from .views import (
|
||||||
|
QuestionnaireListAPIView,
|
||||||
|
QuestionnaireSubmitView,
|
||||||
|
)
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("submit/", QuestionnaireSubmitView.as_view()),
|
||||||
|
path("list/", QuestionnaireListAPIView.as_view()),
|
||||||
|
]
|
|
@ -1,3 +1,28 @@
|
||||||
from django.shortcuts import render
|
from rest_framework import generics
|
||||||
|
from .serializers import QuestionnaireSerializer
|
||||||
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
from .models import Questionnaire
|
||||||
|
from rest_framework.pagination import PageNumberPagination
|
||||||
|
from accounts.permissions import IsStaff
|
||||||
|
|
||||||
# Create your views here.
|
|
||||||
|
class QuestionnaireListAPIView(generics.ListAPIView):
|
||||||
|
"""
|
||||||
|
Used by staff to view questionnaires
|
||||||
|
"""
|
||||||
|
|
||||||
|
http_method_names = ["get"]
|
||||||
|
serializer_class = QuestionnaireSerializer
|
||||||
|
queryset = Questionnaire.objects.all()
|
||||||
|
pagination_class = PageNumberPagination
|
||||||
|
permission_classes = [IsAuthenticated, IsStaff]
|
||||||
|
|
||||||
|
|
||||||
|
class QuestionnaireSubmitView(generics.CreateAPIView):
|
||||||
|
"""
|
||||||
|
Used by clients to submit questionnaires
|
||||||
|
"""
|
||||||
|
|
||||||
|
http_method_names = ["post"]
|
||||||
|
serializer_class = QuestionnaireSerializer
|
||||||
|
permission_classes = [IsAuthenticated]
|
||||||
|
|
Loading…
Reference in a new issue