mirror of
https://github.com/lemeow125/Borrowing-TrackerBackend.git
synced 2024-11-17 06:19:26 +08:00
Merge branch 'master' of https://git.keannu1.duckdns.org/keannu125/Borrowing-TrackerBackend
This commit is contained in:
commit
1e17a4f142
12 changed files with 51 additions and 75 deletions
|
@ -1,10 +1,9 @@
|
||||||
# Generated by Django 4.2.7 on 2024-01-05 10:26
|
# Generated by Django 5.0.1 on 2024-01-14 12:55
|
||||||
|
|
||||||
import accounts.models
|
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
import django.contrib.auth.validators
|
import django.contrib.auth.validators
|
||||||
from django.db import migrations, models
|
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -33,7 +32,7 @@ class Migration(migrations.Migration):
|
||||||
('is_technician', models.BooleanField(default=False)),
|
('is_technician', models.BooleanField(default=False)),
|
||||||
('is_teacher', models.BooleanField(default=False)),
|
('is_teacher', models.BooleanField(default=False)),
|
||||||
('course', models.CharField(choices=[('BS Chemistry', 'BS Chemistry'), ('BS Food Technology', 'BS Food Technology'), ('BS Applied Physics', 'BS Applied Physics'), ('BS Environmental Science', 'BS Environmental Science')], default=None, max_length=60, null=True)),
|
('course', models.CharField(choices=[('BS Chemistry', 'BS Chemistry'), ('BS Food Technology', 'BS Food Technology'), ('BS Applied Physics', 'BS Applied Physics'), ('BS Environmental Science', 'BS Environmental Science')], default=None, max_length=60, null=True)),
|
||||||
('avatar', models.ImageField(null=True, upload_to=accounts.models.CustomUser._get_upload_to)),
|
('section', models.CharField(default=None, max_length=60, null=True)),
|
||||||
('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')),
|
('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')),
|
('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')),
|
||||||
],
|
],
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,35 +1,12 @@
|
||||||
from django.db import models
|
|
||||||
|
from django.db.models.signals import post_migrate
|
||||||
from django.contrib.auth.models import AbstractUser
|
from django.contrib.auth.models import AbstractUser
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.signals import post_migrate
|
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
import os
|
import os
|
||||||
from uuid import uuid4
|
|
||||||
|
|
||||||
|
|
||||||
class CustomUser(AbstractUser):
|
class CustomUser(AbstractUser):
|
||||||
# Function for avatar uploads
|
|
||||||
def _get_upload_to(instance, filename):
|
|
||||||
base_filename, file_extension = os.path.splitext(filename)
|
|
||||||
# Get the student ID number
|
|
||||||
ext = base_filename.split('.')[-1]
|
|
||||||
filename = '{}.{}'.format(uuid4().hex, ext)
|
|
||||||
|
|
||||||
student_id = str(instance.student_id_number)
|
|
||||||
new_filename = f"{student_id}_{filename}_{file_extension}"
|
|
||||||
return os.path.join('avatars', new_filename)
|
|
||||||
|
|
||||||
# Delete old avatar file if new one is uploaded
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
try:
|
|
||||||
# is the object in the database yet?
|
|
||||||
this = CustomUser.objects.get(id=self.id)
|
|
||||||
if this.avatar != self.avatar:
|
|
||||||
this.avatar.delete(save=False)
|
|
||||||
except:
|
|
||||||
pass # when new photo then we do nothing, normal case
|
|
||||||
super(CustomUser, self).save(*args, **kwargs)
|
|
||||||
|
|
||||||
first_name = models.CharField(max_length=100)
|
first_name = models.CharField(max_length=100)
|
||||||
last_name = models.CharField(max_length=100)
|
last_name = models.CharField(max_length=100)
|
||||||
# Email inherited from base user class
|
# Email inherited from base user class
|
||||||
|
@ -49,7 +26,7 @@ class CustomUser(AbstractUser):
|
||||||
|
|
||||||
course = models.CharField(
|
course = models.CharField(
|
||||||
max_length=60, null=True, choices=COURSE_CHOICES, default=None)
|
max_length=60, null=True, choices=COURSE_CHOICES, default=None)
|
||||||
avatar = models.ImageField(upload_to=_get_upload_to, null=True)
|
section = models.CharField(max_length=60, null=True, default=None)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def full_name(self):
|
def full_name(self):
|
||||||
|
|
|
@ -1,39 +1,38 @@
|
||||||
from djoser.serializers import UserCreateSerializer as BaseUserRegistrationSerializer
|
|
||||||
from djoser.serializers import UserSerializer as BaseUserSerializer
|
from djoser.serializers import UserSerializer as BaseUserSerializer
|
||||||
from django.core import exceptions as django_exceptions
|
from django.core import exceptions as django_exceptions
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from accounts.models import CustomUser
|
from accounts.models import CustomUser
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
from django.contrib.auth.password_validation import validate_password
|
from django.contrib.auth.password_validation import validate_password
|
||||||
from django.utils.encoding import smart_str
|
|
||||||
from drf_spectacular.utils import extend_schema_field
|
|
||||||
from drf_spectacular.types import OpenApiTypes
|
|
||||||
from drf_extra_fields.fields import Base64ImageField
|
|
||||||
|
|
||||||
# There can be multiple subject instances with the same name, only differing in course, year level, and semester. We filter them here
|
# There can be multiple subject instances with the same name, only differing in course, year level, and semester. We filter them here
|
||||||
|
|
||||||
|
|
||||||
class CustomUserSerializer(BaseUserSerializer):
|
class CustomUserSerializer(BaseUserSerializer):
|
||||||
avatar = Base64ImageField()
|
course = serializers.ChoiceField(
|
||||||
|
choices=CustomUser.COURSE_CHOICES, allow_blank=True, allow_null=True)
|
||||||
|
section = serializers.CharField(allow_blank=True, allow_null=True)
|
||||||
|
|
||||||
class Meta(BaseUserSerializer.Meta):
|
class Meta(BaseUserSerializer.Meta):
|
||||||
model = CustomUser
|
model = CustomUser
|
||||||
fields = ('id', 'username', 'email', 'avatar', 'first_name',
|
fields = ('id', 'username', 'email', 'first_name', 'course', 'section',
|
||||||
'last_name', 'is_teacher', 'is_technician')
|
'last_name', 'is_teacher', 'is_technician')
|
||||||
|
read_only_fields = ('id', 'username', 'email',
|
||||||
|
'is_teacher', 'is_technician')
|
||||||
|
|
||||||
|
|
||||||
class UserRegistrationSerializer(serializers.ModelSerializer):
|
class UserRegistrationSerializer(serializers.ModelSerializer):
|
||||||
email = serializers.EmailField(required=True)
|
email = serializers.EmailField(required=True)
|
||||||
course = serializers.ChoiceField(
|
course = serializers.ChoiceField(
|
||||||
choices=CustomUser.COURSE_CHOICES, required=True)
|
choices=CustomUser.COURSE_CHOICES, allow_blank=True, allow_null=True)
|
||||||
|
section = serializers.CharField(allow_blank=True, allow_null=True)
|
||||||
password = serializers.CharField(
|
password = serializers.CharField(
|
||||||
write_only=True, style={'input_type': 'password', 'placeholder': 'Password'})
|
write_only=True, style={'input_type': 'password', 'placeholder': 'Password'})
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CustomUser # Use your custom user model here
|
model = CustomUser # Use your custom user model here
|
||||||
fields = ('username', 'email', 'password', 'avatar', 'course',
|
fields = ('username', 'email', 'password', 'course', 'section',
|
||||||
'first_name', 'last_name')
|
'first_name', 'last_name')
|
||||||
read_only_fields = ('is_teacher', 'is_technician')
|
read_only_fields = ('username', 'email', 'is_teacher', 'is_technician')
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
user = self.Meta.model(**attrs)
|
user = self.Meta.model(**attrs)
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -80,7 +80,7 @@ def create_superuser(sender, **kwargs):
|
||||||
|
|
||||||
# Get equipment information
|
# Get equipment information
|
||||||
category = filename.split('-')[0]
|
category = filename.split('-')[0]
|
||||||
name = row[2] + ' ' + row[1]
|
name = row[1]
|
||||||
# If quantity is missing, set value as 0
|
# If quantity is missing, set value as 0
|
||||||
if (row[3] == ''):
|
if (row[3] == ''):
|
||||||
available = 0
|
available = 0
|
||||||
|
|
|
@ -1139,6 +1139,9 @@ components:
|
||||||
required:
|
required:
|
||||||
- token
|
- token
|
||||||
- uid
|
- uid
|
||||||
|
BlankEnum:
|
||||||
|
enum:
|
||||||
|
- ''
|
||||||
BreakageReport:
|
BreakageReport:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -1210,12 +1213,18 @@ components:
|
||||||
format: email
|
format: email
|
||||||
title: Email address
|
title: Email address
|
||||||
maxLength: 254
|
maxLength: 254
|
||||||
avatar:
|
|
||||||
type: string
|
|
||||||
format: uri
|
|
||||||
first_name:
|
first_name:
|
||||||
type: string
|
type: string
|
||||||
maxLength: 100
|
maxLength: 100
|
||||||
|
course:
|
||||||
|
nullable: true
|
||||||
|
oneOf:
|
||||||
|
- $ref: '#/components/schemas/CourseEnum'
|
||||||
|
- $ref: '#/components/schemas/NullEnum'
|
||||||
|
section:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
maxLength: 60
|
||||||
last_name:
|
last_name:
|
||||||
type: string
|
type: string
|
||||||
maxLength: 100
|
maxLength: 100
|
||||||
|
@ -1224,7 +1233,6 @@ components:
|
||||||
is_technician:
|
is_technician:
|
||||||
type: boolean
|
type: boolean
|
||||||
required:
|
required:
|
||||||
- avatar
|
|
||||||
- first_name
|
- first_name
|
||||||
- id
|
- id
|
||||||
- last_name
|
- last_name
|
||||||
|
@ -1448,6 +1456,9 @@ components:
|
||||||
- history_user
|
- history_user
|
||||||
- id
|
- id
|
||||||
- name
|
- name
|
||||||
|
NullEnum:
|
||||||
|
enum:
|
||||||
|
- null
|
||||||
PasswordResetConfirm:
|
PasswordResetConfirm:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -1477,12 +1488,18 @@ components:
|
||||||
format: email
|
format: email
|
||||||
title: Email address
|
title: Email address
|
||||||
maxLength: 254
|
maxLength: 254
|
||||||
avatar:
|
|
||||||
type: string
|
|
||||||
format: uri
|
|
||||||
first_name:
|
first_name:
|
||||||
type: string
|
type: string
|
||||||
maxLength: 100
|
maxLength: 100
|
||||||
|
course:
|
||||||
|
nullable: true
|
||||||
|
oneOf:
|
||||||
|
- $ref: '#/components/schemas/CourseEnum'
|
||||||
|
- $ref: '#/components/schemas/NullEnum'
|
||||||
|
section:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
|
maxLength: 60
|
||||||
last_name:
|
last_name:
|
||||||
type: string
|
type: string
|
||||||
maxLength: 100
|
maxLength: 100
|
||||||
|
@ -1736,12 +1753,15 @@ components:
|
||||||
password:
|
password:
|
||||||
type: string
|
type: string
|
||||||
writeOnly: true
|
writeOnly: true
|
||||||
avatar:
|
|
||||||
type: string
|
|
||||||
format: uri
|
|
||||||
nullable: true
|
|
||||||
course:
|
course:
|
||||||
$ref: '#/components/schemas/CourseEnum'
|
nullable: true
|
||||||
|
oneOf:
|
||||||
|
- $ref: '#/components/schemas/CourseEnum'
|
||||||
|
- $ref: '#/components/schemas/BlankEnum'
|
||||||
|
- $ref: '#/components/schemas/NullEnum'
|
||||||
|
section:
|
||||||
|
type: string
|
||||||
|
nullable: true
|
||||||
first_name:
|
first_name:
|
||||||
type: string
|
type: string
|
||||||
maxLength: 100
|
maxLength: 100
|
||||||
|
@ -1754,6 +1774,7 @@ components:
|
||||||
- first_name
|
- first_name
|
||||||
- last_name
|
- last_name
|
||||||
- password
|
- password
|
||||||
|
- section
|
||||||
- username
|
- username
|
||||||
UsernameResetConfirm:
|
UsernameResetConfirm:
|
||||||
type: object
|
type: object
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
# Generated by Django 5.0.1 on 2024-01-11 03:58
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('transactions', '0002_alter_transaction_transaction_status'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='transaction',
|
|
||||||
name='section',
|
|
||||||
field=models.CharField(max_length=255, null=True),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -38,7 +38,6 @@ class Transaction(models.Model):
|
||||||
max_length=40, choices=TRANSACTION_STATUS_CHOICES, default='Pending', db_index=True)
|
max_length=40, choices=TRANSACTION_STATUS_CHOICES, default='Pending', db_index=True)
|
||||||
subject = models.TextField(max_length=128)
|
subject = models.TextField(max_length=128)
|
||||||
timestamp = models.DateTimeField(default=now, editable=False)
|
timestamp = models.DateTimeField(default=now, editable=False)
|
||||||
section = models.CharField(max_length=255, null=True)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Transaction #{self.id} under {self.teacher} by {self.borrower}"
|
return f"Transaction #{self.id} under {self.teacher} by {self.borrower}"
|
||||||
|
|
|
@ -41,7 +41,6 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
required=False, allow_null=True, allow_blank=True)
|
required=False, allow_null=True, allow_blank=True)
|
||||||
timestamp = serializers.DateTimeField(
|
timestamp = serializers.DateTimeField(
|
||||||
format="%m-%d-%Y %I:%M %p", read_only=True)
|
format="%m-%d-%Y %I:%M %p", read_only=True)
|
||||||
section = serializers.CharField(required=True, allow_null=False)
|
|
||||||
|
|
||||||
transaction_status = serializers.ChoiceField(
|
transaction_status = serializers.ChoiceField(
|
||||||
choices=Transaction.TRANSACTION_STATUS_CHOICES)
|
choices=Transaction.TRANSACTION_STATUS_CHOICES)
|
||||||
|
@ -49,7 +48,7 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Transaction
|
model = Transaction
|
||||||
fields = ['id', 'borrower', 'teacher', 'subject',
|
fields = ['id', 'borrower', 'teacher', 'subject',
|
||||||
'equipments', 'remarks', 'transaction_status', 'additional_members', 'consumables', 'timestamp', 'section']
|
'equipments', 'remarks', 'transaction_status', 'additional_members', 'consumables', 'timestamp']
|
||||||
read_only_fields = ['id', 'timestamp']
|
read_only_fields = ['id', 'timestamp']
|
||||||
|
|
||||||
def to_representation(self, instance):
|
def to_representation(self, instance):
|
||||||
|
|
Loading…
Reference in a new issue