mirror of
https://github.com/lemeow125/Borrowing-TrackerBackend.git
synced 2024-11-17 06:19:26 +08:00
Change Working status to Available
This commit is contained in:
parent
8abf689544
commit
9e16bda918
6 changed files with 110 additions and 33 deletions
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -24,13 +24,13 @@ class Equipment(models.Model):
|
||||||
|
|
||||||
class EquipmentInstance(models.Model):
|
class EquipmentInstance(models.Model):
|
||||||
EQUIPMENT_INSTANCE_STATUS_CHOICES = (
|
EQUIPMENT_INSTANCE_STATUS_CHOICES = (
|
||||||
('Working', 'Working'),
|
('Available', 'Available'),
|
||||||
('Broken', 'Broken'),
|
('Broken', 'Broken'),
|
||||||
('Borrowed', 'Borrowed'),
|
('Borrowed', 'Borrowed'),
|
||||||
)
|
)
|
||||||
equipment = models.ForeignKey(Equipment, on_delete=models.CASCADE)
|
equipment = models.ForeignKey(Equipment, on_delete=models.CASCADE)
|
||||||
status = models.CharField(
|
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)
|
remarks = models.TextField(max_length=512, null=True)
|
||||||
date_added = models.DateTimeField(default=now, editable=False)
|
date_added = models.DateTimeField(default=now, editable=False)
|
||||||
last_updated = models.DateTimeField(auto_now=True, 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(
|
EQUIPMENT, CREATED = Equipment.objects.get_or_create(
|
||||||
name="Pyrex Beaker", description="", category="Glassware")
|
name="Pyrex Beaker", description="", category="Glassware")
|
||||||
EQUIPMENT_INSTANCE, CREATED = EquipmentInstance.objects.get_or_create(
|
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(
|
EQUIPMENT, CREATED = Equipment.objects.get_or_create(
|
||||||
name="Bunsen Burner", description="", category="Miscellaneous")
|
name="Bunsen Burner", description="", category="Miscellaneous")
|
||||||
EQUIPMENT_INSTANCE, CREATED = EquipmentInstance.objects.get_or_create(
|
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(
|
EQUIPMENT, CREATED = Equipment.objects.get_or_create(
|
||||||
name="Microscope", description="", category="Miscellaneous")
|
name="Microscope", description="", category="Miscellaneous")
|
||||||
EQUIPMENT_INSTANCE, CREATED = EquipmentInstance.objects.get_or_create(
|
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!")
|
||||||
|
|
|
@ -159,12 +159,12 @@ class EquipmentInstanceSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
equipments=instance, resolved=False).first()
|
equipments=instance, resolved=False).first()
|
||||||
# If there is one
|
# If there is one
|
||||||
if associated_breakage_report:
|
if associated_breakage_report:
|
||||||
# Check if all the equipments of the currently associated BreakageReport are "Working"
|
# Check if all the equipments of the currently associated BreakageReport are "Available"
|
||||||
all_working = all(
|
all_available = all(
|
||||||
eq.status == 'Working' for eq in associated_breakage_report.equipments.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 the equipments are "Available", set Breakage Report to be resolved (resolved=True)
|
||||||
if all_working:
|
if all_available:
|
||||||
associated_breakage_report.resolved = True
|
associated_breakage_report.resolved = True
|
||||||
associated_breakage_report.save()
|
associated_breakage_report.save()
|
||||||
|
|
||||||
|
|
|
@ -1020,6 +1020,37 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Transaction'
|
$ref: '#/components/schemas/Transaction'
|
||||||
description: ''
|
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:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
Activation:
|
Activation:
|
||||||
|
@ -1106,6 +1137,7 @@ components:
|
||||||
type: string
|
type: string
|
||||||
description:
|
description:
|
||||||
type: string
|
type: string
|
||||||
|
maxLength: 512
|
||||||
category:
|
category:
|
||||||
$ref: '#/components/schemas/CategoryEnum'
|
$ref: '#/components/schemas/CategoryEnum'
|
||||||
last_updated:
|
last_updated:
|
||||||
|
@ -1121,7 +1153,6 @@ components:
|
||||||
readOnly: true
|
readOnly: true
|
||||||
required:
|
required:
|
||||||
- date_added
|
- date_added
|
||||||
- description
|
|
||||||
- id
|
- id
|
||||||
- last_updated
|
- last_updated
|
||||||
- last_updated_by
|
- last_updated_by
|
||||||
|
@ -1144,6 +1175,7 @@ components:
|
||||||
$ref: '#/components/schemas/StatusEnum'
|
$ref: '#/components/schemas/StatusEnum'
|
||||||
remarks:
|
remarks:
|
||||||
type: string
|
type: string
|
||||||
|
maxLength: 512
|
||||||
last_updated:
|
last_updated:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
|
@ -1367,6 +1399,7 @@ components:
|
||||||
type: string
|
type: string
|
||||||
description:
|
description:
|
||||||
type: string
|
type: string
|
||||||
|
maxLength: 512
|
||||||
category:
|
category:
|
||||||
$ref: '#/components/schemas/CategoryEnum'
|
$ref: '#/components/schemas/CategoryEnum'
|
||||||
last_updated:
|
last_updated:
|
||||||
|
@ -1398,6 +1431,7 @@ components:
|
||||||
$ref: '#/components/schemas/StatusEnum'
|
$ref: '#/components/schemas/StatusEnum'
|
||||||
remarks:
|
remarks:
|
||||||
type: string
|
type: string
|
||||||
|
maxLength: 512
|
||||||
last_updated:
|
last_updated:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
|
@ -1409,6 +1443,26 @@ components:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
readOnly: true
|
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:
|
SendEmailReset:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -1444,12 +1498,12 @@ components:
|
||||||
- new_username
|
- new_username
|
||||||
StatusEnum:
|
StatusEnum:
|
||||||
enum:
|
enum:
|
||||||
- Working
|
- Available
|
||||||
- Broken
|
- Broken
|
||||||
- Borrowed
|
- Borrowed
|
||||||
type: string
|
type: string
|
||||||
description: |-
|
description: |-
|
||||||
* `Working` - Working
|
* `Available` - Available
|
||||||
* `Broken` - Broken
|
* `Broken` - Broken
|
||||||
* `Borrowed` - Borrowed
|
* `Borrowed` - Borrowed
|
||||||
TokenObtainPair:
|
TokenObtainPair:
|
||||||
|
@ -1500,11 +1554,8 @@ components:
|
||||||
readOnly: true
|
readOnly: true
|
||||||
borrower:
|
borrower:
|
||||||
type: integer
|
type: integer
|
||||||
nullable: true
|
|
||||||
teacher:
|
teacher:
|
||||||
type: string
|
type: integer
|
||||||
format: uri
|
|
||||||
nullable: true
|
|
||||||
equipments:
|
equipments:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
|
@ -1516,7 +1567,10 @@ components:
|
||||||
format: date-time
|
format: date-time
|
||||||
readOnly: true
|
readOnly: true
|
||||||
required:
|
required:
|
||||||
|
- borrower
|
||||||
|
- equipments
|
||||||
- id
|
- id
|
||||||
|
- teacher
|
||||||
- timestamp
|
- timestamp
|
||||||
- transaction_status
|
- transaction_status
|
||||||
TransactionStatusEnum:
|
TransactionStatusEnum:
|
||||||
|
|
|
@ -99,7 +99,7 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
equipments = validated_data['equipments']
|
equipments = validated_data['equipments']
|
||||||
for equipment in equipments:
|
for equipment in equipments:
|
||||||
existing__pending_transactions = Transaction.objects.filter(
|
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():
|
if existing__pending_transactions.exists():
|
||||||
raise serializers.ValidationError(
|
raise serializers.ValidationError(
|
||||||
f"Cannot add Equipment #{equipment.id}. It is still part of a non-finalized transaction")
|
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
|
user = self.context['request'].user
|
||||||
|
|
||||||
# If user is not a teacher or a technician, forbid them from changing the status of a transaction
|
# 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(
|
raise serializers.ValidationError(
|
||||||
"You are not a teacher or technician. You do not have permission to change the status of transactions"
|
"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 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(
|
raise serializers.ValidationError(
|
||||||
"You do not have permission to change the status of a transaction"
|
"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)
|
# For already finalized/done transactions (Rejected or Finalized ones)
|
||||||
# Do not allow any changes to already finalized transactions
|
# 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(
|
raise serializers.ValidationError(
|
||||||
"Unable to update rejected or finalized transaction. Please create a new one"
|
"Unable to update rejected or finalized transaction. Please create a new one"
|
||||||
)
|
)
|
||||||
|
@ -138,7 +138,7 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
|
||||||
# For Pending transactions
|
# For Pending transactions
|
||||||
# If not changing to Approved or Rejected, throw an error
|
# 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(
|
raise serializers.ValidationError(
|
||||||
"A pending transaction can only change to Approved or Rejected"
|
"A pending transaction can only change to Approved or Rejected"
|
||||||
)
|
)
|
||||||
|
@ -146,7 +146,7 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
# For Approved transactions,
|
# For Approved transactions,
|
||||||
# If not changing to Borrowed or Cancelled, throw an error
|
# If not changing to Borrowed or Cancelled, throw an error
|
||||||
# Already approved transactions can only be moved to Borrowed or Cancelled
|
# 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(
|
raise serializers.ValidationError(
|
||||||
"An already approved transaction can only changed to Borrowed (On borrow) or Cancelled"
|
"An already approved transaction can only changed to Borrowed (On borrow) or Cancelled"
|
||||||
)
|
)
|
||||||
|
@ -154,7 +154,7 @@ class TransactionSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
# For Borrowed transactions,
|
# For Borrowed transactions,
|
||||||
# If not changing to returned, throw an error
|
# If not changing to returned, throw an error
|
||||||
# Borrowed transactions that can only be changed to returned, pending checking for broken items
|
# 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(
|
raise serializers.ValidationError(
|
||||||
"A borrowed transaction can only changed to status of Finalized or With Breakages: Pending Resolution"
|
"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,
|
# For Return: Pending Checking transactions,
|
||||||
# If not changing to With Breakages: Pending Resolution or Finalized, throw an error
|
# 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
|
# 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(
|
raise serializers.ValidationError(
|
||||||
"A borrowed transaction can only changed to status of Finalized or With Breakages: Pending Resolution"
|
"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,
|
# For transactions with pending breakage resolutions,
|
||||||
# Do not allow updating of status. It should be updated within its respective breakage report
|
# 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 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(
|
raise serializers.ValidationError(
|
||||||
"A transaction with pending breakage resolutions must be updated or resolved in its respective breakage report"
|
"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 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', [])
|
equipments = validated_data.get('equipments', [])
|
||||||
for equipment in equipments:
|
for equipment in equipments:
|
||||||
equipment.status = 'Borrowed'
|
equipment.transaction_status = 'Borrowed'
|
||||||
equipment.save()
|
equipment.save()
|
||||||
return super().update(validated_data)
|
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 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.status == 'Borrowed' and validated_data['transaction_status'] == 'Finalized':
|
if instance.transaction_status == "Borrowed" and validated_data['transaction_status'] == "Finalized":
|
||||||
equipments = validated_data.get('equipments', [])
|
equipments = validated_data.get('equipments', [])
|
||||||
for equipment in equipments:
|
for equipment in equipments:
|
||||||
equipment.status = 'Working'
|
equipment.transaction_status = 'Available'
|
||||||
equipment.save()
|
equipment.save()
|
||||||
return super().update(validated_data)
|
return super().update(validated_data)
|
||||||
# If the transaction changes from Borrowed to With Breakages, we create a Breakage Report instance
|
# 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(
|
BreakageReport.objects.create(
|
||||||
transaction=instance,
|
transaction=instance,
|
||||||
equipments=instance.equipments.all(),
|
equipments=instance.equipments.all(),
|
||||||
|
|
|
@ -7,7 +7,7 @@ from .models import Transaction
|
||||||
class TransactionViewSet(viewsets.ModelViewSet):
|
class TransactionViewSet(viewsets.ModelViewSet):
|
||||||
# Only allow GET, POST/CREATE
|
# Only allow GET, POST/CREATE
|
||||||
# Transactions cannot be deleted
|
# Transactions cannot be deleted
|
||||||
http_method_names = ['get', 'post']
|
http_method_names = ['get', 'post', 'patch']
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
serializer_class = TransactionSerializer
|
serializer_class = TransactionSerializer
|
||||||
queryset = Transaction.objects.all()
|
queryset = Transaction.objects.all()
|
||||||
|
|
Loading…
Reference in a new issue