From 084ed26dd50eaa49555955db11b3212025f6f2f7 Mon Sep 17 00:00:00 2001 From: Srivatsa19 Date: Thu, 22 Feb 2024 19:43:54 +0530 Subject: [PATCH 1/2] Implemented the cerate_request, process_request and approve/reject_request use cases. --- FusionIIIT/applications/iwdModuleV2/models.py | 19 +++ FusionIIIT/applications/iwdModuleV2/urls.py | 13 +- FusionIIIT/applications/iwdModuleV2/views.py | 135 +++++++++++++++- .../templates/dashboard/sidenavbar.html | 6 +- .../templates/iwdModuleV2/billsView.html | 147 ++++++++++++++++++ .../iwdModuleV2/createdRequests.html | 120 ++++++++++++++ .../templates/iwdModuleV2/dashboard.html | 77 ++++++--- .../iwdModuleV2/deanProcessedRequests.html | 96 ++++++++++++ .../engineerProcessedRequests.html | 121 ++++++++++++++ .../templates/iwdModuleV2/requestsStatus.html | 114 ++++++++++++++ .../templates/iwdModuleV2/requestsView.html | 124 +++++++++++++++ requirements.txt | 2 +- 12 files changed, 943 insertions(+), 31 deletions(-) create mode 100644 FusionIIIT/templates/iwdModuleV2/billsView.html create mode 100644 FusionIIIT/templates/iwdModuleV2/createdRequests.html create mode 100644 FusionIIIT/templates/iwdModuleV2/deanProcessedRequests.html create mode 100644 FusionIIIT/templates/iwdModuleV2/engineerProcessedRequests.html create mode 100644 FusionIIIT/templates/iwdModuleV2/requestsStatus.html create mode 100644 FusionIIIT/templates/iwdModuleV2/requestsView.html diff --git a/FusionIIIT/applications/iwdModuleV2/models.py b/FusionIIIT/applications/iwdModuleV2/models.py index a5c40c7b2..c0754c70d 100644 --- a/FusionIIIT/applications/iwdModuleV2/models.py +++ b/FusionIIIT/applications/iwdModuleV2/models.py @@ -160,3 +160,22 @@ class NoOfTechnicalBidTimes(models.Model): key = models.ForeignKey(Projects, on_delete=models.CASCADE, unique=True) number = models.IntegerField() +class Requests(models.Model): + # id = models.IntegerField(primary_key=True, max_length=200) + name = models.CharField(max_length=200) + description = models.CharField(max_length=200) + area = models.CharField(max_length=200) + requestCreatedBy = models.CharField(max_length=200) + engineerProcessed = models.IntegerField() + directorApproval = models.IntegerField() + deanProcessed = models.IntegerField() + status = models.CharField(max_length=200) + +class Bills(models.Model): + key = models.ForeignKey(Projects, on_delete=models.CASCADE, unique=True) + name = models.CharField(max_length=200) + work = models.CharField(max_length=200) + description = models.CharField(max_length=200) + agency = models.CharField(max_length=200) + bill_processed = models.IntegerField() + bill_settled = models.IntegerField() \ No newline at end of file diff --git a/FusionIIIT/applications/iwdModuleV2/urls.py b/FusionIIIT/applications/iwdModuleV2/urls.py index 6ad401098..2f047d690 100644 --- a/FusionIIIT/applications/iwdModuleV2/urls.py +++ b/FusionIIIT/applications/iwdModuleV2/urls.py @@ -36,5 +36,16 @@ url(r'milestoneView/$', views.milestoneView, name='Milestones'), url(r'addendumView/$', views.addendumView, name='Addendum View'), url('agreementView/$', views.agreementView, name='Agreement VIew'), - url(r'corrigendumView/$', views.corrigendumView, name='Corrigendum View') + url(r'corrigendumView/$', views.corrigendumView, name='Corrigendum View'), + url('requestsView/',views.requestsView, name='Requests view'), + url('createdRequestsView/',views.createdRequests, name='Created Requests view'), + url('handleEngineerProcessRequests/', views.handleEngineerProcessRequests, name='Engineer-Process-Requests'), + url('engineerProcessedRequestsView/',views.engineerProcessedRequests, name='Engineer-Processed-Requests view'), + url('handleDeanProcessRequests/', views.handleDeanProcessRequests, name='Dean-Process-Requests'), + url('deanProcessedRequestsView/',views.deanProcessedRequests, name='Dean-Processed-Requests view'), + url('handleDirectorApprovalRequests/', views.handleDirectorApprovalRequests, name='Director-Approval-Requests'), + url('handleDirectorRejectionRequests/', views.handleDirectorRejectionRequests, name='Director-Rejection-Requests'), + url('requestsStatus/', views.requestsStatus, name='Requests-Status'), + url('billsView/',views.billsView, name='Bills View'), + ] diff --git a/FusionIIIT/applications/iwdModuleV2/views.py b/FusionIIIT/applications/iwdModuleV2/views.py index 2b36550fc..0a532548d 100644 --- a/FusionIIIT/applications/iwdModuleV2/views.py +++ b/FusionIIIT/applications/iwdModuleV2/views.py @@ -1,5 +1,5 @@ from django.shortcuts import render, redirect - +from django.db.models import Q from applications.globals.models import * from .models import * from django.http import HttpResponseRedirect @@ -17,17 +17,24 @@ # owing to length and inherent extensiveness of code. Rather than, whosoever read this code is advised to do so # in conjunction with SRS. After that, everything will become easier. +# def dashboard(request): +# eligible = False +# userObj = request.user +# userDesignationObjects = HoldsDesignation.objects.filter(user=userObj) +# for p in userDesignationObjects: +# if p.designation.name == 'Admin IWD': +# eligible = True +# break +# return render(request, 'iwdModuleV2/dashboard.html', {'eligible': eligible}) + def dashboard(request): - eligible = False + eligible = "" userObj = request.user userDesignationObjects = HoldsDesignation.objects.filter(user=userObj) for p in userDesignationObjects: - if p.designation.name == 'Admin IWD': - eligible = True - break + eligible = p.designation.name return render(request, 'iwdModuleV2/dashboard.html', {'eligible': eligible}) - def page1_1(request): if request.method == 'POST': formObject = PageOneDetails() @@ -401,3 +408,119 @@ def page3View(request): def extensionFormView(request): extensionObjects = ExtensionOfTimeDetails.objects.filter(key=Projects.objects.get(id=request.session['projectId'])) return render(request, 'iwdModuleV2/ExtensionForm.html', {'extension': extensionObjects}) + +def requestsView(request): + if request.method == 'POST': + formObject = Requests() + # formObject.key = Projects.objects.get(id=request.session['projectId']) + formObject.name = request.POST['name'] + formObject.description = request.POST['description'] + formObject.area = request.POST['area'] + formObject.engineerProcessed = 0 + formObject.directorApproval = 0 + formObject.deanProcessed = 0 + formObject.requestCreatedBy = request.user.username + formObject.status = "Pending" + formObject.save() + return redirect('http://127.0.0.1:8000/iwdModuleV2/') + return render(request, 'http://127.0.0.1:8000/iwdModuleV2/', {}) + + +def billsView(request): + if request.method == 'POST': + formObject = Requests() + # formObject.key = Projects.objects.get(id=request.session['projectId']) + formObject.name = request.POST['name'] + formObject.work = request.POST['work'] + formObject.description = request.POST['description'] + formObject.agency = request.POST['agency'] + formObject.bill_processed = request.POST['bill_processed'] + formObject.bill_settled = request.POST['bill_settled'] + formObject.save() + return redirect('iwdModuleV2/billsView.html') + return render(request, 'iwdModuleV2/billsView.html', {}) + +def createdRequests(request): + obj = [] + requestsObject = Requests.objects.exclude( + Q(requestCreatedBy=request.user.username) | + Q(engineerProcessed__gt=0) | + Q(deanProcessed__gt=0) | + Q(directorApproval__gt=0) + ) + + for x in requestsObject: + element = [x.id, x.name, x.area, x.description, x.requestCreatedBy] + obj.append(element) + return render(request, 'iwdModuleV2/createdRequests.html', {'obj' : obj}) + +def handleEngineerProcessRequests(request): + if request.method == 'POST': + request_id = request.POST.get("id", 0) + Requests.objects.filter(id=request_id).update(engineerProcessed=1, status="Approved by the engineer") + obj = [] + requestsObject = Requests.objects.filter(engineerProcessed = 0, deanProcessed = 0, directorApproval = 0) + for x in requestsObject: + element = [x.id, x.name, x.area, x.description, x.requestCreatedBy] + obj.append(element) + return render(request, 'iwdModuleV2/createdRequests.html', {'obj' : obj}) + +def engineerProcessedRequests(request): + obj = [] + requestsObject = Requests.objects.filter(engineerProcessed = 1, deanProcessed = 0, directorApproval = 0) + for x in requestsObject: + element = [x.id, x.name, x.area, x.description, x.requestCreatedBy] + obj.append(element) + return render(request, 'iwdModuleV2/engineerProcessedRequests.html', {'obj' : obj}) + +def handleDeanProcessRequests(request): + if request.method == 'POST': + request_id = request.POST.get("id", 0) + Requests.objects.filter(id=request_id).update(deanProcessed=1, status="Approved by the dean") + obj = [] + requestsObject = Requests.objects.filter(engineerProcessed = 1, deanProcessed = 0, directorApproval = 0) + for x in requestsObject: + element = [x.id, x.name, x.area, x.description, x.requestCreatedBy] + obj.append(element) + return render(request, 'iwdModuleV2/engineerProcessedRequests.html', {'obj' : obj}) + +def deanProcessedRequests(request): + print(request) + obj = [] + requestsObject = Requests.objects.filter(engineerProcessed = 1, deanProcessed = 1, directorApproval = 0) + for x in requestsObject: + element = [x.id, x.name, x.area, x.description, x.requestCreatedBy] + obj.append(element) + return render(request, 'iwdModuleV2/deanProcessedRequests.html', {'obj' : obj}) + +def handleDirectorApprovalRequests(request): + if request.method == 'POST': + request_id = request.POST.get("id", 0) + Requests.objects.filter(id=request_id).update(directorApproval=1, status="Approved by the director") + obj = [] + requestsObject = Requests.objects.filter(engineerProcessed = 1, deanProcessed = 1, directorApproval = 0) + for x in requestsObject: + element = [x.id, x.name, x.area, x.description, x.requestCreatedBy] + obj.append(element) + return render(request, 'iwdModuleV2/deanProcessedRequests.html', {'obj' : obj}) + +def handleDirectorRejectionRequests(request): + if request.method == 'POST': + request_id = request.POST.get("id", 0) + Requests.objects.filter(id=request_id).update(directorApproval=-1, status="Rejected by the director") + obj = [] + requestsObject = Requests.objects.filter(engineerProcessed = 1, deanProcessed = 1, directorApproval = 0) + for x in requestsObject: + element = [x.id, x.name, x.area, x.description, x.requestCreatedBy] + obj.append(element) + return render(request, 'iwdModuleV2/deanProcessedRequests.html', {'obj' : obj}) + +def requestsStatus(request): + print(request) + obj = [] + requestsObject = Requests.objects.all() + for x in requestsObject: + element = [x.id, x.name, x.area, x.description, x.requestCreatedBy, x.status] + obj.append(element) + return render(request, 'iwdModuleV2/requestsStatus.html', {'obj' : obj}) + diff --git a/FusionIIIT/templates/dashboard/sidenavbar.html b/FusionIIIT/templates/dashboard/sidenavbar.html index 81cecbe94..fbf346e47 100644 --- a/FusionIIIT/templates/dashboard/sidenavbar.html +++ b/FusionIIIT/templates/dashboard/sidenavbar.html @@ -53,9 +53,9 @@

Programme & Curriculum Module

Gymkhana Module

- -

IWD Module

-
+ +

IWD Module

+
{% if request.user.extrainfo.user_type == 'faculty' or request.user.extrainfo.user_type == 'staff' %}

Establishment Module

