From c22fd4b3968f608a6ff859ba7dbf275d2682ad7a Mon Sep 17 00:00:00 2001 From: Aniket Date: Sun, 18 Feb 2024 15:16:28 +0530 Subject: [PATCH 01/19] Added Sdk module for Approve/Forwd and Indent file, add/view stock, generate report --- .../migrations/0002_auto_20240217_1615.py | 38 ++ .../eis/migrations/0002_auto_20240217_1615.py | 53 +++ .../filetracking/api/serializers.py | 30 ++ .../applications/filetracking/api/urls.py | 22 + .../applications/filetracking/api/views.py | 89 ++++ .../migrations/0002_auto_20240217_1615.py | 33 ++ .../applications/filetracking/models.py | 14 +- .../applications/filetracking/sdk/methods.py | 331 +++++++++++++++ FusionIIIT/applications/filetracking/urls.py | 27 +- FusionIIIT/applications/filetracking/views.py | 383 ++++++++---------- .../migrations/0002_auto_20240217_1615.py | 23 ++ FusionIIIT/applications/ps1/urls.py | 3 +- FusionIIIT/applications/ps1/views.py | 182 ++++++--- .../migrations/0002_auto_20240217_1615.py | 18 + FusionIIIT/templates/ps1/generate_report.html | 279 +++++++++++++ requirements.txt | 2 +- 16 files changed, 1263 insertions(+), 264 deletions(-) create mode 100644 FusionIIIT/applications/academic_procedures/migrations/0002_auto_20240217_1615.py create mode 100644 FusionIIIT/applications/eis/migrations/0002_auto_20240217_1615.py create mode 100644 FusionIIIT/applications/filetracking/api/serializers.py create mode 100644 FusionIIIT/applications/filetracking/api/urls.py create mode 100644 FusionIIIT/applications/filetracking/api/views.py create mode 100644 FusionIIIT/applications/filetracking/migrations/0002_auto_20240217_1615.py create mode 100644 FusionIIIT/applications/filetracking/sdk/methods.py create mode 100644 FusionIIIT/applications/programme_curriculum/migrations/0002_auto_20240217_1615.py create mode 100644 FusionIIIT/applications/scholarships/migrations/0002_auto_20240217_1615.py create mode 100644 FusionIIIT/templates/ps1/generate_report.html diff --git a/FusionIIIT/applications/academic_procedures/migrations/0002_auto_20240217_1615.py b/FusionIIIT/applications/academic_procedures/migrations/0002_auto_20240217_1615.py new file mode 100644 index 000000000..0b130f128 --- /dev/null +++ b/FusionIIIT/applications/academic_procedures/migrations/0002_auto_20240217_1615.py @@ -0,0 +1,38 @@ +# Generated by Django 3.1.5 on 2024-02-17 16:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('academic_procedures', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='assistantshipclaim', + name='year', + field=models.IntegerField(choices=[(2024, 2024), (2023, 2023)]), + ), + migrations.AlterField( + model_name='course_registration', + name='working_year', + field=models.IntegerField(blank=True, choices=[(2024, 2024), (2023, 2023)], null=True), + ), + migrations.AlterField( + model_name='finalregistrations', + name='batch', + field=models.IntegerField(default=2024), + ), + migrations.AlterField( + model_name='messdue', + name='year', + field=models.IntegerField(choices=[(2024, 2024), (2023, 2023)]), + ), + migrations.AlterField( + model_name='register', + name='year', + field=models.IntegerField(default=2024), + ), + ] diff --git a/FusionIIIT/applications/eis/migrations/0002_auto_20240217_1615.py b/FusionIIIT/applications/eis/migrations/0002_auto_20240217_1615.py new file mode 100644 index 000000000..be4a04848 --- /dev/null +++ b/FusionIIIT/applications/eis/migrations/0002_auto_20240217_1615.py @@ -0,0 +1,53 @@ +# Generated by Django 3.1.5 on 2024-02-17 16:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('eis', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='emp_achievement', + name='a_year', + field=models.IntegerField(blank=True, choices=[(1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016), (2017, 2017), (2018, 2018), (2019, 2019), (2020, 2020), (2021, 2021), (2022, 2022), (2023, 2023), (2024, 2024)], null=True, verbose_name='year'), + ), + migrations.AlterField( + model_name='emp_confrence_organised', + name='k_year', + field=models.IntegerField(blank=True, choices=[(1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016), (2017, 2017), (2018, 2018), (2019, 2019), (2020, 2020), (2021, 2021), (2022, 2022), (2023, 2023), (2024, 2024)], null=True, verbose_name='year'), + ), + migrations.AlterField( + model_name='emp_expert_lectures', + name='l_year', + field=models.IntegerField(blank=True, choices=[(1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016), (2017, 2017), (2018, 2018), (2019, 2019), (2020, 2020), (2021, 2021), (2022, 2022), (2023, 2023), (2024, 2024)], null=True, verbose_name='year'), + ), + migrations.AlterField( + model_name='emp_keynote_address', + name='k_year', + field=models.IntegerField(blank=True, choices=[(1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016), (2017, 2017), (2018, 2018), (2019, 2019), (2020, 2020), (2021, 2021), (2022, 2022), (2023, 2023), (2024, 2024)], null=True, verbose_name='year'), + ), + migrations.AlterField( + model_name='emp_mtechphd_thesis', + name='s_year', + field=models.IntegerField(blank=True, choices=[(1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016), (2017, 2017), (2018, 2018), (2019, 2019), (2020, 2020), (2021, 2021), (2022, 2022), (2023, 2023), (2024, 2024)], null=True, verbose_name='year'), + ), + migrations.AlterField( + model_name='emp_patents', + name='p_year', + field=models.IntegerField(blank=True, choices=[(1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016), (2017, 2017), (2018, 2018), (2019, 2019), (2020, 2020), (2021, 2021), (2022, 2022), (2023, 2023), (2024, 2024)], null=True, verbose_name='year'), + ), + migrations.AlterField( + model_name='emp_published_books', + name='pyear', + field=models.IntegerField(blank=True, choices=[(1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016), (2017, 2017), (2018, 2018), (2019, 2019), (2020, 2020), (2021, 2021), (2022, 2022), (2023, 2023), (2024, 2024)], null=True, verbose_name='year'), + ), + migrations.AlterField( + model_name='emp_research_papers', + name='year', + field=models.CharField(blank=True, choices=[(1995, 1995), (1996, 1996), (1997, 1997), (1998, 1998), (1999, 1999), (2000, 2000), (2001, 2001), (2002, 2002), (2003, 2003), (2004, 2004), (2005, 2005), (2006, 2006), (2007, 2007), (2008, 2008), (2009, 2009), (2010, 2010), (2011, 2011), (2012, 2012), (2013, 2013), (2014, 2014), (2015, 2015), (2016, 2016), (2017, 2017), (2018, 2018), (2019, 2019), (2020, 2020), (2021, 2021), (2022, 2022), (2023, 2023), (2024, 2024)], max_length=10, null=True), + ), + ] diff --git a/FusionIIIT/applications/filetracking/api/serializers.py b/FusionIIIT/applications/filetracking/api/serializers.py new file mode 100644 index 000000000..a65b56651 --- /dev/null +++ b/FusionIIIT/applications/filetracking/api/serializers.py @@ -0,0 +1,30 @@ +from applications.filetracking.models import File, Tracking +from django.core.files import File as DjangoFile +from rest_framework import serializers + + +class FileSerializer(serializers.ModelSerializer): + class Meta: + model = File + fields = '__all__' + + +class TrackingSerializer(serializers.ModelSerializer): + class Meta: + model = Tracking + fields = '__all__' + + +class FileHeaderSerializer(serializers.ModelSerializer): + ''' + This serializes everything except the attachments of a file and whether it is read or not + ''' + class Meta: + model = File + fields = [ + 'id', + 'uploader', + 'designation', + 'subject', + 'description', + 'upload_date'] \ No newline at end of file diff --git a/FusionIIIT/applications/filetracking/api/urls.py b/FusionIIIT/applications/filetracking/api/urls.py new file mode 100644 index 000000000..e90bc711f --- /dev/null +++ b/FusionIIIT/applications/filetracking/api/urls.py @@ -0,0 +1,22 @@ +from django.conf.urls import url +from .views import ( + CreateFileView, + ViewFileView, + DeleteFileView, + ViewInboxView, + ViewOutboxView, + ViewHistoryView, + ForwardFileView, + GetDesignationsView, +) + +urlpatterns = [ + url(r'^file/$', CreateFileView.as_view(), name='create_file'), + url(r'^file/(?P\d+)/$', ViewFileView.as_view(), name='view_file'), + url(r'^file/(?P\d+)/$', DeleteFileView.as_view(), name='delete_file'), + url(r'^inbox/$', ViewInboxView.as_view(), name='view_inbox'), + url(r'^outbox/$', ViewOutboxView.as_view(), name='view_outbox'), + url(r'^history/(?P\d+)/$', ViewHistoryView.as_view(), name='view_history'), + url(r'^file/(?P\d+)/$', ForwardFileView.as_view(), name='forward_file'), + url(r'^designations/(?P\w+)/$', GetDesignationsView.as_view(), name='get_designations'), +] \ No newline at end of file diff --git a/FusionIIIT/applications/filetracking/api/views.py b/FusionIIIT/applications/filetracking/api/views.py new file mode 100644 index 000000000..76483cf5e --- /dev/null +++ b/FusionIIIT/applications/filetracking/api/views.py @@ -0,0 +1,89 @@ +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework import status, permissions +from rest_framework.authentication import TokenAuthentication +from ..sdk.methods import create_file, view_file, delete_file, view_inbox, view_outbox, view_history, forward_file, get_designations + + +class CreateFileView(APIView): + #authentication_classes = [TokenAuthentication] + #permission_classes = [permissions.IsAuthenticated] + + def post(self, request, *args, **kwargs): + file_id = create_file(**request.data) + return Response({'file_id': file_id}, status=status.HTTP_201_CREATED) + + +class ViewFileView(APIView): + #authentication_classes = [TokenAuthentication] + #permission_classes = [permissions.IsAuthenticated] + + def get(self, request, file_id, *args, **kwargs): + file_details = view_file(int(file_id)) + return Response(file_details) + + +class DeleteFileView(APIView): + #authentication_classes = [TokenAuthentication] + #permission_classes = [permissions.IsAuthenticated] + + def delete(self, request, file_id, *args, **kwargs): + success = delete_file(int(file_id)) + if success: + return Response({'message': 'File deleted successfully'}, + status=status.HTTP_204_NO_CONTENT) + else: + return Response({'error': 'File not found'}, + status=status.HTTP_404_NOT_FOUND) + + +class ViewInboxView(APIView): + #authentication_classes = [TokenAuthentication] + #permission_classes = [permissions.IsAuthenticated] + + def get(self, request, *args, **kwargs): + inbox_files = view_inbox( + request.user.username, + request.query_params.get('designation'), + request.query_params.get('src_module')) + return Response(inbox_files) + + +class ViewOutboxView(APIView): + #authentication_classes = [TokenAuthentication] + #permission_classes = [permissions.IsAuthenticated] + + def get(self, request, *args, **kwargs): + outbox_files = view_outbox( + request.user.username, + request.query_params.get('designation'), + request.query_params.get('src_module')) + return Response(outbox_files) + + +class ViewHistoryView(APIView): + #authentication_classes = [TokenAuthentication] + #permission_classes = [permissions.IsAuthenticated] + + def get(self, request, file_id, *args, **kwargs): + history = view_history(int(file_id)) + return Response(history) + + +class ForwardFileView(APIView): + #authentication_classes = [TokenAuthentication] + #permission_classes = [permissions.IsAuthenticated] + + def post(self, request, file_id, *args, **kwargs): + new_tracking_id = forward_file(int(file_id), **request.data) + return Response({'tracking_id': new_tracking_id}, + status=status.HTTP_201_CREATED) + + +class GetDesignationsView(APIView): + #authentication_classes = [TokenAuthentication] + #permission_classes = [permissions.IsAuthenticated] + + def get(self, request, username, *args, **kwargs): + user_designations = get_designations(username) + return Response({'designations': user_designations}) \ No newline at end of file diff --git a/FusionIIIT/applications/filetracking/migrations/0002_auto_20240217_1615.py b/FusionIIIT/applications/filetracking/migrations/0002_auto_20240217_1615.py new file mode 100644 index 000000000..c43148bc3 --- /dev/null +++ b/FusionIIIT/applications/filetracking/migrations/0002_auto_20240217_1615.py @@ -0,0 +1,33 @@ +# Generated by Django 3.1.5 on 2024-02-17 16:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('filetracking', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='file', + name='file_extra_JSON', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='file', + name='src_module', + field=models.CharField(default='filetracking', max_length=100), + ), + migrations.AddField( + model_name='file', + name='src_object_id', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='tracking', + name='tracking_extra_JSON', + field=models.JSONField(null=True), + ), + ] diff --git a/FusionIIIT/applications/filetracking/models.py b/FusionIIIT/applications/filetracking/models.py index 5f9581a08..70eb4f059 100644 --- a/FusionIIIT/applications/filetracking/models.py +++ b/FusionIIIT/applications/filetracking/models.py @@ -16,6 +16,11 @@ class File(models.Model): is_read = models.BooleanField(default = False) + # additions for API + src_module = models.CharField(max_length=100, default='filetracking') + src_object_id = models.CharField(max_length=100,null=True) + file_extra_JSON = models.JSONField(null=True) + class Meta: db_table = 'File' @@ -25,12 +30,12 @@ class Meta: class Tracking(models.Model): """ - This is File Tracing Table which contains the status of each indivisual file created by the user + This is File Tracing Table which contains the status of each individual file created by the user """ file_id = models.ForeignKey(File, on_delete=models.CASCADE, null=True) current_id = models.ForeignKey(ExtraInfo, on_delete=models.CASCADE) current_design = models.ForeignKey(HoldsDesignation, null=True, on_delete=models.CASCADE) - # receiver_id = models.ForeignKey(ExtraInfo, on_delete=models.CASCADE, related_name='receiver_id') + # receiver_id = models.ForeignKey(ExtraInfo, on_delete=models.CASCADE, related_name='receiver_id') # receive_design = models.ForeignKey(HoldsDesignation, null=True, on_delete=models.CASCADE, related_name='rec_design') receiver_id = models.ForeignKey(User,null = True, on_delete=models.CASCADE, related_name='receiver_id') receive_design = models.ForeignKey(Designation, null=True, on_delete=models.CASCADE, related_name='rec_design') @@ -41,5 +46,8 @@ class Tracking(models.Model): upload_file = models.FileField(blank=True) is_read = models.BooleanField(default = False) + # additions for API + tracking_extra_JSON = models.JSONField(null=True) + class Meta: - db_table = 'Tracking' + db_table = 'Tracking' \ No newline at end of file diff --git a/FusionIIIT/applications/filetracking/sdk/methods.py b/FusionIIIT/applications/filetracking/sdk/methods.py new file mode 100644 index 000000000..02374415f --- /dev/null +++ b/FusionIIIT/applications/filetracking/sdk/methods.py @@ -0,0 +1,331 @@ +from django.contrib.auth.models import User +from applications.filetracking.models import Tracking, File +from applications.globals.models import Designation, HoldsDesignation, ExtraInfo +from applications.filetracking.api.serializers import FileSerializer, FileHeaderSerializer, TrackingSerializer +from django.core.exceptions import ValidationError +from typing import Any + + +def create_file( + uploader: str, + uploader_designation: str, + receiver: str, + receiver_designation: str, + src_module: str = "filetracking", + src_object_id: str = "", + file_extra_JSON: dict = {}, + attached_file: Any = None) -> int: + ''' + This function is used to create a file object corresponding to any object of a module that needs to be tracked + ''' + + ''' + Functioning: + create base file with params + create tracking with params + if both complete then return id of file + else raise error + + also, delete file object if tracking isnt created + ''' + uploader_user_obj = get_user_object_from_username(uploader) + uploader_extrainfo_obj = get_ExtraInfo_object_from_username(uploader) + uploader_designation_obj = Designation.objects.get( + name=uploader_designation) + receiver_obj = get_user_object_from_username(receiver) + receiver_designation_obj = Designation.objects.get( + name=receiver_designation) + + new_file = File.objects.create( + uploader=uploader_extrainfo_obj, + designation=uploader_designation_obj, + src_module=src_module, + src_object_id=src_object_id, + file_extra_JSON=file_extra_JSON, + upload_file=attached_file + ) + uploader_holdsdesignation_obj = HoldsDesignation.objects.get( + user=uploader_user_obj, designation=uploader_designation_obj) + + new_tracking = Tracking.objects.create( + file_id=new_file, + current_id=uploader_extrainfo_obj, + current_design=uploader_holdsdesignation_obj, + receiver_id=receiver_obj, + receive_design=receiver_designation_obj, + tracking_extra_JSON=file_extra_JSON, + remarks=f"File with id:{str(new_file.id)} created by {uploader} and sent to {receiver}" + # upload_file = None, dont add file for first tracking + ) + if new_tracking is None: + new_file.delete() + raise ValidationError('Tracking model data is incorrect') + else: + return new_file.id + + +def view_file(file_id: int) -> dict: + ''' + This function returns all the details of a given file + ''' + try: + requested_file = File.objects.get(id=file_id) + serializer = FileSerializer(requested_file) + file_details = serializer.data + return file_details + except File.DoesNotExist: + raise NotFound("File Not Found with provided ID") + + +def delete_file(file_id: int) -> bool: + ''' + This function is used to delete a file from being tracked, all the tracking history is deleted as well and returns true if the deletion was successful + ''' + try: + File.objects.filter(id=file_id).delete() + return True + except File.DoesNotExist: + return False + +# inbox and outbox could be sorted based on most recent linked tracking entry + +def view_inbox(username: str, designation: str, src_module: str) -> dict: + ''' + This function is used to get all the files in the inbox of a particular user and designation + ''' + # TODO: currently this does not return a value of sent by + user_designation = Designation.objects.get(name=designation) + recipient_object = get_user_object_from_username(username) + received_files_tracking = Tracking.objects.select_related('file_id').filter( + receiver_id=recipient_object, + receive_design=user_designation, + file_id__src_module=src_module, + file_id__is_read=False) + received_files = [tracking.file_id for tracking in received_files_tracking] + + # remove duplicate file ids (from sending back and forth) + received_files_unique = uniqueList(received_files) + + received_files_serialized = FileHeaderSerializer( + received_files_unique, many=True) + return received_files_serialized.data + + +def view_outbox(username: str, designation: str, src_module: str) -> dict: + ''' + This function is used to get all the files in the outbox of a particular user and designation + ''' + user_designation = Designation.objects.get(name=designation) + user_object = get_user_object_from_username(username) + + # holds designation is used instead of Designation due to legacy code + # having it and breaking changes cannot be introduced + user_HoldsDesignation_object = HoldsDesignation.objects.get( + user=user_object, designation=user_designation) + sender_ExtraInfo_object = get_ExtraInfo_object_from_username(username) + sent_files_tracking = Tracking.objects.select_related('file_id').filter( + current_id=sender_ExtraInfo_object, + current_design=user_HoldsDesignation_object, + file_id__src_module=src_module, + file_id__is_read=False) + sent_files = [tracking.file_id for tracking in sent_files_tracking] + + # remove duplicate file ids (from sending back and forth) + sent_files_unique = uniqueList(sent_files) + + sent_files_serialized = FileHeaderSerializer(sent_files_unique, many=True) + return sent_files_serialized.data + + +# need: view_archived, archive_file, (can get details of archived files by view_file, etc) +# view_drafts, create_draft, (delete_draft can be via delete_file), +# (forward_draft can be via forward_file, but lets implement a send draft that follows our remark convention) + +def view_archived(username: str, designation: str, src_module: str) -> dict: + ''' + This function is used to get all the files in the archive of a particular user and designation + Archived file mean those which the user has ever interacted with, and are now finished or archived + ''' + user_designation = Designation.objects.get(name=designation) + user_object = get_user_object_from_username(username) + received_archived_tracking = Tracking.objects.select_related('file_id').filter( + receiver_id=user_object, + receive_design=user_designation, + file_id__src_module=src_module, + file_id__is_read=True) + + user_HoldsDesignation_object = HoldsDesignation.objects.get( + user=user_object, designation=user_designation) + sender_ExtraInfo_object = get_ExtraInfo_object_from_username(username) + sent_archived_tracking = Tracking.objects.select_related('file_id').filter( + current_id=sender_ExtraInfo_object, + current_design=user_HoldsDesignation_object, + file_id__src_module=src_module, + file_id__is_read=True) + + archived_tracking = received_archived_tracking | sent_archived_tracking + archived_files = [tracking.file_id for tracking in archived_tracking] + + # remove duplicate file ids (from sending back and forth) + archived_files_unique = uniqueList(archived_files) + + archived_files_serialized = FileHeaderSerializer(archived_files_unique, many=True) + return archived_files_serialized.data + + + +def archive_file(file_id: int) -> bool: + ''' + This function is used to archive a file and returns true if the archiving was successful + ''' + try: + File.objects.filter(id=file_id).update(is_read=True) + return True + except File.DoesNotExist: + return False + + + +def create_draft( + uploader: str, + uploader_designation: str, + src_module: str = "filetracking", + src_object_id: str = "", + file_extra_JSON: dict = {}, + attached_file: Any = None) -> int: + ''' + This function is used to create a draft file object corresponding to any object of a module that needs to be tracked + It is similar to create_file but is not sent to anyone + Later this file can be sent to someone by forward_file by using draft file_id + ''' + uploader_extrainfo_obj = get_ExtraInfo_object_from_username(uploader) + uploader_designation_obj = Designation.objects.get( + name=uploader_designation) + + new_file = File.objects.create( + uploader=uploader_extrainfo_obj, + designation=uploader_designation_obj, + src_module=src_module, + src_object_id=src_object_id, + file_extra_JSON=file_extra_JSON, + upload_file=attached_file + ) + return new_file.id + + +def view_drafts(username: str, designation: str, src_module: str) -> dict: + ''' + This function is used to get all the files in the drafts (has not been sent) of a particular user and designation + ''' + user_designation = Designation.objects.get(name=designation) + user_ExtraInfo_object = get_ExtraInfo_object_from_username(username) + draft_files = File.objects.filter( + tracking__isnull=True, uploader=user_ExtraInfo_object, designation=user_designation, src_module=src_module) + draft_files_serialized = FileHeaderSerializer(draft_files, many=True) + return draft_files_serialized.data + + + +def get_current_file_owner(file_id: int) -> User: + ''' + This functions returns the current owner of the file. + The current owner is the latest recipient of the file + ''' + latest_tracking = Tracking.objects.filter( + file_id=file_id).order_by('-receive_date').first() + latest_recipient = latest_tracking.receiver_id + return latest_recipient + + +def get_current_file_owner_designation(file_id: int) -> Designation: + ''' + This function returns the designation of the current owner of the file. + The current owner is the latest recipient of the file + ''' + latest_tracking = Tracking.objects.filter( + file_id=file_id).order_by('-receive_date').first() + latest_recipient_designation = latest_tracking.receive_design + return latest_recipient_designation + + +def forward_file( + file_id: int, + receiver: str, + receiver_designation: str, + file_extra_JSON: dict, + remarks: str = "", + file_attachment: Any = None) -> int: + ''' + This function forwards the file and inserts a new tracking history into the file tracking table + Note that only the current owner(with appropriate designation) of the file has the ability to forward files + ''' + # HoldsDesignation and ExtraInfo object are used instead + # of Designation and User object because of the legacy code being that way + + current_owner = get_current_file_owner(file_id) + current_owner_designation = get_current_file_owner_designation(file_id) + current_owner_extra_info = ExtraInfo.objects.get(user=current_owner) + current_owner_holds_designation = HoldsDesignation.objects.get( + user=current_owner, designation=current_owner_designation) + receiver_obj = User.objects.get(username=receiver) + receiver_designation_obj = Designation.objects.get( + name=receiver_designation) + tracking_data = { + 'file_id': file_id, + 'current_id': current_owner_extra_info.id, + 'current_design': current_owner_holds_designation.id, + 'receiver_id': receiver_obj.id, + 'receive_design': receiver_designation_obj.id, + 'tracking_extra_JSON': file_extra_JSON, + 'remarks': remarks, + } + if file_attachment is not None: + tracking_data['upload_file'] = file_attachment + + tracking_entry = TrackingSerializer(data=tracking_data) + if tracking_entry.is_valid(): + tracking_entry.save() + return tracking_entry.instance.id + else: + raise ValidationError('forward data is incomplete') + + +def view_history(file_id: int) -> dict: + ''' + This function is used to get the history of a particular file with the given file_id + ''' + Tracking_history = Tracking.objects.filter( + file_id=file_id).order_by('-receive_date') + Tracking_history_serialized = TrackingSerializer( + Tracking_history, many=True) + return Tracking_history_serialized.data + + +def get_designations(username: str) -> list: + ''' + This function is used to return a list of all the designation names of a particular user + ''' + user = User.objects.get(username=username) + designations_held = HoldsDesignation.objects.filter(user=user) + designation_name = [designation.name for designation in designations_held] + + +def get_user_object_from_username(username: str) -> User: + user = User.objects.get(username=username) + return user + + +def get_ExtraInfo_object_from_username(username: str) -> ExtraInfo: + user = User.objects.get(username=username) + extrainfo = ExtraInfo.objects.get(user=user) + return extrainfo + + +def uniqueList(l: list) -> list: + ''' + This function is used to return a list with unique elements + O(n) time and space + ''' + s = set(l) + unique_list = (list(s)) + return unique_list \ No newline at end of file diff --git a/FusionIIIT/applications/filetracking/urls.py b/FusionIIIT/applications/filetracking/urls.py index cb4a7563d..257483cf8 100644 --- a/FusionIIIT/applications/filetracking/urls.py +++ b/FusionIIIT/applications/filetracking/urls.py @@ -1,7 +1,7 @@ -from django.conf.urls import url +from django.conf.urls import url, include from . import views - +from .api import urls app_name = 'filetracking' urlpatterns = [ @@ -13,19 +13,28 @@ url(r'^fileview2/(?P\d+)$', views.fileview2, name='fileview2'), url(r'^outward/$', views.outward, name='outward'), url(r'^inward/$', views.inward, name='inward'), - url(r'^confirmdelete/(?P\d+)$', views.confirmdelete, name='confirm_delete'), + url(r'^confirmdelete/(?P\d+)$', + views.confirmdelete, name='confirm_delete'), url(r'^archive/(?P\d+)/$', views.archive, name='archive'), url(r'^finish/(?P\d+)/$', views.finish, name='finish'), url(r'^forward/(?P\d+)/$', views.forward, name='forward'), url(r'^ajax/$', views.AjaxDropdown1, name='ajax_dropdown1'), url(r'^ajax_dropdown/$', views.AjaxDropdown, name='ajax_dropdown'), - url(r'^test/$',views.test, name='test'), - url(r'^delete/(?P\d+)$',views.delete, name='delete'), - url(r'^forward_inward/(?P\d+)/$', views.forward_inward, name='forward_inward'), + url(r'^test/$', views.test, name='test'), + url(r'^delete/(?P\d+)$', views.delete, name='delete'), + url(r'^forward_inward/(?P\d+)/$', + views.forward_inward, name='forward_inward'), - ## correction team 24 + # correction team 24 url(r'^finish_design/$', views.finish_design, name='finish_design'), - url(r'^finish_fileview/(?P\d+)$', views.finish_fileview, name='finish_fileview'), + url(r'^finish_fileview/(?P\d+)$', + views.finish_fileview, + name='finish_fileview'), url(r'^archive_design/$', views.archive_design, name='archive_design'), - url(r'^archive_finish/(?P\d+)/$', views.archive_finish, name='archive_finish'), + url(r'^archive_finish/(?P\d+)/$', + views.archive_finish, name='archive_finish'), + + # REST api urls + url(r'^api/', include(urls)) + ] diff --git a/FusionIIIT/applications/filetracking/views.py b/FusionIIIT/applications/filetracking/views.py index ef5d8f347..283a83335 100644 --- a/FusionIIIT/applications/filetracking/views.py +++ b/FusionIIIT/applications/filetracking/views.py @@ -9,11 +9,11 @@ from django.core import serializers from django.contrib.auth.models import User from timeit import default_timer as time -from notification.views import office_module_notif,file_tracking_notif +from notification.views import office_module_notif, file_tracking_notif from .utils import * -@login_required(login_url = "/accounts/login/") +@login_required(login_url="/accounts/login/") def filetracking(request): """ The function is used to create files by current user(employee). @@ -35,18 +35,20 @@ def filetracking(request): holdsdesignations - The HoldsDesignation object. context - Holds data needed to make necessary changes in the template. """ - if request.method =="POST": + if request.method == "POST": try: if 'save' in request.POST: uploader = request.user.extrainfo subject = request.POST.get('title') description = request.POST.get('desc') design = request.POST.get('design') - designation = Designation.objects.get(id = HoldsDesignation.objects.select_related('user','working','designation').get(id = design).designation_id) + designation = Designation.objects.get(id=HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(id=design).designation_id) upload_file = request.FILES.get('myfile') - if(upload_file.size / 1000 > 10240): - messages.error(request,"File should not be greater than 10MB") - return redirect("/filetracking") + if upload_file and upload_file.size / 1000 > 10240: + messages.error( + request, "File should not be greater than 10MB") + return redirect("/filetracking") File.objects.create( uploader=uploader, @@ -56,18 +58,20 @@ def filetracking(request): upload_file=upload_file ) - messages.success(request,'File Draft Saved Successfully') + messages.success(request, 'File Draft Saved Successfully') if 'send' in request.POST: uploader = request.user.extrainfo subject = request.POST.get('title') description = request.POST.get('desc') design = request.POST.get('design') - designation = Designation.objects.get(id = HoldsDesignation.objects.select_related('user','working','designation').get(id = design).designation_id) + designation = Designation.objects.get(id=HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(id=design).designation_id) upload_file = request.FILES.get('myfile') - if(upload_file.size / 1000 > 10240): - messages.error(request,"File should not be greater than 10MB") + if upload_file and upload_file.size / 1000 > 10240: + messages.error( + request, "File should not be greater than 10MB") return redirect("/filetracking") file = File.objects.create( @@ -78,12 +82,12 @@ def filetracking(request): upload_file=upload_file ) - current_id = request.user.extrainfo remarks = request.POST.get('remarks') sender = request.POST.get('design') - current_design = HoldsDesignation.objects.select_related('user','working','designation').get(id=sender) + current_design = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(id=sender) receiver = request.POST.get('receiver') try: @@ -109,19 +113,19 @@ def filetracking(request): remarks=remarks, upload_file=upload_file, ) - #office_module_notif(request.user, receiver_id) - file_tracking_notif(request.user,receiver_id,subject) - messages.success(request,'File sent successfully') + # office_module_notif(request.user, receiver_id) + file_tracking_notif(request.user, receiver_id, subject) + messages.success(request, 'File sent successfully') except IntegrityError: message = "FileID Already Taken.!!" return HttpResponse(message) - - - file = File.objects.select_related('uploader__user','uploader__department','designation').all() - extrainfo = ExtraInfo.objects.select_related('user','department').all() - holdsdesignations = HoldsDesignation.objects.select_related('user','working','designation').all() + file = File.objects.select_related( + 'uploader__user', 'uploader__department', 'designation').all() + extrainfo = ExtraInfo.objects.select_related('user', 'department').all() + holdsdesignations = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').all() designations = get_designation(request.user) context = { @@ -133,7 +137,7 @@ def filetracking(request): return render(request, 'filetracking/composefile.html', context) -@login_required(login_url = "/accounts/login") +@login_required(login_url="/accounts/login") def drafts(request): """ The function is used to get the designation of the user and renders it on draft template. @@ -142,8 +146,8 @@ def drafts(request): request - trivial. @variables: - - + + context - Holds data needed to make necessary changes in the template. """ designation = get_designation(request.user) @@ -153,9 +157,8 @@ def drafts(request): return render(request, 'filetracking/drafts.html', context) -@login_required(login_url = "/accounts/login") -def fileview(request,id): - +@login_required(login_url="/accounts/login") +def fileview(request, id): """ This function is used to veiw all all created files by the user ordered by upload date.it collects all the created files from File object. @@ -166,30 +169,31 @@ def fileview(request,id): @parameters draft - file obeject containing all the files created by user context - holds data needed to render the template - - + + """ # draft = File.objects.select_related('uploader__user','uploader__department','designation').filter(uploader=request.user.extrainfo).order_by('-upload_date') # extrainfo = ExtraInfo.objects.select_related('user','department').all() - extrainfo = ExtraInfo.objects.select_related('user','department').all() - - ids = File.objects.filter(uploader=request.user.extrainfo).order_by('-upload_date').values_list('id', flat=True) - draft_files_pk=[] - - for i in ids: - file_tracking_ids = Tracking.objects.filter(file_id=i).values_list('id', flat=True) - if(len(file_tracking_ids)==0): - draft_files_pk.append(i) - - draft_file_list=[] - for i in draft_files_pk: - draft_file_list.append(File.objects.get(pk=i)) + extrainfo = ExtraInfo.objects.select_related('user', 'department').all() + + ids = File.objects.filter(uploader=request.user.extrainfo).order_by( + '-upload_date').values_list('id', flat=True) + draft_files_pk = [] + for i in ids: + file_tracking_ids = Tracking.objects.filter( + file_id=i).values_list('id', flat=True) + if (len(file_tracking_ids) == 0): + draft_files_pk.append(i) + draft_file_list = [] + for i in draft_files_pk: + draft_file_list.append(File.objects.get(pk=i)) - user_designation = HoldsDesignation.objects.select_related('user','working','designation').get(pk=id) + user_designation = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(pk=id) s = str(user_designation).split(" - ") designations = s[1] context = { @@ -201,10 +205,8 @@ def fileview(request,id): return render(request, 'filetracking/fileview.html', context) - -@login_required(login_url = "/accounts/login") -def fileview1(request,id): - +@login_required(login_url="/accounts/login") +def fileview1(request, id): """ The function is used to get all the files sent by user(employee) to other employees which are filtered from Tracking(table) objects by current user i.e. current_id. @@ -218,13 +220,14 @@ def fileview1(request,id): @variables: out - The Tracking object filtered by current_id i.e, present working user. context - Holds data needed to make necessary changes in the template. - + """ - outward_files = Tracking.objects.select_related('file_id__uploader__user','file_id__uploader__department','file_id__designation','current_id__user','current_id__department', - 'current_design__user','current_design__working','current_design__designation','receiver_id','receive_design').filter(current_id=request.user.extrainfo).order_by('-forward_date') + outward_files = Tracking.objects.select_related('file_id__uploader__user', 'file_id__uploader__department', 'file_id__designation', 'current_id__user', 'current_id__department', + 'current_design__user', 'current_design__working', 'current_design__designation', 'receiver_id', 'receive_design').filter(current_id=request.user.extrainfo).order_by('-forward_date') - user_designation = HoldsDesignation.objects.select_related('user','working','designation').get(pk=id) + user_designation = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(pk=id) context = { @@ -234,9 +237,8 @@ def fileview1(request,id): return render(request, 'filetracking/fileview1.html', context) -@login_required(login_url = "/accounts/login") -def fileview2(request,id): - +@login_required(login_url="/accounts/login") +def fileview2(request, id): """ The function is used to fetch the files received by the user form other employees. These files are filtered by receiver id and ordered by receive date. @@ -250,10 +252,11 @@ def fileview2(request,id): context - Holds data needed to make necessary changes in the template. """ - inward_file = Tracking.objects.select_related('file_id__uploader__user','file_id__uploader__department','file_id__designation','current_id__user','current_id__department', - 'current_design__user','current_design__working','current_design__designation','receiver_id','receive_design').filter(receiver_id=request.user).order_by('-receive_date') + inward_file = Tracking.objects.select_related('file_id__uploader__user', 'file_id__uploader__department', 'file_id__designation', 'current_id__user', 'current_id__department', + 'current_design__user', 'current_design__working', 'current_design__designation', 'receiver_id', 'receive_design').filter(receiver_id=request.user).order_by('-receive_date') - user_designation = HoldsDesignation.objects.select_related('user','working','designation').get(pk=id) + user_designation = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(pk=id) s = str(user_designation).split(" - ") designations = s[1] @@ -265,7 +268,7 @@ def fileview2(request,id): return render(request, 'filetracking/fileview2.html', context) -@login_required(login_url = "/accounts/login") +@login_required(login_url="/accounts/login") def outward(request): """ This function fetches the different designations of the user and renders it on outward template @@ -274,22 +277,22 @@ def outward(request): @variables: context - Holds the different designation data of the user - + """ designation = get_designation(request.user) context = { 'designation': designation, } - return render( request, 'filetracking/outward.html', context) + return render(request, 'filetracking/outward.html', context) -@login_required(login_url = "/accounts/login") +@login_required(login_url="/accounts/login") def inward(request): """ This function fetches the different designations of the user and renders it on inward template - + @param: request - trivial. @@ -298,15 +301,14 @@ def inward(request): """ designation = get_designation(request.user) context = { - + 'designation': designation, } return render(request, 'filetracking/inward.html', context) -@login_required(login_url = "/accounts/login") -def confirmdelete(request,id): - +@login_required(login_url="/accounts/login") +def confirmdelete(request, id): """ The function is used to confirm the deletion of a file. @param: @@ -316,16 +318,17 @@ def confirmdelete(request,id): @variables: context - Holds data needed to make necessary changes in the template. """ - file = File.objects.select_related('uploader__user','uploader__department','designation').get(pk = id) + file = File.objects.select_related( + 'uploader__user', 'uploader__department', 'designation').get(pk=id) context = { 'j': file, } - return render(request, 'filetracking/confirmdelete.html',context) + return render(request, 'filetracking/confirmdelete.html', context) -@login_required(login_url = "/accounts/login") +@login_required(login_url="/accounts/login") def forward(request, id): """ The function is used to forward files received by user(employee) from other @@ -351,73 +354,72 @@ def forward(request, id): holdsdesignations = HoldsDesignation objects. context - Holds data needed to make necessary changes in the template. """ - - file = get_object_or_404(File, id=id) - track = Tracking.objects.select_related('file_id__uploader__user','file_id__uploader__department','file_id__designation','current_id__user','current_id__department', - 'current_design__user','current_design__working','current_design__designation','receiver_id','receive_design').filter(file_id=file) - - if request.method == "POST": - if 'finish' in request.POST: - file.complete_flag = True - file.save() - if 'send' in request.POST: - current_id = request.user.extrainfo - remarks = request.POST.get('remarks') - track.update(is_read=True) - - sender = request.POST.get('sender') - current_design = HoldsDesignation.objects.select_related('user','working','designation').get(id=sender) - - receiver = request.POST.get('receiver') - try: - receiver_id = User.objects.get(username=receiver) - except Exception as e: - messages.error(request, 'Enter a valid destination') - designations = HoldsDesignation.objects.select_related('user','working','designation').filter(user=request.user) - - context = { - - 'designations': designations, - 'file': file, - 'track': track, - } - return render(request, 'filetracking/forward.html', context) - receive = request.POST.get('recieve') - try: - receive_design = Designation.objects.get(name=receive) - except Exception as e: - messages.error(request, 'Enter a valid Designation') - designations = get_designation(request.user) + file = get_object_or_404(File, id=id) + track = Tracking.objects.select_related('file_id__uploader__user', 'file_id__uploader__department', 'file_id__designation', 'current_id__user', 'current_id__department', + 'current_design__user', 'current_design__working', 'current_design__designation', 'receiver_id', 'receive_design').filter(file_id=file) - context = { - - 'designations': designations, - 'file': file, - 'track': track, - } - return render(request, 'filetracking/forward.html', context) + if request.method == "POST": + if 'finish' in request.POST: + file.is_read = True + file.save() + if 'send' in request.POST: + current_id = request.user.extrainfo + remarks = request.POST.get('remarks') + track.update(is_read=True) + + sender = request.POST.get('sender') + current_design = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(id=sender) + + receiver = request.POST.get('receiver') + try: + receiver_id = User.objects.get(username=receiver) + except Exception as e: + messages.error(request, 'Enter a valid destination') + designations = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').filter(user=request.user) + + context = { + + 'designations': designations, + 'file': file, + 'track': track, + } + return render(request, 'filetracking/forward.html', context) + receive = request.POST.get('recieve') + try: + receive_design = Designation.objects.get(name=receive) + except Exception as e: + messages.error(request, 'Enter a valid Designation') + designations = get_designation(request.user) + + context = { + + 'designations': designations, + 'file': file, + 'track': track, + } + return render(request, 'filetracking/forward.html', context) + + upload_file = request.FILES.get('myfile') + + Tracking.objects.create( + file_id=file, + current_id=current_id, + current_design=current_design, + receive_design=receive_design, + receiver_id=receiver_id, + remarks=remarks, + upload_file=upload_file, + ) + messages.success(request, 'File sent successfully') - - upload_file = request.FILES.get('myfile') - - Tracking.objects.create( - file_id=file, - current_id=current_id, - current_design=current_design, - receive_design=receive_design, - receiver_id=receiver_id, - remarks=remarks, - upload_file=upload_file, - ) - messages.success(request, 'File sent successfully') - - designations = get_designation(request.user) context = { - - 'designations':designations, + + 'designations': designations, 'file': file, 'track': track, } @@ -425,32 +427,31 @@ def forward(request, id): return render(request, 'filetracking/forward.html', context) -@login_required(login_url = "/accounts/login") +@login_required(login_url="/accounts/login") def archive_design(request): - designation = HoldsDesignation.objects.select_related('user','working','designation').filter(user=request.user) + designation = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').filter(user=request.user) context = { 'designation': designation, } - return render( request, 'filetracking/archive_design.html', context) - - - + return render(request, 'filetracking/archive_design.html', context) -@login_required(login_url = "/accounts/login") -def archive(request , id): +@login_required(login_url="/accounts/login") +def archive(request, id): - draft = File.objects.select_related('uploader__user','uploader__department','designation').filter(is_read=True).order_by('-upload_date') + draft = File.objects.select_related('uploader__user', 'uploader__department', 'designation').filter( + is_read=True).order_by('-upload_date') - - extrainfo = ExtraInfo.objects.select_related('user','department').all() + extrainfo = ExtraInfo.objects.select_related('user', 'department').all() # designations = Designation.objects.filter(upload_designation=extrainfo.id) - abcd = HoldsDesignation.objects.select_related('user','working','designation').get(pk=id) + abcd = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(pk=id) s = str(abcd).split(" - ") designations = s[1] - #designations = HoldsDesignation.objects.filter(user=request.user) + # designations = HoldsDesignation.objects.filter(user=request.user) # for x in designations: # if abcd==x: # designations=abcd @@ -462,46 +463,38 @@ def archive(request , id): 'designations': designations, } + return render(request, 'filetracking/archive.html', context) - - return render(request, 'filetracking/archive.html' , context) - - -@login_required(login_url = "/accounts/login") +@login_required(login_url="/accounts/login") def archive_finish(request, id): - file1 = get_object_or_404(File, id=id) ##file = get_object_or_404(File, ref_id=id) + # file = get_object_or_404(File, ref_id=id) + file1 = get_object_or_404(File, id=id) track = Tracking.objects.filter(file_id=file1) - - return render(request, 'filetracking/archive_finish.html', {'file': file1, 'track': track}) - - -@login_required(login_url = "/accounts/login") +@login_required(login_url="/accounts/login") def finish_design(request): - designation = HoldsDesignation.objects.select_related('user','working','designation').filter(user=request.user) + designation = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').filter(user=request.user) context = { 'designation': designation, } - return render( request, 'filetracking/finish_design.html', context) + return render(request, 'filetracking/finish_design.html', context) -@login_required(login_url = "/accounts/login") +@login_required(login_url="/accounts/login") def finish_fileview(request, id): - out = Tracking.objects.select_related('file_id__uploader__user','file_id__uploader__department','file_id__designation','current_id__user','current_id__department', - 'current_design__user','current_design__working','current_design__designation','receiver_id','receive_design').filter(file_id__uploader=request.user.extrainfo, is_read=False).order_by('-forward_date') - - - - - abcd = HoldsDesignation.objects.select_related('user','working','designation').get(pk=id) + out = Tracking.objects.select_related('file_id__uploader__user', 'file_id__uploader__department', 'file_id__designation', 'current_id__user', 'current_id__department', + 'current_design__user', 'current_design__working', 'current_design__designation', 'receiver_id', 'receive_design').filter(file_id__uploader=request.user.extrainfo, is_read=False).order_by('-forward_date') + abcd = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(pk=id) context = { @@ -511,29 +504,19 @@ def finish_fileview(request, id): return render(request, 'filetracking/finish_fileview.html', context) - - -@login_required(login_url = "/accounts/login") +@login_required(login_url="/accounts/login") def finish(request, id): - file1 = get_object_or_404(File, id=id) ##file = get_object_or_404(File, ref_id=id) + # file = get_object_or_404(File, ref_id=id) + file1 = get_object_or_404(File, id=id) track = Tracking.objects.filter(file_id=file1) - if request.method == "POST": - if 'Finished' in request.POST: - File.objects.filter(pk=id).update(is_read=True) - track.update(is_read=True) - messages.success(request,'File Archived') - - - - - - - - return render(request, 'filetracking/finish.html', {'file': file1, 'track': track,'fileid':id}) - + if 'Finished' in request.POST: + File.objects.filter(pk=id).update(is_read=True) + track.update(is_read=True) + messages.success(request, 'File Archived') + return render(request, 'filetracking/finish.html', {'file': file1, 'track': track, 'fileid': id}) def AjaxDropdown1(request): @@ -542,7 +525,7 @@ def AjaxDropdown1(request): @param: request - trivial. - + @variables: context - return the httpresponce containing the matched designation of the user @@ -553,20 +536,19 @@ def AjaxDropdown1(request): hold = Designation.objects.filter(name__startswith=value) holds = serializers.serialize('json', list(hold)) context = { - 'holds' : holds + 'holds': holds } return HttpResponse(JsonResponse(context), content_type='application/json') def AjaxDropdown(request): - """ This function returns the usernames of receiver on the forward or compose file template. @param: request - trivial. - + @variables: context - return the httpresponce containing the matched username @@ -586,27 +568,22 @@ def test(request): return HttpResponse('success') - -@login_required(login_url = "/accounts/login") -def delete(request,id): - +@login_required(login_url="/accounts/login") +def delete(request, id): """ The function is used the delete of a file and it returns to the drafts page. @param: request - trivial. id - id of the file that is going to be deleted - + """ - file = File.objects.get(pk = id) + file = File.objects.get(pk=id) file.delete() return redirect('/filetracking/drafts/') - - -def forward_inward(request,id): - +def forward_inward(request, id): """ This function is used forward the files which are available in the inbox of the user . @param: @@ -617,21 +594,19 @@ def forward_inward(request,id): file - file object track - tracking object of the file context - necessary data to render - + """ file = get_object_or_404(File, id=id) file.is_read = True - track = Tracking.objects.select_related('file_id__uploader__user','file_id__uploader__department','file_id__designation','current_id__user','current_id__department', - 'current_design__user','current_design__working','current_design__designation','receiver_id','receive_design').filter(file_id=file) + track = Tracking.objects.select_related('file_id__uploader__user', 'file_id__uploader__department', 'file_id__designation', 'current_id__user', 'current_id__department', + 'current_design__user', 'current_design__working', 'current_design__designation', 'receiver_id', 'receive_design').filter(file_id=file) designations = get_designation(request.user) context = { - - 'designations':designations, + + 'designations': designations, 'file': file, 'track': track, } - return render(request, 'filetracking/forward.html', context) - - + return render(request, 'filetracking/forward.html', context) \ No newline at end of file diff --git a/FusionIIIT/applications/programme_curriculum/migrations/0002_auto_20240217_1615.py b/FusionIIIT/applications/programme_curriculum/migrations/0002_auto_20240217_1615.py new file mode 100644 index 000000000..cd57f443c --- /dev/null +++ b/FusionIIIT/applications/programme_curriculum/migrations/0002_auto_20240217_1615.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.5 on 2024-02-17 16:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('programme_curriculum', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='batch', + name='year', + field=models.PositiveIntegerField(default=2024), + ), + migrations.AlterField( + model_name='programme', + name='programme_begin_year', + field=models.PositiveIntegerField(default=2024), + ), + ] diff --git a/FusionIIIT/applications/ps1/urls.py b/FusionIIIT/applications/ps1/urls.py index e8b3ad417..43f7299a4 100644 --- a/FusionIIIT/applications/ps1/urls.py +++ b/FusionIIIT/applications/ps1/urls.py @@ -24,5 +24,6 @@ url(r'^stock_edit/$', views.stock_edit, name='stock_edit'), url(r'^stock_update/$', views.stock_update, name='stock_update'), url(r'^entry/$', views.entry, name='entry'), - url(r'^stock_login/$', views.dealing_assistant, name='dealing_assistant') + url(r'^stock_login/$', views.dealing_assistant, name='dealing_assistant'), + url(r'^generate_report/$', views.generate_report, name='generate_report') ] diff --git a/FusionIIIT/applications/ps1/views.py b/FusionIIIT/applications/ps1/views.py index 15168a6b9..b97dc7529 100644 --- a/FusionIIIT/applications/ps1/views.py +++ b/FusionIIIT/applications/ps1/views.py @@ -1,6 +1,6 @@ from django.contrib import messages from django.shortcuts import render, get_object_or_404, redirect -from applications.filetracking.models import File, Tracking +from applications.filetracking.sdk.methods import * from applications.ps1.models import IndentFile,StockEntry from applications.globals.models import ExtraInfo, HoldsDesignation, Designation from django.template.defaulttags import csrf_token @@ -14,6 +14,15 @@ @login_required(login_url = "/accounts/login/") def ps1(request): + # print("-------------------------------------------------") + # print(request.user) + # print("-------------------------------------------------") + # print("-------------------------------------------------") + # print(request.GET) + # print("-------------------------------------------------") + # print("-------------------------------------------------") + # print(request.body) + # print("-------------------------------------------------") """ The function is used to create indents by faculty. It adds the indent datails to the indet_table of Purchase and Store module @@ -47,11 +56,20 @@ def ps1(request): purchased =request.POST.get('purchased') """ des = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() + print("-------------------------------------------------") + print("designation ") + print(des.designation) + print("-------------------------------------------------") if str(des.designation) == "student": return redirect('/dashboard') + + if str(des.designation) == "dept_admin": + return redirect('/purchase-and-store/entry/') + if request.user.extrainfo.id == '132': return redirect("/purchase-and-store/entry/") - if request.method =="POST": + + if request.method =="POST" and str(des.designation) == "Assistant Professor": try: if 'save' in request.POST: uploader = request.user.extrainfo @@ -136,35 +154,7 @@ def ps1(request): financial_approval=False purchased = False - file = File.objects.create( - uploader=uploader, - description=description, - subject=subject, - designation=designation, - upload_file=upload_file - ) - - IndentFile.objects.create( - file_info=file, - item_name= item_name, - quantity=quantity, - present_stock=present_stock, - estimated_cost=estimated_cost, - purpose=purpose, - specification=specification, - indent_type=indent_type, - nature=nature, - indigenous=indigenous, - replaced = replaced , - budgetary_head=budgetary_head, - expected_delivery=expected_delivery, - sources_of_supply=sources_of_supply, - head_approval=head_approval, - director_approval=director_approval, - financial_approval=financial_approval, - purchased =purchased, - ) current_id = request.user.extrainfo @@ -186,17 +176,54 @@ def ps1(request): messages.error(request, 'Enter a valid Designation') return redirect('/ps1/') - upload_file = request.FILES.get('myfile') - Tracking.objects.create( - file_id=file, - current_id=current_id, - current_design=current_design, - receive_design=receive_design, - receiver_id=receiver_id, - remarks=remarks, - upload_file=upload_file, + file_id = create_file( + uploader=request.user, + uploader_designation=designation, + receiver= receiver_id, + receiver_designation=receive_design, + src_module="ps1", + src_object_id="", + file_extra_JSON={"value": 2}, + attached_file=request.FILES.get('myfile') + # description=description, + # subject=subject, + # designation=designation, + # upload_file=upload_file ) + + IndentFile.objects.create( + file_info=get_object_or_404(File, pk=file_id), + item_name= item_name, + quantity=quantity, + present_stock=present_stock, + estimated_cost=estimated_cost, + purpose=purpose, + specification=specification, + indent_type=indent_type, + nature=nature, + indigenous=indigenous, + replaced = replaced , + budgetary_head=budgetary_head, + expected_delivery=expected_delivery, + sources_of_supply=sources_of_supply, + head_approval=head_approval, + director_approval=director_approval, + financial_approval=financial_approval, + purchased =purchased, + ) + + + + # Tracking.objects.create( + # file_id=file, + # current_id=current_id, + # current_design=current_design, + # receive_design=receive_design, + # receiver_id=receiver_id, + # remarks=remarks, + # upload_file=upload_file, + # ) office_module_notif(request.user, receiver_id) messages.success(request,'Indent Filed Successfully!') @@ -295,6 +322,16 @@ def drafts(request): @login_required(login_url = "/accounts/login") def indentview(request,id): + # des = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() + # print(des) + # # designation = Designation.objects.get(id = HoldsDesignation.objects.select_related('user','working','designation').get(id = design).designation_id) + # outbox_files = view_outbox( + # username=request.user, + # designation=des.designation, + # src_module="ps1" + # ) + + # print(outbox_files) tracking_objects=Tracking.objects.all() @@ -438,9 +475,13 @@ def forwardindent(request, id): current_id = request.user.extrainfo remarks = request.POST.get('remarks') - sender = request.POST.get('sender') - current_design = HoldsDesignation.objects.select_related('user','working','designation').get(id=sender) - + # sender = request.POST.get('sender') + # sender = request.user.id + print("-----------------------------------------------") + print(request.user.id) + print("-----------------------------------------------") + # current_design = HoldsDesignation.objects.select_related('user','working','designation').get(id=sender) + current_design = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() receiver = request.POST.get('receiver') try: receiver_id = User.objects.get(username=receiver) @@ -475,6 +516,16 @@ def forwardindent(request, id): # receive_design = receive_designation[0] upload_file = request.FILES.get('myfile') # return HttpResponse ("success") + # print("--------------------------------------------") + # print(file) + forwarded_file_id = forward_file( + file_id=file.id, + receiver=receiver_id, + receiver_designation=receive_design, + file_extra_JSON={"key": 2}, + remarks="Forwarding", + file_attachment=None + ) Tracking.objects.create( file_id=file, current_id=current_id, @@ -815,8 +866,21 @@ def stock_update(request): # return render(request,'ps1/stock_view.html',{'StockEntry':sto}) # @login_required(login_url = "/accounts/login") def stock_view(request): - - sto=StockEntry.objects.all() + + # stock_entries = StockEntry.objects.filter( + # item_id__file_info__designation__name='Professor' + # ) + # print(stock_entries) + + des = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() + department = request.user.extrainfo.department.name + + if str(des.designation) == "dept_admin": + sto=StockEntry.objects.filter(item_id__file_info__uploader__department__name=department) + else: + sto=StockEntry.objects.all() + # print(request.user) + if sto: temp=sto.first() @@ -850,8 +914,15 @@ def entry(request): - - ent=IndentFile.objects.all() + # ent=IndentFile.objects.all() + des = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() + department = request.user.extrainfo.department.name + + if str(des.designation) == "dept_admin": + ent=IndentFile.objects.filter(file_info__uploader__department__name=department) + # sto=StockEntry.objects.filter(item_id__file_info__uploader__department__name=department) + else: + ent=IndentFile.objects.all() return render(request,'ps1/entry.html',{'ent':ent}) def dealing_assistant(request): @@ -861,3 +932,22 @@ def dealing_assistant(request): return redirect('/ps1/entry/') else: return redirect('/ps1') + + +@login_required(login_url = "/accounts/login") +def generate_report(request): + + # stock_entries = StockEntry.objects.filter( + # item_id__file_info__designation__name='Professor' + # ) + # print(stock_entries) + + des = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() + department = request.user.extrainfo.department.name + + if str(des.designation) == "dept_admin": + sto=StockEntry.objects.filter(item_id__file_info__uploader__department__name=department) + else: + sto=StockEntry.objects.all() + + return render(request,'ps1/generate_report.html',{'sto':sto}) \ No newline at end of file diff --git a/FusionIIIT/applications/scholarships/migrations/0002_auto_20240217_1615.py b/FusionIIIT/applications/scholarships/migrations/0002_auto_20240217_1615.py new file mode 100644 index 000000000..837e5a1ad --- /dev/null +++ b/FusionIIIT/applications/scholarships/migrations/0002_auto_20240217_1615.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.5 on 2024-02-17 16:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('scholarships', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='previous_winner', + name='year', + field=models.IntegerField(default=2024), + ), + ] diff --git a/FusionIIIT/templates/ps1/generate_report.html b/FusionIIIT/templates/ps1/generate_report.html new file mode 100644 index 000000000..f9e356385 --- /dev/null +++ b/FusionIIIT/templates/ps1/generate_report.html @@ -0,0 +1,279 @@ +{% extends 'ps1/ps2.html' %} +{% load static %} + +{% block filetracking_tab %} + + + +
+ +
+
+ +
+ + + + +
+ {% if sto %} + + + + + + + + + + + + + + + {% for s in sto %} + {% if s.item_id.purchased %} + + + + + + + + + + + + + + + + {% endif %} + + {% endfor %} + + +
item_idStock_NameQuantity dealing assistant idDepartmentEdit stocks Delete stocks
{{s.item_id.file_info.id}}{{s.item_name}}{{s.current_stock}}{{s.dealing_assistant_id}}{{s.item_id.file_info.uploader.department.name}}
{% csrf_token %} + + +
+
{% csrf_token %} + + +
+
+ +
+ {% else %} +

