Change Working status to Available

This commit is contained in:
Keannu Bernasol 2023-12-16 15:00:13 +08:00
parent 8abf689544
commit 9e16bda918
6 changed files with 110 additions and 33 deletions

View file

@ -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),
),
]

View file

@ -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!")

View file

@ -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()

View file

@ -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:

View file

@ -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(),

View file

@ -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()