From 4a6bd1ef35b98518cf0be992b63c557ec7a042d3 Mon Sep 17 00:00:00 2001 From: Keannu Bernasol Date: Sat, 2 Dec 2023 20:58:55 +0800 Subject: [PATCH] Add category to equipment model and improve serializers for equipments app --- .../accounts/migrations/0001_initial.py | 3 +- .../0002_customuser_is_technician.py | 18 -------- .../migrations/0001_initial.py | 4 +- .../equipments/migrations/0001_initial.py | 33 ++++++++++++--- ...move_equipment_last_changed_by_and_more.py | 25 ----------- .../migrations/0003_historicalequipment.py | 40 ------------------ equipment_tracker/equipments/models.py | 32 +++++++++----- equipment_tracker/equipments/serializers.py | 42 +++++++++++-------- 8 files changed, 78 insertions(+), 119 deletions(-) delete mode 100644 equipment_tracker/accounts/migrations/0002_customuser_is_technician.py delete mode 100644 equipment_tracker/equipments/migrations/0002_remove_equipment_last_changed_by_and_more.py delete mode 100644 equipment_tracker/equipments/migrations/0003_historicalequipment.py diff --git a/equipment_tracker/accounts/migrations/0001_initial.py b/equipment_tracker/accounts/migrations/0001_initial.py index 4e58eae..6479e54 100644 --- a/equipment_tracker/accounts/migrations/0001_initial.py +++ b/equipment_tracker/accounts/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.7 on 2023-11-09 11:42 +# Generated by Django 4.2.7 on 2023-12-02 12:25 import accounts.models import django.contrib.auth.models @@ -30,6 +30,7 @@ class Migration(migrations.Migration): ('first_name', models.CharField(max_length=100)), ('last_name', models.CharField(max_length=100)), ('is_active', models.BooleanField(default=False)), + ('is_technician', models.BooleanField(default=False)), ('avatar', models.ImageField(null=True, upload_to=accounts.models.CustomUser._get_upload_to)), ('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')), diff --git a/equipment_tracker/accounts/migrations/0002_customuser_is_technician.py b/equipment_tracker/accounts/migrations/0002_customuser_is_technician.py deleted file mode 100644 index a0f81d9..0000000 --- a/equipment_tracker/accounts/migrations/0002_customuser_is_technician.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.7 on 2023-11-13 10:22 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='customuser', - name='is_technician', - field=models.BooleanField(default=False), - ), - ] diff --git a/equipment_tracker/equipment_groups/migrations/0001_initial.py b/equipment_tracker/equipment_groups/migrations/0001_initial.py index dfa74f7..b4c6f84 100644 --- a/equipment_tracker/equipment_groups/migrations/0001_initial.py +++ b/equipment_tracker/equipment_groups/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.7 on 2023-11-13 09:43 +# Generated by Django 4.2.7 on 2023-12-02 12:25 from django.conf import settings from django.db import migrations, models @@ -13,7 +13,7 @@ class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('equipments', '0003_historicalequipment'), + ('equipments', '0001_initial'), ] operations = [ diff --git a/equipment_tracker/equipments/migrations/0001_initial.py b/equipment_tracker/equipments/migrations/0001_initial.py index b3e1f27..9288eb1 100644 --- a/equipment_tracker/equipments/migrations/0001_initial.py +++ b/equipment_tracker/equipments/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.7 on 2023-11-12 12:07 +# Generated by Django 4.2.7 on 2023-12-02 12:25 from django.conf import settings from django.db import migrations, models @@ -24,14 +24,14 @@ class Migration(migrations.Migration): ('description', models.TextField(max_length=512)), ('date_added', models.DateTimeField(default=django.utils.timezone.now, editable=False)), ('last_updated', models.DateTimeField(auto_now=True)), - ('last_changed_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ('category', models.CharField(choices=[('PC', 'PC'), ('NETWORKING', 'Networking'), ('CCTV', 'CCTV'), ('FURNITURE', 'Furniture'), ('PERIPHERALS', 'Peripherals'), ('MISC', 'Miscellaneous')], default='MISC', max_length=20)), ], ), migrations.CreateModel( name='HistoricalEquipmentInstance', fields=[ ('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), - ('status', models.CharField(choices=[('Working', 'Working'), ('Broken', 'Broken'), ('Under Maintenance', 'Under Maintenance'), ('Decomissioned', 'Decomissioned ')], default='PENDING', max_length=20)), + ('status', models.CharField(choices=[('WORKING', 'Working'), ('BROKEN', 'Broken'), ('MAINTENANCE', 'Under Maintenance'), ('DECOMISSIONED', 'Decomissioned')], default='PENDING', max_length=20)), ('remarks', models.TextField(max_length=512)), ('date_added', models.DateTimeField(default=django.utils.timezone.now, editable=False)), ('last_updated', models.DateTimeField(blank=True, editable=False)), @@ -41,7 +41,6 @@ class Migration(migrations.Migration): ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), ('equipment', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='equipments.equipment')), ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), - ('last_changed_by', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL)), ], options={ 'verbose_name': 'historical equipment instance', @@ -51,16 +50,38 @@ class Migration(migrations.Migration): }, bases=(simple_history.models.HistoricalChanges, models.Model), ), + migrations.CreateModel( + name='HistoricalEquipment', + fields=[ + ('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), + ('name', models.CharField(max_length=40)), + ('description', models.TextField(max_length=512)), + ('date_added', models.DateTimeField(default=django.utils.timezone.now, editable=False)), + ('last_updated', models.DateTimeField(blank=True, editable=False)), + ('category', models.CharField(choices=[('PC', 'PC'), ('NETWORKING', 'Networking'), ('CCTV', 'CCTV'), ('FURNITURE', 'Furniture'), ('PERIPHERALS', 'Peripherals'), ('MISC', 'Miscellaneous')], default='MISC', max_length=20)), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_date', models.DateTimeField(db_index=True)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'historical equipment', + 'verbose_name_plural': 'historical equipments', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': ('history_date', 'history_id'), + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), migrations.CreateModel( name='EquipmentInstance', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('status', models.CharField(choices=[('Working', 'Working'), ('Broken', 'Broken'), ('Under Maintenance', 'Under Maintenance'), ('Decomissioned', 'Decomissioned ')], default='PENDING', max_length=20)), + ('status', models.CharField(choices=[('WORKING', 'Working'), ('BROKEN', 'Broken'), ('MAINTENANCE', 'Under Maintenance'), ('DECOMISSIONED', 'Decomissioned')], default='PENDING', max_length=20)), ('remarks', models.TextField(max_length=512)), ('date_added', models.DateTimeField(default=django.utils.timezone.now, editable=False)), ('last_updated', models.DateTimeField(auto_now=True)), ('equipment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='equipments.equipment')), - ('last_changed_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), ], ), ] diff --git a/equipment_tracker/equipments/migrations/0002_remove_equipment_last_changed_by_and_more.py b/equipment_tracker/equipments/migrations/0002_remove_equipment_last_changed_by_and_more.py deleted file mode 100644 index 8c3f3ac..0000000 --- a/equipment_tracker/equipments/migrations/0002_remove_equipment_last_changed_by_and_more.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 4.2.7 on 2023-11-12 12:16 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('equipments', '0001_initial'), - ] - - operations = [ - migrations.RemoveField( - model_name='equipment', - name='last_changed_by', - ), - migrations.RemoveField( - model_name='equipmentinstance', - name='last_changed_by', - ), - migrations.RemoveField( - model_name='historicalequipmentinstance', - name='last_changed_by', - ), - ] diff --git a/equipment_tracker/equipments/migrations/0003_historicalequipment.py b/equipment_tracker/equipments/migrations/0003_historicalequipment.py deleted file mode 100644 index 81c6666..0000000 --- a/equipment_tracker/equipments/migrations/0003_historicalequipment.py +++ /dev/null @@ -1,40 +0,0 @@ -# Generated by Django 4.2.7 on 2023-11-12 12:27 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import django.utils.timezone -import simple_history.models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('equipments', '0002_remove_equipment_last_changed_by_and_more'), - ] - - operations = [ - migrations.CreateModel( - name='HistoricalEquipment', - fields=[ - ('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')), - ('name', models.CharField(max_length=40)), - ('description', models.TextField(max_length=512)), - ('date_added', models.DateTimeField(default=django.utils.timezone.now, editable=False)), - ('last_updated', models.DateTimeField(blank=True, editable=False)), - ('history_id', models.AutoField(primary_key=True, serialize=False)), - ('history_date', models.DateTimeField(db_index=True)), - ('history_change_reason', models.CharField(max_length=100, null=True)), - ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), - ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'verbose_name': 'historical equipment', - 'verbose_name_plural': 'historical equipments', - 'ordering': ('-history_date', '-history_id'), - 'get_latest_by': ('history_date', 'history_id'), - }, - bases=(simple_history.models.HistoricalChanges, models.Model), - ), - ] diff --git a/equipment_tracker/equipments/models.py b/equipment_tracker/equipments/models.py index 8c7730f..a198c2a 100644 --- a/equipment_tracker/equipments/models.py +++ b/equipment_tracker/equipments/models.py @@ -7,10 +7,22 @@ from django.dispatch import receiver class Equipment(models.Model): + + CATEGORY_CHOICES = ( + ('PC', 'PC'), + ('NETWORKING', 'Networking'), + ('CCTV', 'CCTV'), + ('FURNITURE', 'Furniture'), + ('PERIPHERALS', 'Peripherals'), + ('MISC', 'Miscellaneous') + ) + name = models.CharField(max_length=40) description = models.TextField(max_length=512) date_added = models.DateTimeField(default=now, editable=False) last_updated = models.DateTimeField(auto_now=True, editable=False) + category = models.CharField( + max_length=20, choices=CATEGORY_CHOICES, default='MISC') history = HistoricalRecords() def __str__(self): @@ -19,10 +31,10 @@ class Equipment(models.Model): class EquipmentInstance(models.Model): STATUS_CHOICES = ( - ('Working', 'Working'), - ('Broken', 'Broken'), - ('Under Maintenance', 'Under Maintenance'), - ('Decomissioned', 'Decomissioned '), + ('WORKING', 'Working'), + ('BROKEN', 'Broken'), + ('MAINTENANCE', 'Under Maintenance'), + ('DECOMISSIONED', 'Decomissioned'), ) equipment = models.ForeignKey(Equipment, on_delete=models.CASCADE) @@ -41,14 +53,14 @@ class EquipmentInstance(models.Model): def create_superuser(sender, **kwargs): if sender.name == 'equipments': EQUIPMENT, CREATED = Equipment.objects.get_or_create( - name="HP All-in-One PC", description="I5 6500 8GB RAM 1TB HDD") + name="HP All-in-One PC", description="I5 6500 8GB RAM 1TB HDD", category="PC") EQUIPMENT_INSTANCE, CREATED = EquipmentInstance.objects.get_or_create( - equipment=EQUIPMENT, status="Working", remarks="First PC of citc equipment tracker!") + equipment=EQUIPMENT, status="WORKING", remarks="First PC of citc equipment tracker!") EQUIPMENT, CREATED = Equipment.objects.get_or_create( - name="HP Keyboard", description="Generic Membrane Keyboard") + name="HP Keyboard", description="Generic Membrane Keyboard", category="PERIPHERALS") EQUIPMENT_INSTANCE, CREATED = EquipmentInstance.objects.get_or_create( - equipment=EQUIPMENT, status="Working", remarks="First keyboard of citc equipment tracker!") + equipment=EQUIPMENT, status="WORKING", remarks="First keyboard of citc equipment tracker!") EQUIPMENT, CREATED = Equipment.objects.get_or_create( - name="HP Mouse", description="Generic Mouse") + name="HP Mouse", description="Generic Mouse", category="PERIPHERALS") EQUIPMENT_INSTANCE, CREATED = EquipmentInstance.objects.get_or_create( - equipment=EQUIPMENT, status="Working", remarks="First mouse of citc equipment tracker!") + equipment=EQUIPMENT, status="WORKING", remarks="First mouse of citc equipment tracker!") diff --git a/equipment_tracker/equipments/serializers.py b/equipment_tracker/equipments/serializers.py index 4ab60fc..10fd223 100644 --- a/equipment_tracker/equipments/serializers.py +++ b/equipment_tracker/equipments/serializers.py @@ -2,6 +2,7 @@ from rest_framework import serializers from .models import Equipment, EquipmentInstance from drf_spectacular.utils import extend_schema_field from drf_spectacular.types import OpenApiTypes +from django.db.models import F from accounts.models import CustomUser # -- Equipment Serializers @@ -11,7 +12,7 @@ class EquipmentHistoricalRecordField(serializers.ListField): child = serializers.DictField() def to_representation(self, data): - return super().to_representation(data.values('name', 'description', 'history_date', 'history_user').order_by('-history_date')) + return super().to_representation(data.values('name', 'description', 'category', 'history_date', 'history_user').order_by('-history_date')) class EquipmentSerializer(serializers.HyperlinkedModelSerializer): @@ -25,7 +26,7 @@ class EquipmentSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Equipment - fields = ('id', 'name', 'description', + fields = ('id', 'name', 'description', 'category', 'last_updated', 'last_updated_by', 'date_added') read_only_fields = ('id', 'last_updated', 'last_updated_by', 'date_added') @@ -46,7 +47,7 @@ class EquipmentLogsSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Equipment.history.model - fields = ('history_id', 'name', 'description', + fields = ('history_id', 'name', 'description', 'category', 'history_date', 'history_user') read_only_fields = ('history_id', 'id', 'name', 'description', 'history_date', 'history_user') @@ -68,7 +69,7 @@ class EquipmentLogSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Equipment - fields = ('id', 'name', 'description', + fields = ('id', 'name', 'description', 'category', 'last_updated', 'date_added', 'last_updated_by', 'history') read_only_fields = ('id', 'last_updated', 'date_added', 'last_updated_by', 'history') @@ -84,12 +85,15 @@ class EquipmentInstanceHistoricalRecordField(serializers.ListField): child = serializers.DictField() def to_representation(self, data): - return super().to_representation(data.values('equipment', 'status', 'remarks', 'history_date', 'history_user').order_by('-history_date')) + data = data.annotate(equipment_name=F('equipment__name')) + return super().to_representation(data.values('equipment', 'equipment_name', 'status', 'remarks', 'history_date', 'history_user').order_by('-history_date')) class EquipmentInstanceSerializer(serializers.HyperlinkedModelSerializer): - equipment = serializers.PrimaryKeyRelatedField( - source='equipment.name', queryset=Equipment.objects.all()) + equipment = serializers.SlugRelatedField( + slug_field='id', queryset=Equipment.objects.all()) + equipment_name = serializers.CharField( + source='equipment.name', read_only=True) status = serializers.CharField() remarks = serializers.CharField() date_added = serializers.DateTimeField( @@ -107,10 +111,10 @@ class EquipmentInstanceSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = EquipmentInstance - fields = ('id', 'equipment', 'status', 'remarks', + fields = ('id', 'equipment', 'equipment_name', 'status', 'remarks', 'last_updated', 'last_updated_by', 'date_added') read_only_fields = ('id', 'last_updated', - 'last_updated_by', 'date_added') + 'last_updated_by', 'date_added', 'equipment_name') @extend_schema_field(OpenApiTypes.STR) def get_history_user(self, obj): @@ -125,15 +129,17 @@ class EquipmentInstanceLogsSerializer(serializers.HyperlinkedModelSerializer): history_date = serializers.DateTimeField( format="%m-%d-%Y %I:%M%p", read_only=True) history_user = serializers.SerializerMethodField() - equipment = serializers.PrimaryKeyRelatedField( - source='equipment.name', queryset=Equipment.objects.all()) + equipment = serializers.SlugRelatedField( + slug_field='id', queryset=Equipment.objects.all()) + equipment_name = serializers.CharField( + source='equipment.name', read_only=True) class Meta: model = EquipmentInstance.history.model - fields = ('history_id', 'id', 'equipment', 'status', 'remarks', + fields = ('history_id', 'id', 'equipment', 'equipment_name', 'status', 'remarks', 'history_date', 'history_user') read_only_fields = ('history_id', 'id', 'equipment', 'status', 'remarks', - 'history_date', 'history_user') + 'history_date', 'history_user', 'equipment_name') @extend_schema_field(OpenApiTypes.STR) def get_history_user(self, obj): @@ -141,8 +147,10 @@ class EquipmentInstanceLogsSerializer(serializers.HyperlinkedModelSerializer): class EquipmentInstanceLogSerializer(serializers.HyperlinkedModelSerializer): - equipment = serializers.PrimaryKeyRelatedField( - source='equipment.name', queryset=Equipment.objects.all()) + equipment = serializers.SlugRelatedField( + slug_field='id', queryset=Equipment.objects.all()) + equipment_name = serializers.CharField( + source='equipment.name', read_only=True) status = serializers.CharField() remarks = serializers.CharField() date_added = serializers.DateTimeField( @@ -160,10 +168,10 @@ class EquipmentInstanceLogSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = EquipmentInstance - fields = ('id', 'equipment', 'status', 'remarks', + fields = ('id', 'equipment', 'equipment_name', 'status', 'remarks', 'last_updated', 'date_added', 'last_updated_by', 'history') read_only_fields = ('id', 'last_updated', - 'date_added', 'last_updated_by', 'history') + 'date_added', 'last_updated_by', 'history', 'equipment_name') @extend_schema_field(OpenApiTypes.STR) def get_last_updated_by(self, obj):