No Records present in database

+ {% endif %} + + + + + +
+ + + + +{% endblock %} + + diff --git a/requirements.txt b/requirements.txt index 4cc3a0a30..fc7464f24 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ amqp==5.0.2 -arabic-reshaper==2.1.1 +arabic-reshaper==3.0.0 asgiref==3.3.1 attrs==20.3.0 beautifulsoup4==4.9.3 From d65e0a117a67bd16198de7fa18c79c231cdda8d1 Mon Sep 17 00:00:00 2001 From: Aniket Date: Fri, 23 Feb 2024 11:50:28 +0530 Subject: [PATCH 02/19] ps1 changes --- FusionIIIT/Fusion/settings/development.py | 2 +- .../ps1/migrations/0002_auto_20240219_2009.py | 28 ++ FusionIIIT/applications/ps1/models.py | 3 + FusionIIIT/applications/ps1/urls.py | 8 +- FusionIIIT/applications/ps1/views.py | 190 ++++++++++---- FusionIIIT/templates/ps1/composeIndent.html | 20 +- FusionIIIT/templates/ps1/forwardindent.html | 13 +- FusionIIIT/templates/ps1/generate_report.html | 11 +- .../templates/ps1/perform_transfer1.html | 162 ++++++++++++ FusionIIIT/templates/ps1/ps2.html | 9 +- FusionIIIT/templates/ps1/report.html | 246 ++++++++++++++++++ FusionIIIT/templates/ps1/stock_transfer.html | 158 +++++++++++ 12 files changed, 774 insertions(+), 76 deletions(-) create mode 100644 FusionIIIT/applications/ps1/migrations/0002_auto_20240219_2009.py create mode 100644 FusionIIIT/templates/ps1/perform_transfer1.html create mode 100644 FusionIIIT/templates/ps1/report.html create mode 100644 FusionIIIT/templates/ps1/stock_transfer.html diff --git a/FusionIIIT/Fusion/settings/development.py b/FusionIIIT/Fusion/settings/development.py index 6acc214c1..5fd6a1e2e 100644 --- a/FusionIIIT/Fusion/settings/development.py +++ b/FusionIIIT/Fusion/settings/development.py @@ -9,7 +9,7 @@ DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': 'fusionlab', + 'NAME': 'fusionlab2', 'HOST': os.environ.get("DB_HOST", default='localhost'), 'USER': 'fusion_admin', 'PASSWORD': 'hello123', diff --git a/FusionIIIT/applications/ps1/migrations/0002_auto_20240219_2009.py b/FusionIIIT/applications/ps1/migrations/0002_auto_20240219_2009.py new file mode 100644 index 000000000..c72ddbdfc --- /dev/null +++ b/FusionIIIT/applications/ps1/migrations/0002_auto_20240219_2009.py @@ -0,0 +1,28 @@ +# Generated by Django 3.1.5 on 2024-02-19 20:09 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ps1', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='stockentry', + name='dept', + field=models.CharField(max_length=250, null=True), + ), + migrations.AddField( + model_name='stockentry', + name='to_dept', + field=models.CharField(max_length=250, null=True), + ), + migrations.AddField( + model_name='stockentry', + name='transfer', + field=models.BooleanField(default=False, null=True), + ), + ] diff --git a/FusionIIIT/applications/ps1/models.py b/FusionIIIT/applications/ps1/models.py index bee76f36e..cf8e69b07 100644 --- a/FusionIIIT/applications/ps1/models.py +++ b/FusionIIIT/applications/ps1/models.py @@ -36,6 +36,9 @@ class StockEntry(models.Model): current_stock=models.IntegerField(blank=False) recieved_date=models.DateField(blank=False) bill=models.FileField(blank=False) + transfer = models.BooleanField(default = False, null=True) + dept = models.CharField(max_length=250,null=True, blank=False) + to_dept = models.CharField(max_length=250,null=True, blank=False) class Meta: db_table = 'StockEntry' \ No newline at end of file diff --git a/FusionIIIT/applications/ps1/urls.py b/FusionIIIT/applications/ps1/urls.py index 43f7299a4..fe6324087 100644 --- a/FusionIIIT/applications/ps1/urls.py +++ b/FusionIIIT/applications/ps1/urls.py @@ -7,6 +7,7 @@ urlpatterns = [ url(r'^$', views.ps1, name='ps1'), + url(r'^create_proposal/$', views.create_proposal, name='create_proposal'), # url(r'^compose_indent/$', views.compose_indent, name='compose_indent'), url(r'^composed_indents/$', views.composed_indents, name='composed_indents'), url(r'^indentview/(?P\d+)$', views.indentview, name='indentview'), @@ -25,5 +26,10 @@ url(r'^stock_update/$', views.stock_update, name='stock_update'), url(r'^entry/$', views.entry, name='entry'), url(r'^stock_login/$', views.dealing_assistant, name='dealing_assistant'), - url(r'^generate_report/$', views.generate_report, name='generate_report') + url(r'^generate_report/$', views.generate_report, name='generate_report'), + url(r'^report/$', views.report, name='report'), + url(r'view-bill//$', views.view_bill, name='view_bill'), + url(r'^perform_transfer/$', views.perform_transfer, name='perform_transfer'), + url(r'^stock_transfer/$', views.stock_transfer, name='stock_transfer') + ] diff --git a/FusionIIIT/applications/ps1/views.py b/FusionIIIT/applications/ps1/views.py index b97dc7529..0374c3d6d 100644 --- a/FusionIIIT/applications/ps1/views.py +++ b/FusionIIIT/applications/ps1/views.py @@ -11,18 +11,32 @@ from django.contrib.auth.models import User from timeit import default_timer as time from notification.views import office_module_notif +from django.utils import timezone + + @login_required(login_url = "/accounts/login/") def ps1(request): - # print("-------------------------------------------------") - # print(request.user) - # print("-------------------------------------------------") - # print("-------------------------------------------------") - # print(request.GET) - # print("-------------------------------------------------") - # print("-------------------------------------------------") - # print(request.body) - # print("-------------------------------------------------") + des_obj = HoldsDesignation.objects.filter(user=request.user) + + if des_obj: + designations = [des.designation.name for des in des_obj] + + + if "ps_admin" in designations or "dept_admin" in designations: + return redirect('/purchase-and-store/entry/') + elif not("student" in designations) and str((request.user.extrainfo.department.name)): + return redirect('/purchase-and-store/create_proposal/') + else: + return redirect('/dashboard') + + + + + + +@login_required(login_url = "/accounts/login/") +def create_proposal(request): """ The function is used to create indents by faculty. It adds the indent datails to the indet_table of Purchase and Store module @@ -56,20 +70,8 @@ def ps1(request): purchased =request.POST.get('purchased') """ des = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() - print("-------------------------------------------------") - print("designation ") - print(des.designation) - print("-------------------------------------------------") - if str(des.designation) == "student": - return redirect('/dashboard') - - if str(des.designation) == "dept_admin": - return redirect('/purchase-and-store/entry/') - if request.user.extrainfo.id == '132': - return redirect("/purchase-and-store/entry/") - - if request.method =="POST" and str(des.designation) == "Assistant Professor": + if request.method =="POST": try: if 'save' in request.POST: uploader = request.user.extrainfo @@ -128,6 +130,7 @@ def ps1(request): ) if 'send' in request.POST: + uploader = request.user.extrainfo subject = request.POST.get('title') description = request.POST.get('desc') @@ -153,6 +156,13 @@ def ps1(request): director_approval=False financial_approval=False purchased = False + designations = HoldsDesignation.objects.select_related('user','working','designation').filter(user = request.user) + for des in designations: + if str(des.designation) == "Director": + head_approval=True + director_approval=True + financial_approval=True + break @@ -163,18 +173,19 @@ def ps1(request): sender = request.POST.get('design') current_design = HoldsDesignation.objects.select_related('user','working','designation').get(id=sender) + receiver = request.POST.get('receiver') try: receiver_id = User.objects.get(username=receiver) except Exception as e: messages.error(request, 'Enter a valid Username') return redirect('/filetracking/') - receive = request.POST.get('recieve') + receive = request.POST.get('receive') try: receive_design = Designation.objects.get(name=receive) except Exception as e: messages.error(request, 'Enter a valid Designation') - return redirect('/ps1/') + return redirect('/create_proposal/') file_id = create_file( @@ -186,10 +197,6 @@ def ps1(request): src_object_id="", file_extra_JSON={"value": 2}, attached_file=request.FILES.get('myfile') - # description=description, - # subject=subject, - # designation=designation, - # upload_file=upload_file ) IndentFile.objects.create( @@ -213,17 +220,6 @@ def ps1(request): purchased =purchased, ) - - - # Tracking.objects.create( - # file_id=file, - # current_id=current_id, - # current_design=current_design, - # receive_design=receive_design, - # receiver_id=receiver_id, - # remarks=remarks, - # upload_file=upload_file, - # ) office_module_notif(request.user, receiver_id) messages.success(request,'Indent Filed Successfully!') @@ -234,12 +230,31 @@ def ps1(request): extrainfo = ExtraInfo.objects.select_related('user','department').all() holdsdesignations = HoldsDesignation.objects.select_related('user','working','designation').all() designations = HoldsDesignation.objects.select_related('user','working','designation').filter(user = request.user) + today = timezone.now().strftime('%Y-%m-%d') + + Receiver_designation = "HOD (" + get_ExtraInfo_object_from_username(request.user.username).department.name + ")" + + for des in designations: + if str(des.designation) == Receiver_designation: + Receiver_designation = "Director" + break + elif str(des.designation) == "Director": + Receiver_designation = "ps_admin" + break + + + users_with_designation = HoldsDesignation.objects.filter(designation__name=Receiver_designation) + Forward_to = [user_designation.user for user_designation in users_with_designation] context = { 'file': file, 'extrainfo': extrainfo, 'holdsdesignations': holdsdesignations, 'designations': designations, + 'today': today, + 'receiver':Receiver_designation, + 'forwardto': Forward_to + } return render(request, 'ps1/composeIndent.html', context) @@ -477,9 +492,6 @@ def forwardindent(request, id): # sender = request.POST.get('sender') # sender = request.user.id - print("-----------------------------------------------") - print(request.user.id) - print("-----------------------------------------------") # current_design = HoldsDesignation.objects.select_related('user','working','designation').get(id=sender) current_design = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() receiver = request.POST.get('receiver') @@ -566,14 +578,14 @@ def forwardindent(request, id): if val=="accept": - if any(d in designs for d in ("HOD (ME)", "HOD (ECE)", "CSE HOD", "HOD (Design)", "HOD (NS)")): + if any(d in designs for d in ("HOD (ME)", "HOD (ECE)", "HOD (CSE)", "HOD (Design)", "HOD (NS)")): indent.head_approval=True elif "Director" in designs: indent.director_approval=True indent.financial_approval=True else: - if any(d in designs for d in ("HOD (ME)", "HOD (ECE)", "CSE HOD", "HOD (Design)", "HOD (NS)")): + if any(d in designs for d in ("HOD (ME)", "HOD (ECE)", "HOD (CSE)", "HOD (Design)", "HOD (NS)")): indent.head_approval=False elif "Director" in designs: indent.director_approval=False @@ -589,6 +601,14 @@ def forwardindent(request, id): holdsdesignations = HoldsDesignation.objects.select_related('user','working','designation').all() designations = HoldsDesignation.objects.select_related('user','working','designation').filter(user=request.user) + Receiver_designation = "dept_admin "+get_ExtraInfo_object_from_username(request.user.username).department.name + users_with_designation = HoldsDesignation.objects.filter(designation__name=Receiver_designation) + Forward_to = [user_designation.user for user_designation in users_with_designation] + + + + + context = { # 'extrainfo': extrainfo, # 'holdsdesignations': holdsdesignations, @@ -596,6 +616,8 @@ def forwardindent(request, id): 'file': file, 'track': track, 'indent':indent, + 'receiver':Receiver_designation, + 'forwardto': Forward_to } return render(request, 'ps1/forwardindent.html', context) @@ -854,6 +876,7 @@ def stock_update(request): stocks.current_stock=request.POST.get('current_stock') #stocks.recieved_date=request.POST.get('recieved_date') stocks.bill=request.FILES.get('bill') + stocks.dept = request.POST.get('dept') stocks.save() return HttpResponseRedirect('../stock_view') @@ -886,8 +909,6 @@ def stock_view(request): if temp.item_id.purchased: print("Purchase Succesful") - print() - print() return render(request,'ps1/stock_view.html',{'sto':sto}) @login_required(login_url = "/accounts/login") @@ -937,10 +958,60 @@ def dealing_assistant(request): @login_required(login_url = "/accounts/login") def generate_report(request): - # stock_entries = StockEntry.objects.filter( - # item_id__file_info__designation__name='Professor' - # ) - # print(stock_entries) + des = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() + department = request.user.extrainfo.department.name + + if str(des.designation) == "dept_admin": + sto=StockEntry.objects.filter(item_id__file_info__uploader__department__name=department) + else: + sto=StockEntry.objects.all() + + return render(request,'ps1/generate_report.html',{'sto':sto}) + + +@login_required(login_url = "/accounts/login") +def report(request): + id=request.POST.get('id') + designations = HoldsDesignation.objects.select_related('user','working','designation').filter(user=request.user) + indent=IndentFile.objects.select_related('file_info').get(file_info=id) + sto=StockEntry.objects.select_related('item_id').get(item_id=indent) + file=indent.file_info + total_stock = indent.quantity + indent.present_stock + + print(sto.recieved_date) + + context = { + 'designations':designations, + 'file': file, + 'indent':indent, + 'sto' : sto, + 'total_stock': total_stock + } + + return render(request,'ps1/report.html',context) + + +def view_bill(request, stock_entry_id): + stock_entry = get_object_or_404(StockEntry, pk=stock_entry_id) + + # Check if the bill file exists + if stock_entry.bill: + # Read the contents of the bill file + bill_content = stock_entry.bill.read() + + # Return the bill file as a response + response = HttpResponse(bill_content, content_type='application/pdf') + response['Content-Disposition'] = f'attachment; filename="{stock_entry.bill.name}"' + return response + else: + # If the bill file does not exist, return a 404 response + return HttpResponse("Bill not found", status=404) + + + + +@login_required(login_url = "/accounts/login") +def perform_transfer(request): des = HoldsDesignation.objects.all().select_related().filter(user = request.user).first() department = request.user.extrainfo.department.name @@ -950,4 +1021,21 @@ def generate_report(request): else: sto=StockEntry.objects.all() - return render(request,'ps1/generate_report.html',{'sto':sto}) \ No newline at end of file + return render(request,'ps1/perform_transfer1.html',{'sto':sto}) + + + +@login_required(login_url = "/accounts/login") +def stock_transfer(request): + # stocks=StockEntry.objects.get(pk=id) + # return render(request,'ps1/stock_edit.html',{'StockEntry':stocks}) + + + if request.method =="POST": + id=request.POST.get('id') + temp=File.objects.get(id=id) + temp1=IndentFile.objects.get(file_info=temp) + stocks=StockEntry.objects.get(item_id=temp1) + return render(request,'ps1/stock_transfer.html',{'StockEntry':stocks}) + + return HttpResponseRedirect('../stock_transfer') \ No newline at end of file diff --git a/FusionIIIT/templates/ps1/composeIndent.html b/FusionIIIT/templates/ps1/composeIndent.html index 8fa6269ad..716ae415e 100644 --- a/FusionIIIT/templates/ps1/composeIndent.html +++ b/FusionIIIT/templates/ps1/composeIndent.html @@ -87,7 +87,7 @@

- +
@@ -169,20 +169,24 @@

Replaced*