From 9e16bda9181992a1375680af54bd78174da80bf4 Mon Sep 17 00:00:00 2001 From: Keannu Bernasol Date: Sat, 16 Dec 2023 15:00:13 +0800 Subject: [PATCH] Change Working status to Available --- ...alter_equipmentinstance_status_and_more.py | 23 +++++++ equipment_tracker/equipments/models.py | 10 +-- equipment_tracker/equipments/serializers.py | 10 +-- equipment_tracker/schema.yml | 68 +++++++++++++++++-- equipment_tracker/transactions/serializers.py | 30 ++++---- equipment_tracker/transactions/views.py | 2 +- 6 files changed, 110 insertions(+), 33 deletions(-) create mode 100644 equipment_tracker/equipments/migrations/0002_alter_equipmentinstance_status_and_more.py diff --git a/equipment_tracker/equipments/migrations/0002_alter_equipmentinstance_status_and_more.py b/equipment_tracker/equipments/migrations/0002_alter_equipmentinstance_status_and_more.py new file mode 100644 index 0000000..864064f --- /dev/null +++ b/equipment_tracker/equipments/migrations/0002_alter_equipmentinstance_status_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.7 on 2023-12-16 06:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('equipments', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='equipmentinstance', + name='status', + field=models.CharField(choices=[('Available', 'Available'), ('Broken', 'Broken'), ('Borrowed', 'Borrowed')], default='Available', max_length=20), + ), + migrations.AlterField( + model_name='historicalequipmentinstance', + name='status', + field=models.CharField(choices=[('Available', 'Available'), ('Broken', 'Broken'), ('Borrowed', 'Borrowed')], default='Available', max_length=20), + ), + ] diff --git a/equipment_tracker/equipments/models.py b/equipment_tracker/equipments/models.py index a1ab5c5..7b57265 100644 --- a/equipment_tracker/equipments/models.py +++ b/equipment_tracker/equipments/models.py @@ -24,13 +24,13 @@ class Equipment(models.Model): class EquipmentInstance(models.Model): EQUIPMENT_INSTANCE_STATUS_CHOICES = ( - ('Working', 'Working'), + ('Available', 'Available'), ('Broken', 'Broken'), ('Borrowed', 'Borrowed'), ) equipment = models.ForeignKey(Equipment, on_delete=models.CASCADE) status = models.CharField( - max_length=20, choices=EQUIPMENT_INSTANCE_STATUS_CHOICES, default='PENDING') + max_length=20, choices=EQUIPMENT_INSTANCE_STATUS_CHOICES, default='Available') remarks = models.TextField(max_length=512, null=True) date_added = models.DateTimeField(default=now, editable=False) last_updated = models.DateTimeField(auto_now=True, editable=False) @@ -46,12 +46,12 @@ def create_superuser(sender, **kwargs): EQUIPMENT, CREATED = Equipment.objects.get_or_create( name="Pyrex Beaker", description="", category="Glassware") EQUIPMENT_INSTANCE, CREATED = EquipmentInstance.objects.get_or_create( - equipment=EQUIPMENT, status="Working", remarks="First beaker of equipment tracker!") + equipment=EQUIPMENT, status="Available", remarks="First beaker of equipment tracker!") EQUIPMENT, CREATED = Equipment.objects.get_or_create( name="Bunsen Burner", description="", category="Miscellaneous") EQUIPMENT_INSTANCE, CREATED = EquipmentInstance.objects.get_or_create( - equipment=EQUIPMENT, status="Working", remarks="First bunsen burner of equipment tracker!") + equipment=EQUIPMENT, status="Available", remarks="First bunsen burner of equipment tracker!") EQUIPMENT, CREATED = Equipment.objects.get_or_create( name="Microscope", description="", category="Miscellaneous") EQUIPMENT_INSTANCE, CREATED = EquipmentInstance.objects.get_or_create( - equipment=EQUIPMENT, status="Working", remarks="First microscope of equipment tracker!") + equipment=EQUIPMENT, status="Available", remarks="First microscope of equipment tracker!") diff --git a/equipment_tracker/equipments/serializers.py b/equipment_tracker/equipments/serializers.py index a2f5e46..f63598e 100644 --- a/equipment_tracker/equipments/serializers.py +++ b/equipment_tracker/equipments/serializers.py @@ -159,12 +159,12 @@ class EquipmentInstanceSerializer(serializers.HyperlinkedModelSerializer): equipments=instance, resolved=False).first() # If there is one if associated_breakage_report: - # Check if all the equipments of the currently associated BreakageReport are "Working" - all_working = all( - eq.status == 'Working' for eq in associated_breakage_report.equipments.all()) + # Check if all the equipments of the currently associated BreakageReport are "Available" + all_available = all( + eq.status == 'Available' for eq in associated_breakage_report.equipments.all()) - # If all the equipments are "Working", set Breakage Report to be resolved (resolved=True) - if all_working: + # If all the equipments are "Available", set Breakage Report to be resolved (resolved=True) + if all_available: associated_breakage_report.resolved = True associated_breakage_report.save() diff --git a/equipment_tracker/schema.yml b/equipment_tracker/schema.yml index db6b1a0..6d8166a 100644 --- a/equipment_tracker/schema.yml +++ b/equipment_tracker/schema.yml @@ -1020,6 +1020,37 @@ paths: schema: $ref: '#/components/schemas/Transaction' description: '' + patch: + operationId: api_v1_transactions_partial_update + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this transaction. + required: true + tags: + - api + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PatchedTransaction' + application/x-www-form-urlencoded: + schema: + $ref: '#/components/schemas/PatchedTransaction' + multipart/form-data: + schema: + $ref: '#/components/schemas/PatchedTransaction' + security: + - jwtAuth: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/Transaction' + description: '' components: schemas: Activation: @@ -1106,6 +1137,7 @@ components: type: string description: type: string + maxLength: 512 category: $ref: '#/components/schemas/CategoryEnum' last_updated: @@ -1121,7 +1153,6 @@ components: readOnly: true required: - date_added - - description - id - last_updated - last_updated_by @@ -1144,6 +1175,7 @@ components: $ref: '#/components/schemas/StatusEnum' remarks: type: string + maxLength: 512 last_updated: type: string format: date-time @@ -1367,6 +1399,7 @@ components: type: string description: type: string + maxLength: 512 category: $ref: '#/components/schemas/CategoryEnum' last_updated: @@ -1398,6 +1431,7 @@ components: $ref: '#/components/schemas/StatusEnum' remarks: type: string + maxLength: 512 last_updated: type: string format: date-time @@ -1409,6 +1443,26 @@ components: type: string format: date-time readOnly: true + PatchedTransaction: + type: object + properties: + id: + type: integer + readOnly: true + borrower: + type: integer + teacher: + type: integer + equipments: + type: array + items: + type: integer + transaction_status: + $ref: '#/components/schemas/TransactionStatusEnum' + timestamp: + type: string + format: date-time + readOnly: true SendEmailReset: type: object properties: @@ -1444,12 +1498,12 @@ components: - new_username StatusEnum: enum: - - Working + - Available - Broken - Borrowed type: string description: |- - * `Working` - Working + * `Available` - Available * `Broken` - Broken * `Borrowed` - Borrowed TokenObtainPair: @@ -1500,11 +1554,8 @@ components: readOnly: true borrower: type: integer - nullable: true teacher: - type: string - format: uri - nullable: true + type: integer equipments: type: array items: @@ -1516,7 +1567,10 @@ components: format: date-time readOnly: true required: + - borrower + - equipments - id + - teacher - timestamp - transaction_status TransactionStatusEnum: diff --git a/equipment_tracker/transactions/serializers.py b/equipment_tracker/transactions/serializers.py index f0d0a6c..f9c2668 100644 --- a/equipment_tracker/transactions/serializers.py +++ b/equipment_tracker/transactions/serializers.py @@ -99,7 +99,7 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer): equipments = validated_data['equipments'] for equipment in equipments: existing__pending_transactions = Transaction.objects.filter( - equipments=equipment, status__in=['Pending', 'Approved', 'Borrowed', 'With Breakages: Pending Resolution']) + equipments=equipment, transaction_status__in=['Pending', 'Approved', 'Borrowed', 'With Breakages: Pending Resolution']) if existing__pending_transactions.exists(): raise serializers.ValidationError( f"Cannot add Equipment #{equipment.id}. It is still part of a non-finalized transaction") @@ -110,13 +110,13 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer): user = self.context['request'].user # If user is not a teacher or a technician, forbid them from changing the status of a transaction - if not user.is_teacher and not user.technician and 'transaction_status' in validated_data and validated_data['transaction_status'] != instance.status: + if not user.is_teacher and not user.is_technician and 'transaction_status' in validated_data and validated_data['transaction_status'] != instance.transaction_status: raise serializers.ValidationError( "You are not a teacher or technician. You do not have permission to change the status of transactions" ) # If user is not a teacher, forbid them from changing the status of a transaction - if not user.is_teacher and 'transaction_status' in validated_data and validated_data['transaction_status'] != instance.status: + if not user.is_teacher and 'transaction_status' in validated_data and validated_data['transaction_status'] != instance.transaction_status: raise serializers.ValidationError( "You do not have permission to change the status of a transaction" ) @@ -128,7 +128,7 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer): # For already finalized/done transactions (Rejected or Finalized ones) # Do not allow any changes to already finalized transactions - if instance.status in ['Rejected', 'Finalized']: + if instance.transaction_status in ['Rejected', 'Finalized']: raise serializers.ValidationError( "Unable to update rejected or finalized transaction. Please create a new one" ) @@ -138,7 +138,7 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer): # For Pending transactions # If not changing to Approved or Rejected, throw an error - if instance.status == 'Pending' and validated_data['transaction_status'] != 'Approved' or validated_data['transaction_status'] != 'Rejected': + if instance.transaction_status == "Pending" and (validated_data['transaction_status'] != "Approved" or validated_data['transaction_status'] != "Rejected"): raise serializers.ValidationError( "A pending transaction can only change to Approved or Rejected" ) @@ -146,7 +146,7 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer): # For Approved transactions, # If not changing to Borrowed or Cancelled, throw an error # Already approved transactions can only be moved to Borrowed or Cancelled - if instance.status == 'Approved' and validated_data['transaction_status'] != 'Borrowed' or validated_data != 'Cancelled': + if instance.transaction_status == "Approved" and (validated_data['transaction_status'] != "Borrowed" or validated_data != "Cancelled"): raise serializers.ValidationError( "An already approved transaction can only changed to Borrowed (On borrow) or Cancelled" ) @@ -154,7 +154,7 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer): # For Borrowed transactions, # If not changing to returned, throw an error # Borrowed transactions that can only be changed to returned, pending checking for broken items - if instance.status == 'Borrowed' and validated_data['transaction_status'] != 'Finalized' or validated_data != 'With Breakages: Pending Resolution': + if instance.transaction_status == "Borrowed" and (validated_data['transaction_status'] != "Finalized" or validated_data != "With Breakages: Pending Resolution"): raise serializers.ValidationError( "A borrowed transaction can only changed to status of Finalized or With Breakages: Pending Resolution" ) @@ -162,7 +162,7 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer): # For Return: Pending Checking transactions, # If not changing to With Breakages: Pending Resolution or Finalized, throw an error # Returned transactions can only be finalized without any issues or be marked as with breakages - if instance.status == 'Returned: Pending Checking' and validated_data['transaction_status'] != 'Finalized' or validated_data != 'With Breakages: Pending Resolution': + if instance.transaction_status == "Returned: Pending Checking" and (validated_data['transaction_status'] != "Finalized" or validated_data != "With Breakages: Pending Resolution"): raise serializers.ValidationError( "A borrowed transaction can only changed to status of Finalized or With Breakages: Pending Resolution" ) @@ -170,27 +170,27 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer): # For transactions with pending breakage resolutions, # Do not allow updating of status. It should be updated within its respective breakage report # If it has been resolved there, this field will automatically update to Finalized - if instance.status == 'With Breakages: Pending Resolution': + if instance.transaction_status == "With Breakages: Pending Resolution": raise serializers.ValidationError( "A transaction with pending breakage resolutions must be updated or resolved in its respective breakage report" ) # If there are no issues and a transaction changes from Approved to Borrowed, label the selected equipment's statuses as Borrowed - if instance.status == 'Approved' and validated_data['transaction_status'] == 'Borrowed': + if instance.transaction_status == "Approved" and validated_data['transaction_status'] == "Borrowed": equipments = validated_data.get('equipments', []) for equipment in equipments: - equipment.status = 'Borrowed' + equipment.transaction_status = 'Borrowed' equipment.save() return super().update(validated_data) - # If the transaction changes from Borrowed to Finalized and there are no breakages, label the selected equipment's statuses as Working again from Borrowed - if instance.status == 'Borrowed' and validated_data['transaction_status'] == 'Finalized': + # If the transaction changes from Borrowed to Finalized and there are no breakages, label the selected equipment's statuses as Available again from Borrowed + if instance.transaction_status == "Borrowed" and validated_data['transaction_status'] == "Finalized": equipments = validated_data.get('equipments', []) for equipment in equipments: - equipment.status = 'Working' + equipment.transaction_status = 'Available' equipment.save() return super().update(validated_data) # If the transaction changes from Borrowed to With Breakages, we create a Breakage Report instance - if instance.status == 'Borrowed' and validated_data['transaction_status'] == 'Finalized': + if instance.transaction_status == "Borrowed" and validated_data['transaction_status'] == "Finalized": BreakageReport.objects.create( transaction=instance, equipments=instance.equipments.all(), diff --git a/equipment_tracker/transactions/views.py b/equipment_tracker/transactions/views.py index a0d4066..bcdf86d 100644 --- a/equipment_tracker/transactions/views.py +++ b/equipment_tracker/transactions/views.py @@ -7,7 +7,7 @@ from .models import Transaction class TransactionViewSet(viewsets.ModelViewSet): # Only allow GET, POST/CREATE # Transactions cannot be deleted - http_method_names = ['get', 'post'] + http_method_names = ['get', 'post', 'patch'] permission_classes = [IsAuthenticated] serializer_class = TransactionSerializer queryset = Transaction.objects.all()