diff --git a/FusionIIIT/templates/iwdModuleV2/billsView.html b/FusionIIIT/templates/iwdModuleV2/billsView.html new file mode 100644 index 000000000..89969b1b8 --- /dev/null +++ b/FusionIIIT/templates/iwdModuleV2/billsView.html @@ -0,0 +1,147 @@ +{% extends 'globals/base.html' %} +{% load static %} + + +{% block title %} + Academic +{% endblock %} + + +{% block body %} + {% block navBar %} + {% include 'dashboard/navbar.html' %} + {% endblock %} + +
+ + {% comment %}The left-margin segment!{% endcomment %} +
+ + {% comment %}The left-rail segment starts here!{% endcomment %} +
+ {% comment %}The user image card starts here!{% endcomment %} + {% block usercard %} + {% include 'globals/usercard.html' %} + {% endblock %} + {% comment %}The user image card ends here!{% endcomment %} + +
+ + {% comment %}The Tab-Menu ends here!{% endcomment %} +
+ {% comment %} + The left-rail segment ends here! + {% endcomment %} + + {% comment %} + The central-rail segment starts here! + {% endcomment %} +
+
+
+ +
+ {% comment %}the doctor appointment tab ends here {% endcomment %} + + + + + + {% comment %}The central-rail segment ends here!{% endcomment %} + + {% comment %}The right-rail segment starts here!{% endcomment %} +
+
+ {% comment %} + TODO: the right rail! + {% endcomment %} +
+
+ {% comment %}The right-rail segment ends here!{% endcomment %} + + {% comment %}The right-margin segment!{% endcomment %} +
+ + + {% comment %}The grid ends here!{% endcomment %} + +{% endblock %} + +{% block javascript %} + + + + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/iwdModuleV2/createdRequests.html b/FusionIIIT/templates/iwdModuleV2/createdRequests.html new file mode 100644 index 000000000..a7f86e523 --- /dev/null +++ b/FusionIIIT/templates/iwdModuleV2/createdRequests.html @@ -0,0 +1,120 @@ +{% extends 'globals/base.html' %} +{% load static %} + + +{% block title %} +Academic +{% endblock %} + + +{% block body %} +{% block navBar %} +{% include 'dashboard/navbar.html' %} +{% endblock %} + +
+ + {% comment %}The left-margin segment!{% endcomment %} +
+ + {% comment %}The left-rail segment starts here!{% endcomment %} +
+ {% comment %}The user image card starts here!{% endcomment %} + {% block usercard %} + {% include 'globals/usercard.html' %} + {% endblock %} + {% comment %}The user image card ends here!{% endcomment %} + +
+ + {% comment %}The Tab-Menu ends here!{% endcomment %} +
+ {% comment %} + The left-rail segment ends here! + {% endcomment %} + + {% comment %} + The central-rail segment starts here! + {% endcomment %} +
+ + + + {% load static %} + {% comment %}the main tab starts here {% endcomment %} +
+ +
+
+ Created Requests +
+
+
+
+ + + + + + + + + + + + + + {% for f in obj %} + + + + + + + + + + + {% endfor %} +
Details:-
IdNameDescriptionAreaCreated By
{{f.0}}{{f.1}}{{f.3}}{{f.2}}{{f.4}} + +
+ {% csrf_token %} + + +
+
+
+
+
+ + + +
+ {% comment %}The central-rail segment ends here!{% endcomment %} + + {% comment %}The right-rail segment starts here!{% endcomment %} +
+
+ {% comment %} + TODO: the right rail! + {% endcomment %} +
+
+ {% comment %}The right-rail segment ends here!{% endcomment %} + + {% comment %}The right-margin segment!{% endcomment %} +
+ +
+{% comment %}The grid ends here!{% endcomment %} + +{% endblock %} + +{% block javascript %} + + + + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/iwdModuleV2/dashboard.html b/FusionIIIT/templates/iwdModuleV2/dashboard.html index 9f0e1db49..12c27a550 100644 --- a/FusionIIIT/templates/iwdModuleV2/dashboard.html +++ b/FusionIIIT/templates/iwdModuleV2/dashboard.html @@ -34,28 +34,24 @@
{% comment %}ROW #2 starts here!{% endcomment %} - {% if eligible %} + {% if eligible == "Engineer" %}
{% comment %}The Tab-Menu starts here!{% endcomment %} {% comment %}The Tab-Menu ends here!{% endcomment %} @@ -69,22 +65,63 @@ {% comment %}The central-rail segment starts here!{% endcomment %}
{% comment %}The Appointments Form starts here!{% endcomment %} -
+
{% block appointment %} - {% include 'iwdModuleV2/createWork.html' %} + {% include 'iwdModuleV2/requestsView.html' %} {% endblock %}
- {% comment %}The appointment Form ends here!{% endcomment %} - {% comment %}The patient history starts here!{% endcomment %} -
- {% block history %} - {% include 'iwdModuleV2/viewWork.html' %} - {% endblock %} +
+ {% endif %} + {% if eligible == "Dean" %} +
+ {% comment %}The Tab-Menu starts here!{% endcomment %} + + {% comment %}The Tab-Menu ends here!{% endcomment %} +
- {% comment %}The patient history ends here!{% endcomment %} + {% comment %}ROW #2 ends here!{% endcomment %}
+ {% comment %}The left-rail segment ends here!{% endcomment %} + + {% comment %}The central-rail segment starts here!{% endcomment %} + {% endif %} + {% if eligible == "director" %} +
+ {% comment %}The Tab-Menu starts here!{% endcomment %} + + {% comment %}The Tab-Menu ends here!{% endcomment %} + +
+ {% comment %}ROW #2 ends here!{% endcomment %} + +
+ {% comment %}The left-rail segment ends here!{% endcomment %} + + {% comment %}The central-rail segment starts here!{% endcomment %} {% endif %} {% comment %}The central-rail segment ends here!{% endcomment %} diff --git a/FusionIIIT/templates/iwdModuleV2/deanProcessedRequests.html b/FusionIIIT/templates/iwdModuleV2/deanProcessedRequests.html new file mode 100644 index 000000000..dd9ba8ba8 --- /dev/null +++ b/FusionIIIT/templates/iwdModuleV2/deanProcessedRequests.html @@ -0,0 +1,96 @@ +{% extends 'globals/base.html' %} +{% load static %} + +{% block title %} + Academic +{% endblock %} + +{% block body %} + {% block navBar %} + {% include 'dashboard/navbar.html' %} + {% endblock %} + + +
+
+
+ {% block usercard %} + {% include 'globals/usercard.html' %} + {% endblock %} +
+
+
+
+ + +
+
+ Dean processed Requests +
+ +
+
+
+ + + + + + + + + + + + + {% for f in obj %} + + + + + + + + + + + {% endfor %} +
Details:-
IdNameDescriptionAreaCreated By
{{f.0}}{{f.1}}{{f.3}}{{f.2}}{{f.4}} +
+
+ {% csrf_token %} + + +
+
+ {% csrf_token %} + + +
+
+
+
+
+
+
+
+
+ +
+
+
+
+{% endblock %} diff --git a/FusionIIIT/templates/iwdModuleV2/engineerProcessedRequests.html b/FusionIIIT/templates/iwdModuleV2/engineerProcessedRequests.html new file mode 100644 index 000000000..7c3bd813d --- /dev/null +++ b/FusionIIIT/templates/iwdModuleV2/engineerProcessedRequests.html @@ -0,0 +1,121 @@ +{% extends 'globals/base.html' %} +{% load static %} + + +{% block title %} + Academic +{% endblock %} + + +{% block body %} + {% block navBar %} + {% include 'dashboard/navbar.html' %} + {% endblock %} + +
+ + {% comment %}The left-margin segment!{% endcomment %} +
+ + {% comment %}The left-rail segment starts here!{% endcomment %} +
+ {% comment %}The user image card starts here!{% endcomment %} + {% block usercard %} + {% include 'globals/usercard.html' %} + {% endblock %} + {% comment %}The user image card ends here!{% endcomment %} + +
+ + {% comment %}The Tab-Menu ends here!{% endcomment %} +
+ {% comment %} + The left-rail segment ends here! + {% endcomment %} + + {% comment %} + The central-rail segment starts here! + {% endcomment %} +
+ + + + + + {% load static %} + {% comment %}the main tab starts here {% endcomment %} +
+ +
+
+ Engineer Processed Requests +
+
+
+
+ + + + + + + + + + + + + + {% for f in obj %} + + + + + + + + + + + {% endfor %} +
Details:-
IdNameDescriptionAreaCreated By
{{f.0}}{{f.1}}{{f.3}}{{f.2}}{{f.4}} + +
+ {% csrf_token %} + + +
+
+
+
+
+ + + +
+ {% comment %}The central-rail segment ends here!{% endcomment %} + + {% comment %}The right-rail segment starts here!{% endcomment %} +
+
+ {% comment %} + TODO: the right rail! + {% endcomment %} +
+
+ {% comment %}The right-rail segment ends here!{% endcomment %} + + {% comment %}The right-margin segment!{% endcomment %} +
+ +
+ {% comment %}The grid ends here!{% endcomment %} + +{% endblock %} + +{% block javascript %} + + + + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/iwdModuleV2/requestsStatus.html b/FusionIIIT/templates/iwdModuleV2/requestsStatus.html new file mode 100644 index 000000000..14711ab16 --- /dev/null +++ b/FusionIIIT/templates/iwdModuleV2/requestsStatus.html @@ -0,0 +1,114 @@ +{% extends 'globals/base.html' %} +{% load static %} + + +{% block title %} + Academic +{% endblock %} + + +{% block body %} + {% block navBar %} + {% include 'dashboard/navbar.html' %} + {% endblock %} + +
+ + {% comment %}The left-margin segment!{% endcomment %} +
+ + {% comment %}The left-rail segment starts here!{% endcomment %} +
+ {% comment %}The user image card starts here!{% endcomment %} + {% block usercard %} + {% include 'globals/usercard.html' %} + {% endblock %} + {% comment %}The user image card ends here!{% endcomment %} + +
+ + {% comment %}The Tab-Menu ends here!{% endcomment %} +
+ {% comment %} + The left-rail segment ends here! + {% endcomment %} + + {% comment %} + The central-rail segment starts here! + {% endcomment %} +
+ + + + + + {% load static %} + {% comment %}the main tab starts here {% endcomment %} +
+ +
+
+ Requests Status +
+
+
+
+ + + + + + + + + + + + + + {% for f in obj %} + + + + + + + + + + + {% endfor %} +
Details:-
IdNameDescriptionAreaCreated ByStatus
{{f.0}}{{f.1}}{{f.3}}{{f.2}}{{f.4}}{{f.5}}
+
+
+
+ + + +
+ {% comment %}The central-rail segment ends here!{% endcomment %} + + {% comment %}The right-rail segment starts here!{% endcomment %} +
+
+ {% comment %} + TODO: the right rail! + {% endcomment %} +
+
+ {% comment %}The right-rail segment ends here!{% endcomment %} + + {% comment %}The right-margin segment!{% endcomment %} +
+ +
+ {% comment %}The grid ends here!{% endcomment %} + +{% endblock %} + +{% block javascript %} + + + + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/iwdModuleV2/requestsView.html b/FusionIIIT/templates/iwdModuleV2/requestsView.html new file mode 100644 index 000000000..230ebe362 --- /dev/null +++ b/FusionIIIT/templates/iwdModuleV2/requestsView.html @@ -0,0 +1,124 @@ + +{% load static %} + + +{% block title %} + Academic +{% endblock %} + + +{% block body %} + {% block navBar %} + + {% endblock %} + + + + {% comment %}The left-margin segment!{% endcomment %} + + + {% comment %}The left-rail segment starts here!{% endcomment %} + + {% comment %}The user image card starts here!{% endcomment %} + {% block usercard %} + + {% endblock %} + {% comment %}The user image card ends here!{% endcomment %} + + + + {% comment %}The Tab-Menu ends here!{% endcomment %} + + {% comment %} + The left-rail segment ends here! + {% endcomment %} + + {% comment %} + The central-rail segment starts here! + {% endcomment %} +
+ + + + + + {% load static %} +
+ Requests +
+
{% csrf_token %} +
+ +
+ +
+
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+ + +
+ + +
+ +
+
+ + +
+
+
+
+ + + + {% comment %}The central-rail segment ends here!{% endcomment %} + + {% comment %}The right-rail segment starts here!{% endcomment %} + + {% comment %}The right-rail segment ends here!{% endcomment %} + + {% comment %}The right-margin segment!{% endcomment %} + + {% comment %}The grid ends here!{% endcomment %} + +{% endblock %} + +{% block javascript %} + + + + +{% endblock %} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 4cc3a0a30..f30bb509a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ amqp==5.0.2 -arabic-reshaper==2.1.1 +# arabic-reshaper==2.1.1 asgiref==3.3.1 attrs==20.3.0 beautifulsoup4==4.9.3 From 338b463b44cc63f813bf264a2d5ee5e687436a89 Mon Sep 17 00:00:00 2001 From: Srivatsa19 Date: Tue, 19 Mar 2024 22:15:47 +0530 Subject: [PATCH 2/2] Changes made --- .../migrations/0002_auto_20240308_1023.py | 38 + .../eis/migrations/0002_auto_20240308_1023.py | 53 ++ .../filetracking/api/serializers.py | 24 + .../applications/filetracking/api/urls.py | 22 + .../applications/filetracking/api/views.py | 111 +++ .../applications/filetracking/decorators.py | 38 + .../filetracking/filetracking/admin.py | 7 + .../filetracking/api/serializers.py | 24 + .../filetracking/filetracking/api/urls.py | 22 + .../filetracking/filetracking/api/views.py | 111 +++ .../filetracking/filetracking/apps.py | 5 + .../filetracking/filetracking/decorators.py | 38 + .../filetracking/migrations/0001_initial.py | 53 ++ .../filetracking/migrations/__init__.py | 0 .../filetracking/filetracking/models.py | 51 ++ .../filetracking/filetracking/sdk/methods.py | 423 ++++++++++ .../filetracking/filetracking/tests.py | 3 + .../filetracking/filetracking/urls.py | 43 + .../filetracking/filetracking/utils.py | 7 + .../filetracking/filetracking/views.py | 732 ++++++++++++++++++ .../migrations/0002_auto_20240308_1023.py | 33 + .../applications/filetracking/models.py | 12 +- .../applications/filetracking/sdk/methods.py | 424 ++++++++++ FusionIIIT/applications/filetracking/urls.py | 40 +- FusionIIIT/applications/filetracking/views.py | 555 +++++++------ .../migrations/0002_auto_20240308_1023.py | 18 + .../migrations/0003_auto_20240308_1025.py | 18 + .../migrations/0002_bills_requests.py | 41 + FusionIIIT/applications/iwdModuleV2/models.py | 20 +- FusionIIIT/applications/iwdModuleV2/urls.py | 14 +- FusionIIIT/applications/iwdModuleV2/views.py | 415 ++++++++-- .../migrations/0002_auto_20240308_1023.py | 23 + .../migrations/0002_auto_20240308_1023.py | 18 + .../templates/iwdModuleV2/addItemsView.html | 120 +++ .../iwdModuleV2/createdRequests.html | 8 + .../templates/iwdModuleV2/dashboard.html | 44 +- .../iwdModuleV2/deanProcessedRequests.html | 14 + .../templates/iwdModuleV2/editInventory.html | 124 +++ .../engineerProcessedRequests.html | 7 + .../templates/iwdModuleV2/inventory.html | 111 +++ .../templates/iwdModuleV2/issueWorkOrder.html | 120 +++ .../iwdModuleV2/requestFromInventory.html | 172 ++++ .../iwdModuleV2/requestsInProgress.html | 134 ++++ .../templates/iwdModuleV2/requestsView.html | 189 ++--- .../templates/iwdModuleV2/workOrder.html | 175 +++++ 45 files changed, 4254 insertions(+), 400 deletions(-) create mode 100644 FusionIIIT/applications/academic_procedures/migrations/0002_auto_20240308_1023.py create mode 100644 FusionIIIT/applications/eis/migrations/0002_auto_20240308_1023.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/decorators.py create mode 100644 FusionIIIT/applications/filetracking/filetracking/admin.py create mode 100644 FusionIIIT/applications/filetracking/filetracking/api/serializers.py create mode 100644 FusionIIIT/applications/filetracking/filetracking/api/urls.py create mode 100644 FusionIIIT/applications/filetracking/filetracking/api/views.py create mode 100644 FusionIIIT/applications/filetracking/filetracking/apps.py create mode 100644 FusionIIIT/applications/filetracking/filetracking/decorators.py create mode 100644 FusionIIIT/applications/filetracking/filetracking/migrations/0001_initial.py create mode 100644 FusionIIIT/applications/filetracking/filetracking/migrations/__init__.py create mode 100644 FusionIIIT/applications/filetracking/filetracking/models.py create mode 100644 FusionIIIT/applications/filetracking/filetracking/sdk/methods.py create mode 100644 FusionIIIT/applications/filetracking/filetracking/tests.py create mode 100644 FusionIIIT/applications/filetracking/filetracking/urls.py create mode 100644 FusionIIIT/applications/filetracking/filetracking/utils.py create mode 100644 FusionIIIT/applications/filetracking/filetracking/views.py create mode 100644 FusionIIIT/applications/filetracking/migrations/0002_auto_20240308_1023.py create mode 100644 FusionIIIT/applications/filetracking/sdk/methods.py create mode 100644 FusionIIIT/applications/globals/migrations/0002_auto_20240308_1023.py create mode 100644 FusionIIIT/applications/globals/migrations/0003_auto_20240308_1025.py create mode 100644 FusionIIIT/applications/iwdModuleV2/migrations/0002_bills_requests.py create mode 100644 FusionIIIT/applications/programme_curriculum/migrations/0002_auto_20240308_1023.py create mode 100644 FusionIIIT/applications/scholarships/migrations/0002_auto_20240308_1023.py create mode 100644 FusionIIIT/templates/iwdModuleV2/addItemsView.html create mode 100644 FusionIIIT/templates/iwdModuleV2/editInventory.html create mode 100644 FusionIIIT/templates/iwdModuleV2/inventory.html create mode 100644 FusionIIIT/templates/iwdModuleV2/issueWorkOrder.html create mode 100644 FusionIIIT/templates/iwdModuleV2/requestFromInventory.html create mode 100644 FusionIIIT/templates/iwdModuleV2/requestsInProgress.html create mode 100644 FusionIIIT/templates/iwdModuleV2/workOrder.html diff --git a/FusionIIIT/applications/academic_procedures/migrations/0002_auto_20240308_1023.py b/FusionIIIT/applications/academic_procedures/migrations/0002_auto_20240308_1023.py new file mode 100644 index 000000000..2b5457988 --- /dev/null +++ b/FusionIIIT/applications/academic_procedures/migrations/0002_auto_20240308_1023.py @@ -0,0 +1,38 @@ +# Generated by Django 3.1.5 on 2024-03-08 10:23 + +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_20240308_1023.py b/FusionIIIT/applications/eis/migrations/0002_auto_20240308_1023.py new file mode 100644 index 000000000..217222095 --- /dev/null +++ b/FusionIIIT/applications/eis/migrations/0002_auto_20240308_1023.py @@ -0,0 +1,53 @@ +# Generated by Django 3.1.5 on 2024-03-08 10:23 + +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..bdae2024e --- /dev/null +++ b/FusionIIIT/applications/filetracking/api/serializers.py @@ -0,0 +1,24 @@ +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 + exclude = ['upload_file', 'is_read'] diff --git a/FusionIIIT/applications/filetracking/api/urls.py b/FusionIIIT/applications/filetracking/api/urls.py new file mode 100644 index 000000000..90f03b2ef --- /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'), +] diff --git a/FusionIIIT/applications/filetracking/api/views.py b/FusionIIIT/applications/filetracking/api/views.py new file mode 100644 index 000000000..c4bb01189 --- /dev/null +++ b/FusionIIIT/applications/filetracking/api/views.py @@ -0,0 +1,111 @@ +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 ..models import File +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): + try: + current_user = request.user.username + current_designation = request.data.get('designation') + receiver_username = request.data.get('receiver_username') + receiver_designation = request.data.get('receiver_designation') + subject = request.data.get('subject') + description = request.data.get('description') + + if None in [current_designation, receiver_username, receiver_designation, subject, description]: + return Response({'error': 'One or more required fields are missing.'}, status=status.HTTP_400_BAD_REQUEST) + + file_id = create_file(uploader=current_user, uploader_designation=current_designation, + receiver=receiver_username, receiver_designation=receiver_designation, subject=subject, description=description) + + return Response({'file_id': file_id}, status=status.HTTP_201_CREATED) + except Exception as e: + return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) + + +class ViewFileView(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [permissions.IsAuthenticated] + + def get(self, request, file_id): + try: + file_details = view_file(int(file_id)) + return Response(file_details, status=status.HTTP_200_OK) + except ValueError: + return Response({'error': 'Invalid file ID format.'}, status=status.HTTP_400_BAD_REQUEST) + except File.DoesNotExist: + return Response({'error': 'File not found.'}, status=status.HTTP_404_NOT_FOUND) + except Exception as e: + return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) + + +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}) diff --git a/FusionIIIT/applications/filetracking/decorators.py b/FusionIIIT/applications/filetracking/decorators.py new file mode 100644 index 000000000..05cc7cc51 --- /dev/null +++ b/FusionIIIT/applications/filetracking/decorators.py @@ -0,0 +1,38 @@ +from django.shortcuts import render, get_object_or_404 +from django.contrib.auth.models import User +from applications.globals.models import ExtraInfo, HoldsDesignation + + +def user_check(request): + """ + This function is used to check if the user is a student or not. + Its return type is bool. + @param: + request - contains metadata about the requested page + + @Variables: + current_user - get user from request + user_details - extract details of the user from the database + desig_id - check for designation + student - designation for a student + final_user - final designation of the request(our user) + """ + try: + current_user = get_object_or_404(User, username=request.user.username) + user_details = ExtraInfo.objects.select_related('user','department').get(user=request.user) + des = HoldsDesignation.objects.all().select_related().filter(user=request.user).first() + if str(des.designation) == "student": + return True + else: + return False + except Exception as e: + return False + +def user_is_student(view_func): + def _wrapped_view(request, *args, **kwargs): + if user_check(request): + return render(request, 'filetracking/fileTrackingNotAllowed.html') + else: + return view_func(request, *args, **kwargs) + return _wrapped_view + diff --git a/FusionIIIT/applications/filetracking/filetracking/admin.py b/FusionIIIT/applications/filetracking/filetracking/admin.py new file mode 100644 index 000000000..82b78df95 --- /dev/null +++ b/FusionIIIT/applications/filetracking/filetracking/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin + +# Register your models here. +from applications.filetracking.models import File, Tracking + +admin.site.register(File) +admin.site.register(Tracking) diff --git a/FusionIIIT/applications/filetracking/filetracking/api/serializers.py b/FusionIIIT/applications/filetracking/filetracking/api/serializers.py new file mode 100644 index 000000000..bdae2024e --- /dev/null +++ b/FusionIIIT/applications/filetracking/filetracking/api/serializers.py @@ -0,0 +1,24 @@ +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 + exclude = ['upload_file', 'is_read'] diff --git a/FusionIIIT/applications/filetracking/filetracking/api/urls.py b/FusionIIIT/applications/filetracking/filetracking/api/urls.py new file mode 100644 index 000000000..90f03b2ef --- /dev/null +++ b/FusionIIIT/applications/filetracking/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'), +] diff --git a/FusionIIIT/applications/filetracking/filetracking/api/views.py b/FusionIIIT/applications/filetracking/filetracking/api/views.py new file mode 100644 index 000000000..c4bb01189 --- /dev/null +++ b/FusionIIIT/applications/filetracking/filetracking/api/views.py @@ -0,0 +1,111 @@ +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 ..models import File +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): + try: + current_user = request.user.username + current_designation = request.data.get('designation') + receiver_username = request.data.get('receiver_username') + receiver_designation = request.data.get('receiver_designation') + subject = request.data.get('subject') + description = request.data.get('description') + + if None in [current_designation, receiver_username, receiver_designation, subject, description]: + return Response({'error': 'One or more required fields are missing.'}, status=status.HTTP_400_BAD_REQUEST) + + file_id = create_file(uploader=current_user, uploader_designation=current_designation, + receiver=receiver_username, receiver_designation=receiver_designation, subject=subject, description=description) + + return Response({'file_id': file_id}, status=status.HTTP_201_CREATED) + except Exception as e: + return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) + + +class ViewFileView(APIView): + authentication_classes = [TokenAuthentication] + permission_classes = [permissions.IsAuthenticated] + + def get(self, request, file_id): + try: + file_details = view_file(int(file_id)) + return Response(file_details, status=status.HTTP_200_OK) + except ValueError: + return Response({'error': 'Invalid file ID format.'}, status=status.HTTP_400_BAD_REQUEST) + except File.DoesNotExist: + return Response({'error': 'File not found.'}, status=status.HTTP_404_NOT_FOUND) + except Exception as e: + return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) + + +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}) diff --git a/FusionIIIT/applications/filetracking/filetracking/apps.py b/FusionIIIT/applications/filetracking/filetracking/apps.py new file mode 100644 index 000000000..7e3d3b6d2 --- /dev/null +++ b/FusionIIIT/applications/filetracking/filetracking/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class FileTrackingConfig(AppConfig): + name = 'applications.filetracking' diff --git a/FusionIIIT/applications/filetracking/filetracking/decorators.py b/FusionIIIT/applications/filetracking/filetracking/decorators.py new file mode 100644 index 000000000..05cc7cc51 --- /dev/null +++ b/FusionIIIT/applications/filetracking/filetracking/decorators.py @@ -0,0 +1,38 @@ +from django.shortcuts import render, get_object_or_404 +from django.contrib.auth.models import User +from applications.globals.models import ExtraInfo, HoldsDesignation + + +def user_check(request): + """ + This function is used to check if the user is a student or not. + Its return type is bool. + @param: + request - contains metadata about the requested page + + @Variables: + current_user - get user from request + user_details - extract details of the user from the database + desig_id - check for designation + student - designation for a student + final_user - final designation of the request(our user) + """ + try: + current_user = get_object_or_404(User, username=request.user.username) + user_details = ExtraInfo.objects.select_related('user','department').get(user=request.user) + des = HoldsDesignation.objects.all().select_related().filter(user=request.user).first() + if str(des.designation) == "student": + return True + else: + return False + except Exception as e: + return False + +def user_is_student(view_func): + def _wrapped_view(request, *args, **kwargs): + if user_check(request): + return render(request, 'filetracking/fileTrackingNotAllowed.html') + else: + return view_func(request, *args, **kwargs) + return _wrapped_view + diff --git a/FusionIIIT/applications/filetracking/filetracking/migrations/0001_initial.py b/FusionIIIT/applications/filetracking/filetracking/migrations/0001_initial.py new file mode 100644 index 000000000..6924ae1ff --- /dev/null +++ b/FusionIIIT/applications/filetracking/filetracking/migrations/0001_initial.py @@ -0,0 +1,53 @@ +# Generated by Django 3.1.5 on 2023-03-15 18:53 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('globals', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='File', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('subject', models.CharField(blank=True, max_length=100, null=True)), + ('description', models.CharField(blank=True, max_length=400, null=True)), + ('upload_date', models.DateTimeField(auto_now_add=True)), + ('upload_file', models.FileField(blank=True, upload_to='')), + ('is_read', models.BooleanField(default=False)), + ('designation', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='upload_designation', to='globals.designation')), + ('uploader', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='uploaded_files', to='globals.extrainfo')), + ], + options={ + 'db_table': 'File', + }, + ), + migrations.CreateModel( + name='Tracking', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('receive_date', models.DateTimeField(auto_now_add=True)), + ('forward_date', models.DateTimeField(auto_now_add=True)), + ('remarks', models.CharField(blank=True, max_length=250, null=True)), + ('upload_file', models.FileField(blank=True, upload_to='')), + ('is_read', models.BooleanField(default=False)), + ('current_design', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='globals.holdsdesignation')), + ('current_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='globals.extrainfo')), + ('file_id', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='filetracking.file')), + ('receive_design', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rec_design', to='globals.designation')), + ('receiver_id', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='receiver_id', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'db_table': 'Tracking', + }, + ), + ] diff --git a/FusionIIIT/applications/filetracking/filetracking/migrations/__init__.py b/FusionIIIT/applications/filetracking/filetracking/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/FusionIIIT/applications/filetracking/filetracking/models.py b/FusionIIIT/applications/filetracking/filetracking/models.py new file mode 100644 index 000000000..9d78b24c9 --- /dev/null +++ b/FusionIIIT/applications/filetracking/filetracking/models.py @@ -0,0 +1,51 @@ +from django.db import models +from django.contrib.auth.models import User +from applications.globals.models import ExtraInfo, HoldsDesignation, Designation + + +class File(models.Model): + """ + This is file table which contains the all the files created by user + """ + uploader = models.ForeignKey(ExtraInfo, on_delete=models.CASCADE, related_name='uploaded_files') + designation = models.ForeignKey(Designation, on_delete=models.CASCADE, null=True, related_name='upload_designation') + subject = models.CharField(max_length=100, null=True, blank=True) + description = models.CharField(max_length=400, null=True, blank=True) + upload_date = models.DateTimeField(auto_now_add=True) + upload_file = models.FileField(blank=True) + 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' + + #def __str__(self): + #return str(self.ref_id) + + +class Tracking(models.Model): + """ + 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(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') + + receive_date = models.DateTimeField(auto_now_add=True) + forward_date = models.DateTimeField(auto_now_add=True) + remarks = models.CharField(max_length=250, null=True, blank=True) + 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' diff --git a/FusionIIIT/applications/filetracking/filetracking/sdk/methods.py b/FusionIIIT/applications/filetracking/filetracking/sdk/methods.py new file mode 100644 index 000000000..c6f9ebc53 --- /dev/null +++ b/FusionIIIT/applications/filetracking/filetracking/sdk/methods.py @@ -0,0 +1,423 @@ +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, + subject: str = "", + description: 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, + subject=subject, + description=description, + designation=uploader_designation_obj, + src_module=src_module, + src_object_id=src_object_id, + file_extra_JSON=file_extra_JSON, + ) + + + if attached_file is not None: + new_file.upload_file.save(attached_file.name, attached_file, save=True) + + 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) -> list: + ''' + This function is used to get all the files in the inbox of a particular user and designation + ''' + 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).order_by('receive_date'); + 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 = list(FileHeaderSerializer( + received_files_unique, many=True).data) + + for file in received_files_serialized: + file['sent_by_user'] = get_last_file_sender(file['id']).username + file['sent_by_designation'] = get_last_file_sender_designation(file['id']).name + + return received_files_serialized + + +def view_outbox(username: str, designation: str, src_module: str) -> list: + ''' + This function is used to get all the files in the outbox of a particular user and designation + ''' + user_designation = get_designation_obj_from_name(designation=designation) + user_object = get_user_object_from_username(username) + 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).order_by('-receive_date') + 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 + + + +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 unarchive_file(file_id: int) -> bool: + ''' + This functions is used to unarchive a file and returns true if the unarchiving was successful + ''' + try: + File.objects.filter(id=file_id).update(is_read=False) + 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 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 + + +# HELPER FUNCTIONS + +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 get_last_file_sender(file_id: int) -> User: + ''' + This Function returns the last file sender, + one who has last forwarded/sent the file + ''' + latest_tracking = Tracking.objects.filter( + file_id=file_id).order_by('-receive_date').first() + latest_sender_extra_info = latest_tracking.current_id + return latest_sender_extra_info.user + +def get_last_file_sender_designation(file_id: int) -> Designation: + ''' + This Function returns the last file sender's Designation, + one who has last forwarded/sent the file + ''' + latest_tracking = Tracking.objects.filter( + file_id=file_id).order_by('receive_date').first() + latest_sender_holds_designation = latest_tracking.current_design + return latest_sender_holds_designation.designation + +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 = [hold_designation.designation.name for hold_designation in designations_held] + return designation_name + + +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 + ''' + seen = set() + unique_list = [] + for item in l: + if item not in seen: + unique_list.append(item) + seen.add(item) + return unique_list + +def add_uploader_department_to_files_list(files: list) -> list: + ''' + This function is used to add the department of the uploader to the file + ''' + for file in files: + uploader_Extrainfo = file['uploader'] + file['uploader_department'] = (str(uploader_Extrainfo.department)).split(': ')[1] + + return files + +def get_designation_obj_from_name(designation: str) -> Designation: + des = Designation.objects.get(name = designation) + return des + +def get_HoldsDesignation_obj(username: str, designation:str) -> HoldsDesignation: + user_object = get_user_object_from_username(username=username) + user_designation = get_designation_obj_from_name(designation=designation) + obj = HoldsDesignation.objects.get( + user=user_object, designation=user_designation) + return obj + +def get_last_recv_tracking_for_user(file_id: int, username: str, designation: str)-> Tracking: + ''' + This returns the last tracking where username+designation recieved file_id + ''' + + recv_user_obj = get_user_object_from_username(username) + recv_design_obj = get_designation_obj_from_name(designation) + + last_tracking = Tracking.objects.filter(file_id=file_id, + receiver_id=recv_user_obj, + receive_design=recv_design_obj).order_by('-receive_date')[0] + return last_tracking + +def get_last_forw_tracking_for_user(file_id: int, username: str, designation: str) -> Tracking: + ''' + Returns the last tracking where the specified user forwarded the file. + ''' + + # Get user and designation objects + sender_user_obj = get_ExtraInfo_object_from_username(username) + sender_designation_obj = get_HoldsDesignation_obj(username=username, designation=designation) + + # Filter Tracking objects by file_id, sender_id, and sender_designation + last_tracking = Tracking.objects.filter(file_id=file_id, + current_id=sender_user_obj, + current_design=sender_designation_obj).order_by('-forward_date').first() + return last_tracking + +def get_extra_info_object_from_id(id: int): + return ExtraInfo.objects.get(id=id) diff --git a/FusionIIIT/applications/filetracking/filetracking/tests.py b/FusionIIIT/applications/filetracking/filetracking/tests.py new file mode 100644 index 000000000..a79ca8be5 --- /dev/null +++ b/FusionIIIT/applications/filetracking/filetracking/tests.py @@ -0,0 +1,3 @@ +# from django.test import TestCase + +# Create your tests here. diff --git a/FusionIIIT/applications/filetracking/filetracking/urls.py b/FusionIIIT/applications/filetracking/filetracking/urls.py new file mode 100644 index 000000000..9236b8c36 --- /dev/null +++ b/FusionIIIT/applications/filetracking/filetracking/urls.py @@ -0,0 +1,43 @@ +from django.conf.urls import url, include + +from . import views +from .api import urls + +app_name = 'filetracking' + +urlpatterns = [ + + url(r'^$', views.filetracking, name='filetracking'), + url(r'^draftdesign/$', views.draft_design, name='draft_design'), + url(r'^drafts/(?P\d+)$', views.drafts_view, name='drafts_view'), + url(r'^outbox/(?P\d+)$', views.outbox_view, name='outbox_view'), + url(r'^inbox/(?P\d+)$', views.inbox_view, name='inbox_view'), + 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'^archive/(?P\d+)/$', views.archive_view, name='archive_view'), + url(r'^finish/(?P\d+)/$', views.archive_file, name='finish_file'), + url(r'^viewfile/(?P\d+)/$', views.view_file, name='view_file_view'), + 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'), + + # 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'^archive_design/$', views.archive_design, name='archive_design'), + url(r'^archive_finish/(?P\d+)/$', + views.archive_finish, name='archive_finish'), + url(r'^getdesignations/(?P\w+)/$', views.get_designations_view, name="get_user_designations"), + + # REST api urls + url(r'^api/', include(urls)) + +] diff --git a/FusionIIIT/applications/filetracking/filetracking/utils.py b/FusionIIIT/applications/filetracking/filetracking/utils.py new file mode 100644 index 000000000..5ebd27374 --- /dev/null +++ b/FusionIIIT/applications/filetracking/filetracking/utils.py @@ -0,0 +1,7 @@ +from .models import File, Tracking +from applications.globals.models import ExtraInfo, HoldsDesignation, Designation +from django.contrib.auth.models import User + +def get_designation(userid): + user_designation=HoldsDesignation.objects.select_related('user','working','designation').filter(user=userid) + return user_designation \ No newline at end of file diff --git a/FusionIIIT/applications/filetracking/filetracking/views.py b/FusionIIIT/applications/filetracking/filetracking/views.py new file mode 100644 index 000000000..b6d9e3bff --- /dev/null +++ b/FusionIIIT/applications/filetracking/filetracking/views.py @@ -0,0 +1,732 @@ +from django.contrib import messages +from django.shortcuts import render, get_object_or_404, redirect +from .models import File, Tracking +from applications.globals.models import ExtraInfo, HoldsDesignation, Designation +from django.template.defaulttags import csrf_token +from django.http import HttpResponse, HttpResponseRedirect, JsonResponse +from django.contrib.auth.decorators import login_required +from django.db import IntegrityError +from django.core import serializers +from django.contrib.auth.models import User +from django.http import JsonResponse +from timeit import default_timer as time +from notification.views import office_module_notif, file_tracking_notif +from .utils import * +from django.utils.dateparse import parse_datetime +from .sdk.methods import * +from .decorators import * + +@login_required(login_url="/accounts/login/") +@user_is_student +def filetracking(request): + """ + The function is used to create files by current user(employee). + It adds the employee(uploader) and file datails to a file(table) of filetracking(model) + if he intends to create file. + + @param: + request - trivial. + + @variables: + + + uploader - Employee who creates file. + subject - Title of the file. + description - Description of the file. + upload_file - Attachment uploaded while creating file. + file - The file object. + extrainfo - The Extrainfo object. + holdsdesignations - The HoldsDesignation object. + context - Holds data needed to make necessary changes in the template. + """ + 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) + upload_file = request.FILES.get('myfile') + 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, + description=description, + subject=subject, + designation=designation, + upload_file=upload_file + ) + + 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) + + upload_file = request.FILES.get('myfile') + 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( + uploader=uploader, + description=description, + subject=subject, + designation=designation, + 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) + + 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') + try: + receive_design = Designation.objects.get(name=receive) + except Exception as e: + messages.error(request, 'Enter a valid Designation') + return redirect('/filetracking/') + + 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, + ) + # 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() + designations = get_designation(request.user) + + context = { + 'file': file, + 'extrainfo': extrainfo, + 'holdsdesignations': holdsdesignations, + 'designations': designations, + } + return render(request, 'filetracking/composefile.html', context) + + +@login_required(login_url="/accounts/login") +def draft_design(request): + """ + The function is used to get the designation of the user and renders it on draft template. + + @param: + request - trivial. + + @variables: + + + context - Holds data needed to make necessary changes in the template. + """ + designation = get_designation(request.user) + context = { + 'designation': designation, + } + return render(request, 'filetracking/draft_design.html', context) + + +@login_required(login_url="/accounts/login") +def drafts_view(request, id): + """ + This function is used to view all the drafts created by the user ordered by upload date.it collects all the created files from File object. + + @param: + request - trivial + id - user id + + @parameters + draft - file obeject containing all the files created by user + context - holds data needed to render the template + + + + """ + user_HoldsDesignation_obj = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(pk=id) + s = str(user_HoldsDesignation_obj).split(" - ") + designation = s[1] + draft_files = view_drafts( + username=user_HoldsDesignation_obj.user, + designation=user_HoldsDesignation_obj.designation, + src_module='filetracking' + ) + + # Correct upload_date type + for f in draft_files: + f['upload_date'] = parse_datetime(f['upload_date']) + f['uploader'] = get_extra_info_object_from_id(f['uploader']) + + draft_files = add_uploader_department_to_files_list(draft_files) + + context = { + 'draft_files': draft_files, + 'designations': designation, + } + return render(request, 'filetracking/drafts.html', context) + + +@login_required(login_url="/accounts/login") +def outbox_view(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. + It displays files sent by user to other employees of a Tracking(table) of filetracking(model) + in the 'Outbox' tab of template. + + @param: + request - trivial. + id - user id + + @variables: + outward_files - File objects filtered by current_id i.e, present working user. + context - Holds data needed to make necessary changes in the template. + + """ + user_HoldsDesignation_obj = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(pk=id) + s = str(user_HoldsDesignation_obj).split(" - ") + designation = s[1] + + outward_files = view_outbox(username=user_HoldsDesignation_obj.user, + designation=user_HoldsDesignation_obj.designation, + src_module='filetracking') + + for f in outward_files: + last_forw_tracking = get_last_forw_tracking_for_user(file_id=f['id'], + username=user_HoldsDesignation_obj.user, + designation=user_HoldsDesignation_obj.designation) + f['sent_to_user'] = last_forw_tracking.receiver_id + f['sent_to_design'] = last_forw_tracking.receive_design + f['last_sent_date'] = last_forw_tracking.forward_date + + f['upload_date'] = parse_datetime(f['upload_date']) + f['uploader'] = get_extra_info_object_from_id(f['uploader']) + + outward_files = add_uploader_department_to_files_list(outward_files) + + context = { + + 'out_files': outward_files, + 'viewer_designation': designation, + } + return render(request, 'filetracking/outbox.html', context) + + +@login_required(login_url="/accounts/login") +def inbox_view(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. + + @param: + request - trivial. + id - HoldsDesignation object id + + @variables: + inward_files - File object with additional sent by information + context - Holds data needed to make necessary changes in the template. + + """ + + user_HoldsDesignation_obj = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(pk=id) + s = str(user_HoldsDesignation_obj).split(" - ") + designation = s[1] + inward_files = view_inbox( + username=user_HoldsDesignation_obj.user, + designation=user_HoldsDesignation_obj.designation, + src_module='filetracking' + ) + + # correct upload_date type and add recieve_date + for f in inward_files: + f['upload_date'] = parse_datetime(f['upload_date']) + + last_recv_tracking = get_last_recv_tracking_for_user(file_id=f['id'], + username=user_HoldsDesignation_obj.user, + designation=user_HoldsDesignation_obj.designation) + f['receive_date'] = last_recv_tracking.receive_date + f['uploader'] = get_extra_info_object_from_id(f['uploader']) + + inward_files = add_uploader_department_to_files_list(inward_files) + + + context = { + + 'in_file': inward_files, + 'designations': designation, + } + return render(request, 'filetracking/inbox.html', context) + + +@login_required(login_url="/accounts/login") +def outward(request): + """ + This function fetches the different designations of the user and renders it on outward template + @param: + request - trivial. + + @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) + + +@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. + + @variables: + context - Holds the different designation data of the user + """ + 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): + """ + The function is used to confirm the deletion of a file. + @param: + request - trivial. + id - user 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) + + context = { + 'j': file, + } + + return render(request, 'filetracking/confirmdelete.html', context) + +@login_required(login_url="/accounts/login") +def view_file(request, id): + ''' + This function is used to view a particular file received by an employee from another. + This function also conditionally renders two forms 'forward_file' and 'archive_file' + based on if the user has necessary permissions or not. + The business permissions are as follows: + 1. User can forward file only if they are the last recipient of the file + 2. User can archive a file only if they have received it last and they are also the original owner of the file + + To forward the file and to archive the file separate views with POST request are called + + It displays the details file of a File and remarks as well as the attachments of all the users + who have been involved till that point of the workflow. + + @param: + request - Trivial. + id - ID of the file object which the user intends to forward to another employee. + + @variables: + file - The File object. + track - The Tracking object. + designation - the designations of the 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).order_by('receive_date') + designations = get_designation(request.user) + + forward_enable = False + archive_enable = False + + current_owner = get_current_file_owner(file.id) + file_uploader = get_user_object_from_username(file.uploader.user.username) + + + if current_owner == request.user and file.is_read is False: + forward_enable = True + if current_owner == request.user and file_uploader == request.user and file.is_read is False: + archive_enable = True + + context = { + 'designations': designations, + 'file': file, + 'track': track, + 'forward_enable': forward_enable, + 'archive_enable': archive_enable, + } + return render(request, 'filetracking/viewfile.html', context) + +@login_required(login_url="/accounts/login") +def archive_file(request, id): + '''This function is used to archive a file. + It returns unauthorized access if the user is not file uploader + and the current owner of the file + ''' + if request.method == "POST": + file = get_object_or_404(File, id=id); + current_owner = get_current_file_owner(file.id) + file_uploader = get_user_object_from_username(file.uploader.user.username) + if current_owner == request.user and file_uploader == request.user: + file.is_read = True + file.save() + messages.success(request, 'File Archived') + else: + messages.error(request, 'Unauthorized access') + + return render(request, 'filetracking/composefile.html') + +@login_required(login_url="/accounts/login") +def forward(request, id): + """ + The function is used to forward files received by user(employee) from other + employees which are filtered from Tracking(table) objects by current user + i.e. receiver_id to other employees. + It also gets track of file created by uploader through all users involved in file + along with their remarks and attachments + It displays details file of a File(table) and remarks and attachments of user involved + in file of Tracking(table) of filetracking(model) in the template. + + @param: + request - trivial. + id - id of the file object which the user intends to forward to other employee. + + @variables: + file - The File object. + track - The Tracking object. + remarks = Remarks posted by user. + receiver = Receiver to be selected by user for forwarding file. + receiver_id = Receiver_id who has been selected for forwarding file. + upload_file = File attached by user. + extrainfo = ExtraInfo object. + 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).order_by('receive_date') + + 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') + + designations = get_designation(request.user) + + context = { + + 'designations': designations, + 'file': file, + 'track': track, + } + + return render(request, 'filetracking/forward.html', context) + + +@login_required(login_url="/accounts/login") +def archive_design(request): + designation = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').filter(user=request.user) + + context = { + 'designation': designation, + } + return render(request, 'filetracking/archive_design.html', context) + + +@login_required(login_url="/accounts/login") +def archive_view(request, id): + """ + The function is used to fetch the files in the user's archive + (those which have passed by user and been archived/finished) + + @param: + request - trivial. + id - HoldsDesignation object id + + @variables: + archive_files - File object with additional information + context - Holds data needed to make necessary changes in the template. + + """ + user_HoldsDesignation_obj = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(pk=id) + s = str(user_HoldsDesignation_obj).split(" - ") + designation = s[1] + + archive_files = view_archived( + username=user_HoldsDesignation_obj.user, + designation=user_HoldsDesignation_obj.designation, + src_module='filetracking' + ) + + # correct upload_date type and add receive_date + for f in archive_files: + f['upload_date'] = parse_datetime(f['upload_date']) + f['designation'] = Designation.objects.get(id=f['designation']) + f['uploader'] = get_extra_info_object_from_id(f['uploader']) + + archive_files = add_uploader_department_to_files_list(archive_files) + + context = { + 'archive_files': archive_files, + 'designations': designation, + } + return render(request, 'filetracking/archive.html', context) + + + +@login_required(login_url="/accounts/login") +def archive_finish(request, 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") +def finish_design(request): + + designation = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').filter(user=request.user) + + context = { + 'designation': designation, + } + return render(request, 'filetracking/finish_design.html', context) + + +@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) + + context = { + + 'out': out, + 'abcd': abcd, + } + return render(request, 'filetracking/finish_fileview.html', context) + + +@login_required(login_url="/accounts/login") +def finish(request, 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}) + + +def AjaxDropdown1(request): + + """ + This function returns the designation of receiver on the forward or compose file template. + + @param: + request - trivial. + + + @variables: + context - return the httpresponce containing the matched designation of the user + """ + if request.method == 'POST': + value = request.POST.get('value') + + hold = Designation.objects.filter(name__startswith=value) + holds = serializers.serialize('json', list(hold)) + context = { + '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 + """ + if request.method == 'POST': + value = request.POST.get('value') + users = User.objects.filter(username__startswith=value) + users = serializers.serialize('json', list(users)) + + context = { + 'users': users + } + return HttpResponse(JsonResponse(context), content_type='application/json') + + +def test(request): + return HttpResponse('success') + + + +@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.delete() + return redirect('/filetracking/draftdesign/') + + + + +def forward_inward(request,id): + """ This function is used forward the files which are available in the inbox of the user . + + @param: + request - trivial + id - id of the file that is going to forward + + @variables: + 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) + designations = get_designation(request.user) + + context = { + + 'designations': designations, + 'file': file, + 'track': track, + } + return render(request, 'filetracking/forward.html', context) + +def get_designations_view(request, username): + designations = get_designations(username) + print(designations) + return JsonResponse(designations, safe=False) + diff --git a/FusionIIIT/applications/filetracking/migrations/0002_auto_20240308_1023.py b/FusionIIIT/applications/filetracking/migrations/0002_auto_20240308_1023.py new file mode 100644 index 000000000..31015f1ec --- /dev/null +++ b/FusionIIIT/applications/filetracking/migrations/0002_auto_20240308_1023.py @@ -0,0 +1,33 @@ +# Generated by Django 3.1.5 on 2024-03-08 10:23 + +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..9d78b24c9 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,13 +30,11 @@ 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') - # 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 +44,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' diff --git a/FusionIIIT/applications/filetracking/sdk/methods.py b/FusionIIIT/applications/filetracking/sdk/methods.py new file mode 100644 index 000000000..97b7c87a1 --- /dev/null +++ b/FusionIIIT/applications/filetracking/sdk/methods.py @@ -0,0 +1,424 @@ +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, + subject: str = "", + description: 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, + subject=subject, + description=description, + designation=uploader_designation_obj, + src_module=src_module, + src_object_id=src_object_id, + file_extra_JSON=file_extra_JSON, + ) + + + if attached_file is not None: + new_file.upload_file.save(attached_file.name, attached_file, save=True) + + 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 + print(file_details) + 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) -> list: + ''' + This function is used to get all the files in the inbox of a particular user and designation + ''' + 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).order_by('receive_date'); + 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 = list(FileHeaderSerializer( + received_files_unique, many=True).data) + + for file in received_files_serialized: + file['sent_by_user'] = get_last_file_sender(file['id']).username + file['sent_by_designation'] = get_last_file_sender_designation(file['id']).name + + return received_files_serialized + + +def view_outbox(username: str, designation: str, src_module: str) -> list: + ''' + This function is used to get all the files in the outbox of a particular user and designation + ''' + user_designation = get_designation_obj_from_name(designation=designation) + user_object = get_user_object_from_username(username) + 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).order_by('-receive_date') + 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 + + + +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 unarchive_file(file_id: int) -> bool: + ''' + This functions is used to unarchive a file and returns true if the unarchiving was successful + ''' + try: + File.objects.filter(id=file_id).update(is_read=False) + 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 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 + + +# HELPER FUNCTIONS + +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 get_last_file_sender(file_id: int) -> User: + ''' + This Function returns the last file sender, + one who has last forwarded/sent the file + ''' + latest_tracking = Tracking.objects.filter( + file_id=file_id).order_by('-receive_date').first() + latest_sender_extra_info = latest_tracking.current_id + return latest_sender_extra_info.user + +def get_last_file_sender_designation(file_id: int) -> Designation: + ''' + This Function returns the last file sender's Designation, + one who has last forwarded/sent the file + ''' + latest_tracking = Tracking.objects.filter( + file_id=file_id).order_by('receive_date').first() + latest_sender_holds_designation = latest_tracking.current_design + return latest_sender_holds_designation.designation + +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 = [hold_designation.designation.name for hold_designation in designations_held] + return designation_name + + +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 + ''' + seen = set() + unique_list = [] + for item in l: + if item not in seen: + unique_list.append(item) + seen.add(item) + return unique_list + +def add_uploader_department_to_files_list(files: list) -> list: + ''' + This function is used to add the department of the uploader to the file + ''' + for file in files: + uploader_Extrainfo = file['uploader'] + file['uploader_department'] = (str(uploader_Extrainfo.department)).split(': ')[1] + + return files + +def get_designation_obj_from_name(designation: str) -> Designation: + des = Designation.objects.get(name = designation) + return des + +def get_HoldsDesignation_obj(username: str, designation:str) -> HoldsDesignation: + user_object = get_user_object_from_username(username=username) + user_designation = get_designation_obj_from_name(designation=designation) + obj = HoldsDesignation.objects.get( + user=user_object, designation=user_designation) + return obj + +def get_last_recv_tracking_for_user(file_id: int, username: str, designation: str)-> Tracking: + ''' + This returns the last tracking where username+designation recieved file_id + ''' + + recv_user_obj = get_user_object_from_username(username) + recv_design_obj = get_designation_obj_from_name(designation) + + last_tracking = Tracking.objects.filter(file_id=file_id, + receiver_id=recv_user_obj, + receive_design=recv_design_obj).order_by('-receive_date')[0] + return last_tracking + +def get_last_forw_tracking_for_user(file_id: int, username: str, designation: str) -> Tracking: + ''' + Returns the last tracking where the specified user forwarded the file. + ''' + + # Get user and designation objects + sender_user_obj = get_ExtraInfo_object_from_username(username) + sender_designation_obj = get_HoldsDesignation_obj(username=username, designation=designation) + + # Filter Tracking objects by file_id, sender_id, and sender_designation + last_tracking = Tracking.objects.filter(file_id=file_id, + current_id=sender_user_obj, + current_design=sender_designation_obj).order_by('-forward_date').first() + return last_tracking + +def get_extra_info_object_from_id(id: int): + return ExtraInfo.objects.get(id=id) diff --git a/FusionIIIT/applications/filetracking/urls.py b/FusionIIIT/applications/filetracking/urls.py index cb4a7563d..28c8deac1 100644 --- a/FusionIIIT/applications/filetracking/urls.py +++ b/FusionIIIT/applications/filetracking/urls.py @@ -1,31 +1,43 @@ -from django.conf.urls import url +from django.conf.urls import url, include from . import views +from .api import urls app_name = 'filetracking' urlpatterns = [ url(r'^$', views.filetracking, name='filetracking'), - url(r'^drafts/$', views.drafts, name='drafts'), - url(r'^fileview/(?P\d+)$', views.fileview, name='fileview'), - url(r'^fileview1/(?P\d+)$', views.fileview1, name='fileview1'), - url(r'^fileview2/(?P\d+)$', views.fileview2, name='fileview2'), + url(r'^draftdesign/$', views.draft_design, name='draft_design'), + url(r'^drafts/(?P\d+)$', views.drafts_view, name='drafts_view'), + url(r'^outbox/(?P\d+)$', views.outbox_view, name='outbox_view'), + url(r'^inbox/(?P\d+)$', views.inbox_view, name='inbox_view'), 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'^archive/(?P\d+)/$', views.archive, name='archive'), - url(r'^finish/(?P\d+)/$', views.finish, name='finish'), + url(r'^confirmdelete/(?P\d+)$', + views.confirmdelete, name='confirm_delete'), + url(r'^archive/(?P\d+)/$', views.archive_view, name='archive_view'), + url(r'^finish/(?P\d+)/$', views.archive_file, name='finish_file'), + url(r'^viewfile/(?P\d+)/$', views.view_file, name='view_file_view'), 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'), + url(r'^getdesignations/(?P\w+)/$', views.get_designations_view, name="get_user_designations"), + + # REST api urls + url(r'^api/', include(urls)) + ] diff --git a/FusionIIIT/applications/filetracking/views.py b/FusionIIIT/applications/filetracking/views.py index ef5d8f347..b6d9e3bff 100644 --- a/FusionIIIT/applications/filetracking/views.py +++ b/FusionIIIT/applications/filetracking/views.py @@ -8,12 +8,16 @@ from django.db import IntegrityError from django.core import serializers from django.contrib.auth.models import User +from django.http import JsonResponse 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 * +from django.utils.dateparse import parse_datetime +from .sdk.methods import * +from .decorators import * - -@login_required(login_url = "/accounts/login/") +@login_required(login_url="/accounts/login/") +@user_is_student def filetracking(request): """ The function is used to create files by current user(employee). @@ -35,18 +39,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 +62,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 +86,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 +117,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,8 +141,8 @@ def filetracking(request): return render(request, 'filetracking/composefile.html', context) -@login_required(login_url = "/accounts/login") -def drafts(request): +@login_required(login_url="/accounts/login") +def draft_design(request): """ The function is used to get the designation of the user and renders it on draft template. @@ -142,22 +150,21 @@ def drafts(request): request - trivial. @variables: - - + + context - Holds data needed to make necessary changes in the template. """ designation = get_designation(request.user) context = { 'designation': designation, } - return render(request, 'filetracking/drafts.html', context) + return render(request, 'filetracking/draft_design.html', context) -@login_required(login_url = "/accounts/login") -def fileview(request,id): - +@login_required(login_url="/accounts/login") +def drafts_view(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. + This function is used to view all the drafts created by the user ordered by upload date.it collects all the created files from File object. @param: request - trivial @@ -166,45 +173,36 @@ 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)) + """ + user_HoldsDesignation_obj = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(pk=id) + s = str(user_HoldsDesignation_obj).split(" - ") + designation = s[1] + draft_files = view_drafts( + username=user_HoldsDesignation_obj.user, + designation=user_HoldsDesignation_obj.designation, + src_module='filetracking' + ) + + # Correct upload_date type + for f in draft_files: + f['upload_date'] = parse_datetime(f['upload_date']) + f['uploader'] = get_extra_info_object_from_id(f['uploader']) + + draft_files = add_uploader_department_to_files_list(draft_files) - user_designation = HoldsDesignation.objects.select_related('user','working','designation').get(pk=id) - s = str(user_designation).split(" - ") - designations = s[1] context = { - - 'draft': draft_file_list, - 'extrainfo': extrainfo, - 'designations': designations, + 'draft_files': draft_files, + 'designations': designation, } - return render(request, 'filetracking/fileview.html', context) - - + return render(request, 'filetracking/drafts.html', context) -@login_required(login_url = "/accounts/login") -def fileview1(request,id): +@login_required(login_url="/accounts/login") +def outbox_view(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. @@ -216,56 +214,88 @@ def fileview1(request,id): id - user id @variables: - out - The Tracking object filtered by current_id i.e, present working user. + outward_files - File objects filtered by current_id i.e, present working user. context - Holds data needed to make necessary changes in the template. - + """ + user_HoldsDesignation_obj = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(pk=id) + s = str(user_HoldsDesignation_obj).split(" - ") + designation = s[1] + + outward_files = view_outbox(username=user_HoldsDesignation_obj.user, + designation=user_HoldsDesignation_obj.designation, + src_module='filetracking') + + for f in outward_files: + last_forw_tracking = get_last_forw_tracking_for_user(file_id=f['id'], + username=user_HoldsDesignation_obj.user, + designation=user_HoldsDesignation_obj.designation) + f['sent_to_user'] = last_forw_tracking.receiver_id + f['sent_to_design'] = last_forw_tracking.receive_design + f['last_sent_date'] = last_forw_tracking.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') + f['upload_date'] = parse_datetime(f['upload_date']) + f['uploader'] = get_extra_info_object_from_id(f['uploader']) - user_designation = HoldsDesignation.objects.select_related('user','working','designation').get(pk=id) + outward_files = add_uploader_department_to_files_list(outward_files) context = { - 'out': outward_files, - 'abcd': user_designation, + 'out_files': outward_files, + 'viewer_designation': designation, } - return render(request, 'filetracking/fileview1.html', context) + return render(request, 'filetracking/outbox.html', context) -@login_required(login_url = "/accounts/login") -def fileview2(request,id): - +@login_required(login_url="/accounts/login") +def inbox_view(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. @param: request - trivial. - id - user id + id - HoldsDesignation object id @variables: - inward_file - The Tracking object filtered by receiver_id i.e, present working user. + inward_files - File object with additional sent by information 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') - user_designation = HoldsDesignation.objects.select_related('user','working','designation').get(pk=id) - s = str(user_designation).split(" - ") - designations = s[1] + user_HoldsDesignation_obj = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(pk=id) + s = str(user_HoldsDesignation_obj).split(" - ") + designation = s[1] + inward_files = view_inbox( + username=user_HoldsDesignation_obj.user, + designation=user_HoldsDesignation_obj.designation, + src_module='filetracking' + ) + + # correct upload_date type and add recieve_date + for f in inward_files: + f['upload_date'] = parse_datetime(f['upload_date']) + + last_recv_tracking = get_last_recv_tracking_for_user(file_id=f['id'], + username=user_HoldsDesignation_obj.user, + designation=user_HoldsDesignation_obj.designation) + f['receive_date'] = last_recv_tracking.receive_date + f['uploader'] = get_extra_info_object_from_id(f['uploader']) + + inward_files = add_uploader_department_to_files_list(inward_files) + context = { - 'in_file': inward_file, - 'designations': designations, + 'in_file': inward_files, + 'designations': designation, } - return render(request, 'filetracking/fileview2.html', context) + return render(request, 'filetracking/inbox.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 +304,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,7 +328,7 @@ def inward(request): """ designation = get_designation(request.user) context = { - + 'designation': designation, } return render(request, 'filetracking/inward.html', context) @@ -306,7 +336,6 @@ def inward(request): @login_required(login_url = "/accounts/login") def confirmdelete(request,id): - """ The function is used to confirm the deletion of a file. @param: @@ -316,16 +345,86 @@ 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") +def view_file(request, id): + ''' + This function is used to view a particular file received by an employee from another. + This function also conditionally renders two forms 'forward_file' and 'archive_file' + based on if the user has necessary permissions or not. + The business permissions are as follows: + 1. User can forward file only if they are the last recipient of the file + 2. User can archive a file only if they have received it last and they are also the original owner of the file -@login_required(login_url = "/accounts/login") + To forward the file and to archive the file separate views with POST request are called + + It displays the details file of a File and remarks as well as the attachments of all the users + who have been involved till that point of the workflow. + + @param: + request - Trivial. + id - ID of the file object which the user intends to forward to another employee. + + @variables: + file - The File object. + track - The Tracking object. + designation - the designations of the 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).order_by('receive_date') + designations = get_designation(request.user) + + forward_enable = False + archive_enable = False + + current_owner = get_current_file_owner(file.id) + file_uploader = get_user_object_from_username(file.uploader.user.username) + + + if current_owner == request.user and file.is_read is False: + forward_enable = True + if current_owner == request.user and file_uploader == request.user and file.is_read is False: + archive_enable = True + + context = { + 'designations': designations, + 'file': file, + 'track': track, + 'forward_enable': forward_enable, + 'archive_enable': archive_enable, + } + return render(request, 'filetracking/viewfile.html', context) + +@login_required(login_url="/accounts/login") +def archive_file(request, id): + '''This function is used to archive a file. + It returns unauthorized access if the user is not file uploader + and the current owner of the file + ''' + if request.method == "POST": + file = get_object_or_404(File, id=id); + current_owner = get_current_file_owner(file.id) + file_uploader = get_user_object_from_username(file.uploader.user.username) + if current_owner == request.user and file_uploader == request.user: + file.is_read = True + file.save() + messages.success(request, 'File Archived') + else: + messages.error(request, 'Unauthorized access') + + return render(request, 'filetracking/composefile.html') + +@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 +450,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).order_by('receive_date') - 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,83 +523,88 @@ 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_view(request, id): + """ + The function is used to fetch the files in the user's archive + (those which have passed by user and been archived/finished) -@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') - + @param: + request - trivial. + id - HoldsDesignation object id - 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) - s = str(abcd).split(" - ") - designations = s[1] - #designations = HoldsDesignation.objects.filter(user=request.user) - # for x in designations: - # if abcd==x: - # designations=abcd + @variables: + archive_files - File object with additional information + context - Holds data needed to make necessary changes in the template. - context = { + """ + user_HoldsDesignation_obj = HoldsDesignation.objects.select_related( + 'user', 'working', 'designation').get(pk=id) + s = str(user_HoldsDesignation_obj).split(" - ") + designation = s[1] - 'draft': draft, - 'extrainfo': extrainfo, - 'designations': designations, - } + archive_files = view_archived( + username=user_HoldsDesignation_obj.user, + designation=user_HoldsDesignation_obj.designation, + src_module='filetracking' + ) + # correct upload_date type and add receive_date + for f in archive_files: + f['upload_date'] = parse_datetime(f['upload_date']) + f['designation'] = Designation.objects.get(id=f['designation']) + f['uploader'] = get_extra_info_object_from_id(f['uploader']) + archive_files = add_uploader_department_to_files_list(archive_files) + context = { + 'archive_files': archive_files, + 'designations': designation, + } + 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,38 +614,29 @@ 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): + """ This function returns the designation of receiver on the forward or compose file template. @param: request - trivial. - + @variables: context - return the httpresponce containing the matched designation of the user @@ -553,20 +647,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 @@ -589,24 +682,22 @@ def test(request): @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/') + return redirect('/filetracking/draftdesign/') def forward_inward(request,id): - """ This function is used forward the files which are available in the inbox of the user . @param: @@ -617,21 +708,25 @@ 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) - +def get_designations_view(request, username): + designations = get_designations(username) + print(designations) + return JsonResponse(designations, safe=False) + diff --git a/FusionIIIT/applications/globals/migrations/0002_auto_20240308_1023.py b/FusionIIIT/applications/globals/migrations/0002_auto_20240308_1023.py new file mode 100644 index 000000000..9fa2bfc59 --- /dev/null +++ b/FusionIIIT/applications/globals/migrations/0002_auto_20240308_1023.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.5 on 2024-03-08 10:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('globals', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='extrainfo', + name='user_status', + field=models.CharField(choices=[('NEW', 'NEW'), ('PRESENT', 'PRESENT')], default='PRESENT', max_length=50), + ), + ] diff --git a/FusionIIIT/applications/globals/migrations/0003_auto_20240308_1025.py b/FusionIIIT/applications/globals/migrations/0003_auto_20240308_1025.py new file mode 100644 index 000000000..2f9f4c3d6 --- /dev/null +++ b/FusionIIIT/applications/globals/migrations/0003_auto_20240308_1025.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.5 on 2024-03-08 10:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('globals', '0002_auto_20240308_1023'), + ] + + operations = [ + migrations.AlterField( + model_name='extrainfo', + name='user_status', + field=models.CharField(choices=[('PRESENT', 'PRESENT'), ('NEW', 'NEW')], default='PRESENT', max_length=50), + ), + ] diff --git a/FusionIIIT/applications/iwdModuleV2/migrations/0002_bills_requests.py b/FusionIIIT/applications/iwdModuleV2/migrations/0002_bills_requests.py new file mode 100644 index 000000000..24909bc10 --- /dev/null +++ b/FusionIIIT/applications/iwdModuleV2/migrations/0002_bills_requests.py @@ -0,0 +1,41 @@ +# Generated by Django 3.1.5 on 2024-03-08 10:23 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('iwdModuleV2', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Requests', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('description', models.CharField(max_length=200)), + ('area', models.CharField(max_length=200)), + ('requestCreatedBy', models.CharField(max_length=200)), + ('engineerProcessed', models.IntegerField()), + ('directorApproval', models.IntegerField()), + ('deanProcessed', models.IntegerField()), + ('status', models.CharField(max_length=200)), + ], + ), + migrations.CreateModel( + name='Bills', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('work', models.CharField(max_length=200)), + ('description', models.CharField(max_length=200)), + ('agency', models.CharField(max_length=200)), + ('bill_processed', models.IntegerField()), + ('bill_settled', models.IntegerField()), + ('key', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='iwdModuleV2.projects', unique=True)), + ], + ), + ] diff --git a/FusionIIIT/applications/iwdModuleV2/models.py b/FusionIIIT/applications/iwdModuleV2/models.py index c0754c70d..e4c09f3cc 100644 --- a/FusionIIIT/applications/iwdModuleV2/models.py +++ b/FusionIIIT/applications/iwdModuleV2/models.py @@ -1,5 +1,5 @@ from django.db import models - +from datetime import date # Create your models here. @@ -170,6 +170,24 @@ class Requests(models.Model): directorApproval = models.IntegerField() deanProcessed = models.IntegerField() status = models.CharField(max_length=200) + issuedWorkOrder = models.IntegerField() + workCompleted = models.IntegerField() + +class WorkOrder(models.Model): + request_id = models.IntegerField() + name = models.CharField(max_length=200) + date = models.DateField(default=date.today) + agency = models.CharField(max_length=200) + amount = models.IntegerField() + deposit = models.IntegerField() + alloted_time = models.CharField(max_length=200) + start_date = models.DateField() + completion_date = models.DateField() + +class Inventory(models.Model): + name = models.CharField(max_length=200) + quantity = models.IntegerField() + cost = models.IntegerField() class Bills(models.Model): key = models.ForeignKey(Projects, on_delete=models.CASCADE, unique=True) diff --git a/FusionIIIT/applications/iwdModuleV2/urls.py b/FusionIIIT/applications/iwdModuleV2/urls.py index 2f047d690..1530d11c5 100644 --- a/FusionIIIT/applications/iwdModuleV2/urls.py +++ b/FusionIIIT/applications/iwdModuleV2/urls.py @@ -46,6 +46,18 @@ url('handleDirectorApprovalRequests/', views.handleDirectorApprovalRequests, name='Director-Approval-Requests'), url('handleDirectorRejectionRequests/', views.handleDirectorRejectionRequests, name='Director-Rejection-Requests'), url('requestsStatus/', views.requestsStatus, name='Requests-Status'), - url('billsView/',views.billsView, name='Bills View'), + url('fetchDesignations/', views.fetchDesignations, name='Fetch-Designations'), + url('fetchRequest/', views.fetchRequest, name='Fetch-Request'), + url('issueWorkOrder/', views.issueWorkOrder, name='Issue Work Order'), + url('workOrder/', views.workOrder, name='Work Order'), + url('inventory/', views.inventory, name='Inventory'), + url('addItemsView/', views.addItemsView, name='Add Items View'), + url('addItems/', views.addItems, name='Add Items'), + url('editInventoryView/', views.editInventoryView, name='Edit Inventory View'), + url('editInventory/', views.editInventory, name='Edit Inventory'), + url('requestsInProgess/', views.requestsInProgess, name='Requests In Progress'), + url('workCompleted/', views.workCompleted, name='Work Completed'), + url('requestFromInventory/', views.requestFromInventory, name='Request From Inventory'), + # url('billsView/',views.billsView, name='Bills View'), ] diff --git a/FusionIIIT/applications/iwdModuleV2/views.py b/FusionIIIT/applications/iwdModuleV2/views.py index 0a532548d..d661d67b4 100644 --- a/FusionIIIT/applications/iwdModuleV2/views.py +++ b/FusionIIIT/applications/iwdModuleV2/views.py @@ -1,9 +1,11 @@ from django.shortcuts import render, redirect +from django.urls import reverse from django.db.models import Q from applications.globals.models import * from .models import * from django.http import HttpResponseRedirect - +from applications.filetracking.sdk.methods import * +from applications.globals.models import ExtraInfo, HoldsDesignation, Designation # Create your views here. @@ -409,6 +411,19 @@ def extensionFormView(request): extensionObjects = ExtensionOfTimeDetails.objects.filter(key=Projects.objects.get(id=request.session['projectId'])) return render(request, 'iwdModuleV2/ExtensionForm.html', {'extension': extensionObjects}) +def fetchDesignations(request): + print("yesslkednonmedcm") + designations = Designation.objects.filter() + + holdsDesignations = [] + + for d in designations: + if d.name == "Engineer" or d.name == "Dean" or d.name == "director" or d.name == "Accounts Admin": + list = HoldsDesignation.objects.filter(designation=d) + holdsDesignations.append(list) + + return render(request, 'iwdModuleV2/requestsView.html', {'holdsDesignations' : holdsDesignations}) + def requestsView(request): if request.method == 'POST': formObject = Requests() @@ -421,87 +436,243 @@ def requestsView(request): formObject.deanProcessed = 0 formObject.requestCreatedBy = request.user.username formObject.status = "Pending" + formObject.issuedWorkOrder = 0 + formObject.workCompleted = 0 formObject.save() + request_object = Requests.objects.get(pk=formObject.pk) + d = HoldsDesignation.objects.get(user__username=request.POST['designation']) + create_file(uploader=request.user.username, + uploader_designation="Engineer", + receiver=request.POST['designation'], + receiver_designation=d.designation, + src_module="IWD", + src_object_id= str(request_object.id), + file_extra_JSON= {"value": 2}, + attached_file = None) return redirect('http://127.0.0.1:8000/iwdModuleV2/') return render(request, 'http://127.0.0.1:8000/iwdModuleV2/', {}) - -def billsView(request): - if request.method == 'POST': - formObject = Requests() - # formObject.key = Projects.objects.get(id=request.session['projectId']) - formObject.name = request.POST['name'] - formObject.work = request.POST['work'] - formObject.description = request.POST['description'] - formObject.agency = request.POST['agency'] - formObject.bill_processed = request.POST['bill_processed'] - formObject.bill_settled = request.POST['bill_settled'] - formObject.save() - return redirect('iwdModuleV2/billsView.html') - return render(request, 'iwdModuleV2/billsView.html', {}) - def createdRequests(request): obj = [] - requestsObject = Requests.objects.exclude( - Q(requestCreatedBy=request.user.username) | - Q(engineerProcessed__gt=0) | - Q(deanProcessed__gt=0) | - Q(directorApproval__gt=0) + + inbox_files = view_inbox( + username=request.user, + designation="Engineer", + src_module="IWD" ) - for x in requestsObject: - element = [x.id, x.name, x.area, x.description, x.requestCreatedBy] - obj.append(element) - return render(request, 'iwdModuleV2/createdRequests.html', {'obj' : obj}) + for result in inbox_files: + src_object_id = result['src_object_id'] + request_object = Requests.objects.filter(id=src_object_id).first() + if request_object: + element = [request_object.id, request_object.name, request_object.area, request_object.description, request_object.requestCreatedBy] + obj.append(element) + + designations = Designation.objects.filter() + + holdsDesignations = [] + + for d in designations: + if d.name == "Engineer" or d.name == "Dean" or d.name == "director" or d.name == "Accounts Admin": + list = HoldsDesignation.objects.filter(designation=d) + holdsDesignations.append(list) + + return render(request, 'iwdModuleV2/createdRequests.html', {'obj' : obj, 'holdsDesignations' : holdsDesignations}) def handleEngineerProcessRequests(request): if request.method == 'POST': + request_id = request.POST.get("id", 0) + + d = HoldsDesignation.objects.get(user__username=request.POST['designation']) + d1 = HoldsDesignation.objects.get(user__username=request.user) + + create_file(uploader=request.user.username, + uploader_designation=d1.designation, + receiver=request.POST['designation'], + receiver_designation=d.designation, + src_module="IWD", + src_object_id= str(request_id), + file_extra_JSON= {"value": 2}, + attached_file = None) + Requests.objects.filter(id=request_id).update(engineerProcessed=1, status="Approved by the engineer") + + inbox_files = view_inbox( + username=request.user, + designation=d1.designation, + src_module="IWD" + ) + + for p in inbox_files: + if p['src_object_id'] == request_id: + delete_file(file_id = p['id']) + break + + inbox_files = view_inbox( + username=request.user, + designation=d1.designation, + src_module="IWD" + ) + obj = [] - requestsObject = Requests.objects.filter(engineerProcessed = 0, deanProcessed = 0, directorApproval = 0) - for x in requestsObject: - element = [x.id, x.name, x.area, x.description, x.requestCreatedBy] - obj.append(element) + for result in inbox_files: + src_object_id = result['src_object_id'] + request_object = Requests.objects.filter(id=src_object_id).first() + if request_object: + element = [request_object.id, request_object.name, request_object.area, request_object.description, request_object.requestCreatedBy] + obj.append(element) + return render(request, 'iwdModuleV2/createdRequests.html', {'obj' : obj}) def engineerProcessedRequests(request): + obj = [] - requestsObject = Requests.objects.filter(engineerProcessed = 1, deanProcessed = 0, directorApproval = 0) - for x in requestsObject: - element = [x.id, x.name, x.area, x.description, x.requestCreatedBy] - obj.append(element) - return render(request, 'iwdModuleV2/engineerProcessedRequests.html', {'obj' : obj}) + + d = HoldsDesignation.objects.get(user__username=request.user) + + inbox_files = view_inbox( + username=request.user, + designation=d.designation, + src_module="IWD" + ) + + for result in inbox_files: + src_object_id = result['src_object_id'] + request_object = Requests.objects.filter(id=src_object_id).first() + if request_object: + element = [request_object.id, request_object.name, request_object.area, request_object.description, request_object.requestCreatedBy] + obj.append(element) + + designations = Designation.objects.filter() + + holdsDesignations = [] + + for d in designations: + if d.name == "Engineer" or d.name == "Dean" or d.name == "director" or d.name == "Accounts Admin": + list = HoldsDesignation.objects.filter(designation=d) + holdsDesignations.append(list) + + return render(request, 'iwdModuleV2/engineerProcessedRequests.html', {'obj' : obj, 'holdsDesignations' : holdsDesignations}) def handleDeanProcessRequests(request): if request.method == 'POST': + request_id = request.POST.get("id", 0) + + d = HoldsDesignation.objects.get(user__username=request.POST['designation']) + d1 = HoldsDesignation.objects.get(user__username=request.user) + + create_file(uploader=request.user.username, + uploader_designation=d1.designation, + receiver=request.POST['designation'], + receiver_designation=d.designation, + src_module="IWD", + src_object_id= str(request_id), + file_extra_JSON= {"value": 2}, + attached_file = None) + Requests.objects.filter(id=request_id).update(deanProcessed=1, status="Approved by the dean") + + inbox_files = view_inbox( + username=request.user, + designation=d1.designation, + src_module="IWD" + ) + + for p in inbox_files: + if p['src_object_id'] == request_id: + delete_file(file_id = p['id']) + break + + inbox_files = view_inbox( + username=request.user, + designation=d1.designation, + src_module="IWD" + ) + obj = [] - requestsObject = Requests.objects.filter(engineerProcessed = 1, deanProcessed = 0, directorApproval = 0) - for x in requestsObject: - element = [x.id, x.name, x.area, x.description, x.requestCreatedBy] - obj.append(element) + for result in inbox_files: + src_object_id = result['src_object_id'] + request_object = Requests.objects.filter(id=src_object_id).first() + if request_object: + element = [request_object.id, request_object.name, request_object.area, request_object.description, request_object.requestCreatedBy] + obj.append(element) + return render(request, 'iwdModuleV2/engineerProcessedRequests.html', {'obj' : obj}) def deanProcessedRequests(request): - print(request) obj = [] - requestsObject = Requests.objects.filter(engineerProcessed = 1, deanProcessed = 1, directorApproval = 0) - for x in requestsObject: - element = [x.id, x.name, x.area, x.description, x.requestCreatedBy] - obj.append(element) - return render(request, 'iwdModuleV2/deanProcessedRequests.html', {'obj' : obj}) + + d = HoldsDesignation.objects.get(user__username=request.user) + + inbox_files = view_inbox( + username=request.user, + designation=d.designation, + src_module="IWD" + ) + + for result in inbox_files: + src_object_id = result['src_object_id'] + request_object = Requests.objects.filter(id=src_object_id).first() + if request_object: + element = [request_object.id, request_object.name, request_object.area, request_object.description, request_object.requestCreatedBy] + obj.append(element) + + designations = Designation.objects.filter() + + holdsDesignations = [] + + for d in designations: + if d.name == "Engineer" or d.name == "Dean" or d.name == "director" or d.name == "Accounts Admin": + list = HoldsDesignation.objects.filter(designation=d) + holdsDesignations.append(list) + + return render(request, 'iwdModuleV2/deanProcessedRequests.html', {'obj' : obj, 'holdsDesignations' : holdsDesignations}) def handleDirectorApprovalRequests(request): if request.method == 'POST': request_id = request.POST.get("id", 0) + + d = HoldsDesignation.objects.get(user__username=request.POST['designation']) + d1 = HoldsDesignation.objects.get(user__username=request.user) + + create_file(uploader=request.user.username, + uploader_designation=d1.designation, + receiver=request.POST['designation'], + receiver_designation=d.designation, + src_module="IWD", + src_object_id= str(request_id), + file_extra_JSON= {"value": 2}, + attached_file = None) + Requests.objects.filter(id=request_id).update(directorApproval=1, status="Approved by the director") + + inbox_files = view_inbox( + username=request.user, + designation=d1.designation, + src_module="IWD" + ) + + for p in inbox_files: + if p['src_object_id'] == request_id: + delete_file(file_id = p['id']) + break + + inbox_files = view_inbox( + username=request.user, + designation=d1.designation, + src_module="IWD" + ) + obj = [] - requestsObject = Requests.objects.filter(engineerProcessed = 1, deanProcessed = 1, directorApproval = 0) - for x in requestsObject: - element = [x.id, x.name, x.area, x.description, x.requestCreatedBy] - obj.append(element) + for result in inbox_files: + src_object_id = result['src_object_id'] + request_object = Requests.objects.filter(id=src_object_id).first() + if request_object: + element = [request_object.id, request_object.name, request_object.area, request_object.description, request_object.requestCreatedBy] + obj.append(element) + return render(request, 'iwdModuleV2/deanProcessedRequests.html', {'obj' : obj}) def handleDirectorRejectionRequests(request): @@ -515,8 +686,82 @@ def handleDirectorRejectionRequests(request): obj.append(element) return render(request, 'iwdModuleV2/deanProcessedRequests.html', {'obj' : obj}) +def issueWorkOrder(request): + obj = [] + + d = HoldsDesignation.objects.get(user__username=request.user) + + inbox_files = view_inbox( + username=request.user, + designation=d.designation, + src_module="IWD" + ) + + for result in inbox_files: + uploader = result['sent_by_designation'] + if uploader == 'director': + src_object_id = result['src_object_id'] + request_object = Requests.objects.filter(id=src_object_id).first() + if request_object: + element = [request_object.id, request_object.name, request_object.area, request_object.description, request_object.requestCreatedBy] + obj.append(element) + + return render(request, 'iwdModuleV2/issueWorkOrder.html', {'obj' : obj}) + +def fetchRequest(request): + request_id = request.POST.get("id", 0) + req_request = Requests.objects.get(id=request_id) + return render(request, 'iwdModuleV2/workOrder.html', {'req' : req_request}) + +def workOrder(request): + if request.method == 'POST': + formObject = WorkOrder() + formObject.request_id = request.POST['id'] + formObject.name = request.POST['name'] + formObject.date = request.POST['date'] + formObject.agency = request.POST['agency'] + formObject.amount = request.POST['amount'] + formObject.deposit = request.POST['deposit'] + formObject.alloted_time = request.POST['time'] + formObject.start_date = request.POST['startDate'] + formObject.completion_date = request.POST['completionDate'] + formObject.save() + + Requests.objects.filter(id=request.POST['id']).update(status="Work Order issued", issuedWorkOrder=1) + + d = HoldsDesignation.objects.get(user__username=request.user) + + inbox_files = view_inbox( + username=request.user, + designation=d.designation, + src_module="IWD" + ) + + for result in inbox_files: + if result['src_object_id'] == request.POST['id'] and result['sent_by_designation'] == 'director': + delete_file(file_id = result['id']) + break + + inbox_files = view_inbox( + username=request.user, + designation=d.designation, + src_module="IWD" + ) + + obj = [] + + for result in inbox_files: + uploader = result['sent_by_designation'] + if uploader == 'director': + src_object_id = result['src_object_id'] + request_object = Requests.objects.filter(id=src_object_id).first() + if request_object: + element = [request_object.id, request_object.name, request_object.area, request_object.description, request_object.requestCreatedBy] + obj.append(element) + + return render(request, 'iwdModuleV2/issueWorkOrder.html', {'obj' : obj}) + def requestsStatus(request): - print(request) obj = [] requestsObject = Requests.objects.all() for x in requestsObject: @@ -524,3 +769,75 @@ def requestsStatus(request): obj.append(element) return render(request, 'iwdModuleV2/requestsStatus.html', {'obj' : obj}) +def inventory(request): + items = Inventory.objects.filter() + obj = [] + for i in items: + element = [i.id, i.name, i.quantity, i.cost] + obj.append(element) + return render(request, 'iwdModuleV2/inventory.html', {'obj' : obj}) + +def addItemsView(request): + return render(request, 'iwdModuleV2/addItemsView.html') + +def addItems(request): + if request.method == "POST": + formObject = Inventory() + formObject.name = request.POST['name'] + formObject.quantity = request.POST['quantity'] + formObject.cost = request.POST['cost'] + formObject.save() + return render(request, 'iwdModuleV2/addItemsView.html') + +def editInventoryView(request): + items = Inventory.objects.filter() + obj = [] + for i in items: + element = [i.id, i.name, i.quantity, i.cost] + obj.append(element) + return render(request, 'iwdModuleV2/editInventory.html', {'obj' : obj}) + +def editInventory(request): + if request.method == "POST": + itemId = request.POST['id'] + itemName = request.POST['name'] + itemQuantity = request.POST['quantity'] + itemCost = request.POST['cost'] + Inventory.objects.filter(id=itemId).update(name=itemName, quantity=itemQuantity, cost=itemCost) + items = Inventory.objects.filter() + obj = [] + for i in items: + element = [i.id, i.name, i.quantity, i.cost] + obj.append(element) + return render(request, 'iwdModuleV2/editInventory.html', {'obj' : obj}) + +def requestsInProgess(request): + obj = [] + requestsObject = Requests.objects.filter(issuedWorkOrder=1) + for x in requestsObject: + element = [x.id, x.name, x.area, x.description, x.requestCreatedBy, x.workCompleted] + obj.append(element) + return render(request, 'iwdModuleV2/requestsInProgress.html', {'obj' : obj}) + +def workCompleted(request): + if request.method == 'POST': + Requests.objects.filter(id=request.POST['id']).update(workCompleted=1, status="Work Completed") + obj = [] + requestsObject = Requests.objects.filter(issuedWorkOrder=1) + for x in requestsObject: + element = [x.id, x.name, x.area, x.description, x.requestCreatedBy, x.workCompleted] + obj.append(element) + return render(request, 'iwdModuleV2/requestsInProgress.html', {'obj' : obj}) + +def requestFromInventory(request): + if request.method == 'POST': + requestId = request.POST['id'] + Req = Requests.objects.filter(id=requestId) + Items = Inventory.objects.filter() + req = [] + items = [] + for i in Req: + print(i) + print(req) + print(items) + return render(request, 'iwdModuleV2/requestFromInventory.html', {'req' : req, 'items' : items}) \ No newline at end of file diff --git a/FusionIIIT/applications/programme_curriculum/migrations/0002_auto_20240308_1023.py b/FusionIIIT/applications/programme_curriculum/migrations/0002_auto_20240308_1023.py new file mode 100644 index 000000000..fef68f722 --- /dev/null +++ b/FusionIIIT/applications/programme_curriculum/migrations/0002_auto_20240308_1023.py @@ -0,0 +1,23 @@ +# Generated by Django 3.1.5 on 2024-03-08 10:23 + +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/scholarships/migrations/0002_auto_20240308_1023.py b/FusionIIIT/applications/scholarships/migrations/0002_auto_20240308_1023.py new file mode 100644 index 000000000..997db0247 --- /dev/null +++ b/FusionIIIT/applications/scholarships/migrations/0002_auto_20240308_1023.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.5 on 2024-03-08 10:23 + +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/iwdModuleV2/addItemsView.html b/FusionIIIT/templates/iwdModuleV2/addItemsView.html new file mode 100644 index 000000000..b9b1f003c --- /dev/null +++ b/FusionIIIT/templates/iwdModuleV2/addItemsView.html @@ -0,0 +1,120 @@ +{% extends 'globals/base.html' %} +{% load static %} + + +{% block title %} +Academic +{% endblock %} + + +{% block body %} +{% block navBar %} +{% include 'dashboard/navbar.html' %} +{% endblock %} + +
+ + {% comment %}The left-margin segment!{% endcomment %} +
+ + {% comment %}The left-rail segment starts here!{% endcomment %} +
+ {% comment %}The user image card starts here!{% endcomment %} + {% block usercard %} + {% include 'globals/usercard.html' %} + {% endblock %} + {% comment %}The user image card ends here!{% endcomment %} + +
+ + {% comment %}The Tab-Menu ends here!{% endcomment %} +
+ {% comment %} + The left-rail segment ends here! + {% endcomment %} + + {% comment %} + The central-rail segment starts here! + {% endcomment %} +
+ + + + {% load static %} + {% comment %}the main tab starts here {% endcomment %} + +
+ Add Items +
+
+ {% csrf_token %} +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+ +
+
+ + + +
+ {% comment %}The central-rail segment ends here!{% endcomment %} + + {% comment %}The right-rail segment starts here!{% endcomment %} +
+
+ {% comment %} + TODO: the right rail! + {% endcomment %} +
+
+ {% comment %}The right-rail segment ends here!{% endcomment %} + + {% comment %}The right-margin segment!{% endcomment %} +
+ +
+{% comment %}The grid ends here!{% endcomment %} + +{% endblock %} + +{% block javascript %} + + + + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/iwdModuleV2/createdRequests.html b/FusionIIIT/templates/iwdModuleV2/createdRequests.html index a7f86e523..cce743dec 100644 --- a/FusionIIIT/templates/iwdModuleV2/createdRequests.html +++ b/FusionIIIT/templates/iwdModuleV2/createdRequests.html @@ -61,6 +61,7 @@ Description Area Created By + Send to @@ -76,6 +77,13 @@
{% csrf_token %} +
diff --git a/FusionIIIT/templates/iwdModuleV2/dashboard.html b/FusionIIIT/templates/iwdModuleV2/dashboard.html index 12c27a550..f18a5c156 100644 --- a/FusionIIIT/templates/iwdModuleV2/dashboard.html +++ b/FusionIIIT/templates/iwdModuleV2/dashboard.html @@ -38,7 +38,7 @@ - {% comment %}The left-rail segment ends here!{% endcomment %} - - {% comment %}The central-rail segment starts here!{% endcomment %} -
- {% comment %}The Appointments Form starts here!{% endcomment %} -
- {% block appointment %} - {% include 'iwdModuleV2/requestsView.html' %} - {% endblock %} -
-
{% endif %} {% if eligible == "Dean" %} @@ -121,6 +119,26 @@
{% comment %}The left-rail segment ends here!{% endcomment %} + {% comment %}The central-rail segment starts here!{% endcomment %} + {% endif %} + {% if eligible == "Admin IWD" %} +
+ {% comment %}The Tab-Menu starts here!{% endcomment %} + + {% comment %}The Tab-Menu ends here!{% endcomment %} + +
+ {% comment %}ROW #2 ends here!{% endcomment %} + + + {% comment %}The left-rail segment ends here!{% endcomment %} + {% comment %}The central-rail segment starts here!{% endcomment %} {% endif %} {% comment %}The central-rail segment ends here!{% endcomment %} diff --git a/FusionIIIT/templates/iwdModuleV2/deanProcessedRequests.html b/FusionIIIT/templates/iwdModuleV2/deanProcessedRequests.html index dd9ba8ba8..98f9ad72f 100644 --- a/FusionIIIT/templates/iwdModuleV2/deanProcessedRequests.html +++ b/FusionIIIT/templates/iwdModuleV2/deanProcessedRequests.html @@ -68,11 +68,25 @@
{% csrf_token %} +
{% csrf_token %} +
diff --git a/FusionIIIT/templates/iwdModuleV2/editInventory.html b/FusionIIIT/templates/iwdModuleV2/editInventory.html new file mode 100644 index 000000000..1cc32767f --- /dev/null +++ b/FusionIIIT/templates/iwdModuleV2/editInventory.html @@ -0,0 +1,124 @@ +{% extends 'globals/base.html' %} +{% load static %} + + +{% block title %} +Academic +{% endblock %} + + +{% block body %} +{% block navBar %} +{% include 'dashboard/navbar.html' %} +{% endblock %} + +
+ + {% comment %}The left-margin segment!{% endcomment %} +
+ + {% comment %}The left-rail segment starts here!{% endcomment %} +
+ {% comment %}The user image card starts here!{% endcomment %} + {% block usercard %} + {% include 'globals/usercard.html' %} + {% endblock %} + {% comment %}The user image card ends here!{% endcomment %} + +
+ + {% comment %}The Tab-Menu ends here!{% endcomment %} +
+ {% comment %} + The left-rail segment ends here! + {% endcomment %} + + {% comment %} + The central-rail segment starts here! + {% endcomment %} +
+ + + + {% load static %} + {% comment %}the main tab starts here {% endcomment %} +
+ + +
+
+ Inventory +
+
+
+
+ + + + + + + + + + + + + {% for f in obj %} + + + + {% csrf_token %} + + + + + + + + + {% endfor %} +
IdNameQuantityCost (in Rupees)
{{f.0}} + + + + + + + + +
+
+
+
+ + + +
+ {% comment %}The central-rail segment ends here!{% endcomment %} + + {% comment %}The right-rail segment starts here!{% endcomment %} +
+
+ {% comment %} + TODO: the right rail! + {% endcomment %} +
+
+ {% comment %}The right-rail segment ends here!{% endcomment %} + + {% comment %}The right-margin segment!{% endcomment %} +
+ +
+{% comment %}The grid ends here!{% endcomment %} + +{% endblock %} + +{% block javascript %} + + + + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/iwdModuleV2/engineerProcessedRequests.html b/FusionIIIT/templates/iwdModuleV2/engineerProcessedRequests.html index 7c3bd813d..6b7386054 100644 --- a/FusionIIIT/templates/iwdModuleV2/engineerProcessedRequests.html +++ b/FusionIIIT/templates/iwdModuleV2/engineerProcessedRequests.html @@ -78,6 +78,13 @@
{% csrf_token %} +
diff --git a/FusionIIIT/templates/iwdModuleV2/inventory.html b/FusionIIIT/templates/iwdModuleV2/inventory.html new file mode 100644 index 000000000..4e35ce614 --- /dev/null +++ b/FusionIIIT/templates/iwdModuleV2/inventory.html @@ -0,0 +1,111 @@ +{% extends 'globals/base.html' %} +{% load static %} + + +{% block title %} +Academic +{% endblock %} + + +{% block body %} +{% block navBar %} +{% include 'dashboard/navbar.html' %} +{% endblock %} + +
+ + {% comment %}The left-margin segment!{% endcomment %} +
+ + {% comment %}The left-rail segment starts here!{% endcomment %} +
+ {% comment %}The user image card starts here!{% endcomment %} + {% block usercard %} + {% include 'globals/usercard.html' %} + {% endblock %} + {% comment %}The user image card ends here!{% endcomment %} + +
+ + {% comment %}The Tab-Menu ends here!{% endcomment %} +
+ {% comment %} + The left-rail segment ends here! + {% endcomment %} + + {% comment %} + The central-rail segment starts here! + {% endcomment %} +
+ + + + {% load static %} + {% comment %}the main tab starts here {% endcomment %} +
+ + + +
+
+ Inventory +
+
+
+
+ + + + + + + + + + + + {% for f in obj %} + + + + + + + + + {% endfor %} +
IdNameQuantityCost (in Rupees)
{{f.0}}{{f.1}}{{f.2}}{{f.3}}
+
+
+
+ + + +
+ {% comment %}The central-rail segment ends here!{% endcomment %} + + {% comment %}The right-rail segment starts here!{% endcomment %} +
+
+ {% comment %} + TODO: the right rail! + {% endcomment %} +
+
+ {% comment %}The right-rail segment ends here!{% endcomment %} + + {% comment %}The right-margin segment!{% endcomment %} +
+ +
+{% comment %}The grid ends here!{% endcomment %} + +{% endblock %} + +{% block javascript %} + + + + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/iwdModuleV2/issueWorkOrder.html b/FusionIIIT/templates/iwdModuleV2/issueWorkOrder.html new file mode 100644 index 000000000..7aef765b2 --- /dev/null +++ b/FusionIIIT/templates/iwdModuleV2/issueWorkOrder.html @@ -0,0 +1,120 @@ +{% extends 'globals/base.html' %} +{% load static %} + + +{% block title %} +Academic +{% endblock %} + + +{% block body %} +{% block navBar %} +{% include 'dashboard/navbar.html' %} +{% endblock %} + +
+ + {% comment %}The left-margin segment!{% endcomment %} +
+ + {% comment %}The left-rail segment starts here!{% endcomment %} +
+ {% comment %}The user image card starts here!{% endcomment %} + {% block usercard %} + {% include 'globals/usercard.html' %} + {% endblock %} + {% comment %}The user image card ends here!{% endcomment %} + +
+ + {% comment %}The Tab-Menu ends here!{% endcomment %} +
+ {% comment %} + The left-rail segment ends here! + {% endcomment %} + + {% comment %} + The central-rail segment starts here! + {% endcomment %} +
+ + + + {% load static %} + {% comment %}the main tab starts here {% endcomment %} +
+ +
+
+ Issue Work Order +
+
+
+
+ + + + + + + + + + + + + + {% for f in obj %} + + + + + + + + + + + {% endfor %} +
Details:-
IdNameDescriptionAreaCreated By
{{f.0}}{{f.1}}{{f.3}}{{f.2}}{{f.4}} + +
+ {% csrf_token %} + + +
+
+
+
+
+ + + +
+ {% comment %}The central-rail segment ends here!{% endcomment %} + + {% comment %}The right-rail segment starts here!{% endcomment %} +
+
+ {% comment %} + TODO: the right rail! + {% endcomment %} +
+
+ {% comment %}The right-rail segment ends here!{% endcomment %} + + {% comment %}The right-margin segment!{% endcomment %} +
+ +
+{% comment %}The grid ends here!{% endcomment %} + +{% endblock %} + +{% block javascript %} + + + + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/iwdModuleV2/requestFromInventory.html b/FusionIIIT/templates/iwdModuleV2/requestFromInventory.html new file mode 100644 index 000000000..c17aeb3da --- /dev/null +++ b/FusionIIIT/templates/iwdModuleV2/requestFromInventory.html @@ -0,0 +1,172 @@ +{% extends 'globals/base.html' %} +{% load static %} + + +{% block title %} +Academic +{% endblock %} + + +{% block body %} +{% block navBar %} +{% include 'dashboard/navbar.html' %} +{% endblock %} + +
+ + {% comment %}The left-margin segment!{% endcomment %} +
+ + {% comment %}The left-rail segment starts here!{% endcomment %} +
+ {% comment %}The user image card starts here!{% endcomment %} + {% block usercard %} + {% include 'globals/usercard.html' %} + {% endblock %} + {% comment %}The user image card ends here!{% endcomment %} + +
+ + {% comment %}The Tab-Menu ends here!{% endcomment %} +
+ {% comment %} + The left-rail segment ends here! + {% endcomment %} + + {% comment %} + The central-rail segment starts here! + {% endcomment %} +
+ + + + {% load static %} + {% comment %}the main tab starts here {% endcomment %} +
+ +
+
+ Work Order +
+
{% csrf_token %} +
+ +
+ +
+
+ + + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ + {% csrf_token %} + + +
+ +
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ {% comment %}The central-rail segment ends here!{% endcomment %} + + {% comment %}The right-rail segment starts here!{% endcomment %} +
+
+ {% comment %} + TODO: the right rail! + {% endcomment %} +
+
+ {% comment %}The right-rail segment ends here!{% endcomment %} + + {% comment %}The right-margin segment!{% endcomment %} +
+ +
+{% comment %}The grid ends here!{% endcomment %} + +{% endblock %} + +{% block javascript %} + + + + +{% endblock %} + + + + diff --git a/FusionIIIT/templates/iwdModuleV2/requestsInProgress.html b/FusionIIIT/templates/iwdModuleV2/requestsInProgress.html new file mode 100644 index 000000000..67809a40c --- /dev/null +++ b/FusionIIIT/templates/iwdModuleV2/requestsInProgress.html @@ -0,0 +1,134 @@ +{% extends 'globals/base.html' %} +{% load static %} + + +{% block title %} +Academic +{% endblock %} + + +{% block body %} +{% block navBar %} +{% include 'dashboard/navbar.html' %} +{% endblock %} + +
+ + {% comment %}The left-margin segment!{% endcomment %} +
+ + {% comment %}The left-rail segment starts here!{% endcomment %} +
+ {% comment %}The user image card starts here!{% endcomment %} + {% block usercard %} + {% include 'globals/usercard.html' %} + {% endblock %} + {% comment %}The user image card ends here!{% endcomment %} + +
+ + {% comment %}The Tab-Menu ends here!{% endcomment %} +
+ {% comment %} + The left-rail segment ends here! + {% endcomment %} + + {% comment %} + The central-rail segment starts here! + {% endcomment %} +
+ + + + {% load static %} + {% comment %}the main tab starts here {% endcomment %} +
+ +
+
+ Created Requests +
+
+
+
+ + + + + + + + + + + + + + {% for f in obj %} + + + + + + + + + + + {% endfor %} +
Details:-
IdNameDescriptionAreaCreated By
{{f.0}}{{f.1}}{{f.3}}{{f.2}}{{f.4}} + {% if f.5 == 1 %} +
+ {% csrf_token %} + + +
+ {% endif %} + {% if f.5 == 0 %} +
+ {% csrf_token %} + + +
+
+
+ {% csrf_token %} + + +
+ {% endif %} +
+
+
+
+ + + +
+ {% comment %}The central-rail segment ends here!{% endcomment %} + + {% comment %}The right-rail segment starts here!{% endcomment %} +
+
+ {% comment %} + TODO: the right rail! + {% endcomment %} +
+
+ {% comment %}The right-rail segment ends here!{% endcomment %} + + {% comment %}The right-margin segment!{% endcomment %} +
+ +
+{% comment %}The grid ends here!{% endcomment %} + +{% endblock %} + +{% block javascript %} + + + + +{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/iwdModuleV2/requestsView.html b/FusionIIIT/templates/iwdModuleV2/requestsView.html index 230ebe362..882e84274 100644 --- a/FusionIIIT/templates/iwdModuleV2/requestsView.html +++ b/FusionIIIT/templates/iwdModuleV2/requestsView.html @@ -1,124 +1,135 @@ - +{% extends 'globals/base.html' %} {% load static %} {% block title %} - Academic +Academic {% endblock %} {% block body %} - {% block navBar %} - - {% endblock %} - - - - {% comment %}The left-margin segment!{% endcomment %} - +{% block navBar %} +{% include 'dashboard/navbar.html' %} +{% endblock %} - {% comment %}The left-rail segment starts here!{% endcomment %} - - {% comment %}The user image card starts here!{% endcomment %} - {% block usercard %} - - {% endblock %} - {% comment %}The user image card ends here!{% endcomment %} +
- + {% comment %}The left-margin segment!{% endcomment %} +
- {% comment %}The Tab-Menu ends here!{% endcomment %} - - {% comment %} - The left-rail segment ends here! - {% endcomment %} + {% comment %}The left-rail segment starts here!{% endcomment %} +
+ {% comment %}The user image card starts here!{% endcomment %} + {% block usercard %} + {% include 'globals/usercard.html' %} + {% endblock %} + {% comment %}The user image card ends here!{% endcomment %} - {% comment %} - The central-rail segment starts here! - {% endcomment %} -
+
+ {% comment %}The Tab-Menu ends here!{% endcomment %} +
+ {% comment %} + The left-rail segment ends here! + {% endcomment %} + {% comment %} + The central-rail segment starts here! + {% endcomment %} +
- {% load static %} -
- Requests -
-
{% csrf_token %} -
+ {% load static %} + {% comment %}the main tab starts here {% endcomment %} +
+ +
+
+ Requests +
+ {% csrf_token %} +
-
+
+
- -
- -
- + +
+ +
+ +
-
- -
- -
- -
- -
-
- + +
+
- - -
- - + +
+
-
- - - -
-
+ +
+ +
+ +
+ +
+
+ +
+ + +
+ +
+ +
+ + + + +
+ {% comment %}The central-rail segment ends here!{% endcomment %} + + {% comment %}The right-rail segment starts here!{% endcomment %} +
+
+ {% comment %} + TODO: the right rail! + {% endcomment %}
-
- - - - {% comment %}The central-rail segment ends here!{% endcomment %} +{% endblock %} - {% comment %}The right-rail segment starts here!{% endcomment %} - - {% comment %}The right-rail segment ends here!{% endcomment %} +{% block javascript %} + + + + +{% endblock %} - {% comment %}The right-margin segment!{% endcomment %} - - {% comment %}The grid ends here!{% endcomment %} -{% endblock %} -{% block javascript %} - - - - -{% endblock %} \ No newline at end of file diff --git a/FusionIIIT/templates/iwdModuleV2/workOrder.html b/FusionIIIT/templates/iwdModuleV2/workOrder.html new file mode 100644 index 000000000..11f2f9d93 --- /dev/null +++ b/FusionIIIT/templates/iwdModuleV2/workOrder.html @@ -0,0 +1,175 @@ +{% extends 'globals/base.html' %} +{% load static %} + + +{% block title %} +Academic +{% endblock %} + + +{% block body %} +{% block navBar %} +{% include 'dashboard/navbar.html' %} +{% endblock %} + +
+ + {% comment %}The left-margin segment!{% endcomment %} +
+ + {% comment %}The left-rail segment starts here!{% endcomment %} +
+ {% comment %}The user image card starts here!{% endcomment %} + {% block usercard %} + {% include 'globals/usercard.html' %} + {% endblock %} + {% comment %}The user image card ends here!{% endcomment %} + +
+ + {% comment %}The Tab-Menu ends here!{% endcomment %} +
+ {% comment %} + The left-rail segment ends here! + {% endcomment %} + + {% comment %} + The central-rail segment starts here! + {% endcomment %} +
+ + + + {% load static %} + {% comment %}the main tab starts here {% endcomment %} + +
+ Work Order +
+
{% csrf_token %} +
+ +
+ + +
+
+ + + + + +
+ +
+ +
+ + +
+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+
+
+ {% comment %}The central-rail segment ends here!{% endcomment %} + + {% comment %}The right-rail segment starts here!{% endcomment %} +
+
+ {% comment %} + TODO: the right rail! + {% endcomment %} +
+
+ {% comment %}The right-rail segment ends here!{% endcomment %} + + {% comment %}The right-margin segment!{% endcomment %} +
+ +
+{% comment %}The grid ends here!{% endcomment %} + +{% endblock %} + +{% block javascript %} + + + + +{% endblock %} + + + +