diff --git a/Inventory/admin.py b/Inventory/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/Inventory/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/Inventory/models.py b/Inventory/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/Inventory/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/Inventory/settings.py b/Inventory/settings.py index a276238..b373a85 100644 --- a/Inventory/settings.py +++ b/Inventory/settings.py @@ -37,6 +37,9 @@ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'questionaire.apps.QuestionaireConfig', + 'chat.apps.ChatConfig', + 'rest_framework', ] MIDDLEWARE = [ @@ -122,4 +125,4 @@ STATICFILES_DIRS = [ os.path.join(BASE_DIR, "interface/static") ] -STATIC_ROOT = os.path.join(BASE_DIR, 'assets') \ No newline at end of file +STATIC_ROOT = os.path.join(BASE_DIR, 'assets') diff --git a/Inventory/urls.py b/Inventory/urls.py index ada27ca..d3f4b7e 100644 --- a/Inventory/urls.py +++ b/Inventory/urls.py @@ -1,22 +1,17 @@ -"""Inventory URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/3.0/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: path('', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.urls import include, path - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) -""" -from django.contrib import admin -from django.urls import path, include +from django.urls import path +from interface import views +from item.views import ItemChartView urlpatterns = [ + path('', views.cover, name='cover'), + path('dashboard', views.dashboard, name='dashboard'), + path('categories', views.categories, name='categories'), + path('check', views.check, name='check'), + path('arsenal', views.arsenal, name='arsenal'), + # path('', ItemChartView.as_view(), name='home'), + path('chart', ItemChartView.as_view(), name = 'chart'), + path('thechatbot',include('questionaire.urls')), + path('chat/',include('chat.urls')), path('admin/', admin.site.urls), - path('', include('interface.urls')) + ] diff --git a/Inventory/views.py b/Inventory/views.py new file mode 100644 index 0000000..ee369aa --- /dev/null +++ b/Inventory/views.py @@ -0,0 +1,22 @@ +from django.shortcuts import render +import sys + +# Create your views here. +def cover(request): + return render(request, "interface/cover.html") + +def dashboard(request): + return render(request, "interface/dashboard.html") + +def categories(request): + return render(request, "interface/categories.html") + +def check(request): + return render(request, "interface/check.html") + + +def arsenal(request): + return render(request, "interface/arsenal.html") + +def chart(request): + return render(request,"chart.html") \ No newline at end of file diff --git a/README.md b/README.md index 37cf979..4a2697b 100644 --- a/README.md +++ b/README.md @@ -1 +1,122 @@ -# Inventory_System_Eurymedons \ No newline at end of file + + + + + + + + + + + + + +# Inventory Management System by Eurymedons + + +## Basic Info +A well designed management system(browser based web application) for eliminating time consuming physical management systems/methods, error-prone manual record keeping and physical reporting methods. + +This project is based on python with various user-friendly features which are completely customizable and editable in the long run. + +A preview is shown below +![Image Preview](https://github.com/codesbyN/Inventory-image-Eurymedon/blob/master/SS1.png "Image Preview") +### Features - :eyes: + * Frameworks - + + Django framework, Dango Rest, Bootstrap + * User friendly UI created with Bootstrap + * Various database in different sections + * Admin panel created with Django + * Customizable user login system with editable user profiles + * Contact page for easier help and feedbacks +## Functional features - :handshake: + * Dashboard/Charts for visualization of the data + * Admin panel customizable and different access level + * Encryption feature in lieu of barcode system for better and safe transfer of data in the check in/out system. Also it can be used with various other features, hence improving its flexibility. Also it reduces the disadvantages in case of security of barcode systems. + * Specific ID system for employees and different items, equipped with the encryption feature + * Categories for different types of items stored. Each item has its own profile and can be viewed for more details. More categories can be added as per requirements if needed + * Record/History feature for different kinds of items + * Record keeping of users and filter feature for easy and fast searches + * Pdf download option of records to be used as hard copy. + * Navigation tutorial section for easy use. + * Only selected admins or superusers are permitted for full acccess of the inventory. Only superusers/selected admins can give users specific permissions and other customzatios from the admin panel. + * A user friendly chatbot for easy maintanence and help of the system + + # What makes our Inventory better than everyone else? :clap: + + The problem with the traditional inventory system was that they were not secured and easily maintainable. In a world of Technologies, there is need of an online system of inventory management. But still most inventory system is made using the outdated php language or languages such as React which is known for it's unstable modules sometimes. + After going through a number of articles we found out that Django will be the best language for an inventory system. The Django language is open source and maintain by a large communities and with every update it becomes more and more better. It is very much secure than the other languages and even a normal user can be quickly learn to handle the models of the websites and customize it accordingly. + + And the very next thing that makes us better than any other inventory systems is that instead of the traditional barcode system, we are now using a new cryptography based encryption system. We found out that using barcodes have now become outdated and it is very vulnerable. Any person can retrieve the information stored in a barcode and it is big concern. Even though we are just sending equiments from one place to another, we have to make everything in a secure way. + + Now an user can use our encryption system, input the data such as the quantity of items and their types, encrypt it with a key and print out the encrypted text(instead of the barcode) and send it out with the items. The user who will recieve it will now use the key given to him and decrypt the text(instead of the usual scanning of the barcode). + This way is more secure as only the person who has the key can access the information. + + The Encryption system can also be used to exchange information between different person and can be put into many different uses as required by the user. + +# Installation - +The `requirements.txt` file contains all the required libraries to be installed. + +Use `pip install -r requirements.txt` to install the required dependencies(Or pip3). + +python to be more than 3.0.0 and django –version 3.1.1. Also bootstrap 4.1,4.0 + +Extra apps needed are - + * Pillow + * WeasyPrint + * Crispy_forms + * Widget tweaks + * chart js + * gtk for windows + + Use `pip install libname` to install the apps. + + Steps after extracting the zip file - + * Go to the project folder and start the environment with conda or venv. + * Run `python manage.py collecstatic` + * Run `python manage.py makemigrations` -> `python manage.py sqlmigrate appname migration_number` -> `python manage.py migrate` + * Finally run `python manage.py runserver` to run the site on your localhost on port 8000. + * use `python manage.py createsuperuser` to create a super user and then login to the admin panel and enjoy the databases. + + ## Issues to be solved - :hourglass: + * The chatbot is still an incomplete feature. Also as this is a prototype it has few errors to be solved but it perfectly shows the features and the main aim of of the project we built. + * Since we had only one month and we have only made a prototype with a basic template, everything in the website can be improved with given time and made better. + +# Technologies used +![JavaScript](https://img.shields.io/badge/-JavaScript-black?style=flat-square&logo=javascript) +![Python](https://img.shields.io/badge/-Python-black?style=flat-square&logo=Python) +![Bootstrap](https://img.shields.io/badge/-Bootstrap-563D7C?style=flat-square&logo=bootstrap) +![ElasticSearch](https://img.shields.io/badge/-ElasticSearch-005571?style=flat-square&logo=elasticsearch) +![Git](https://img.shields.io/badge/-Git-black?style=flat-square&logo=git) +![HTML5](https://img.shields.io/badge/-HTML5-E34F26?style=flat-square&logo=html5&logoColor=white) +![CSS3](https://img.shields.io/badge/-CSS3-1572B6?style=flat-square&logo=css3) +![Heroku](https://img.shields.io/badge/-Heroku-430098?style=round&logo=heroku) +![django](https://img.shields.io/badge/-django-450098?style=round&logo=django) + + + ### Site is hosted on [Eurymedon Inventory](www.eurymedon-inventory.herokuapp.com) + **To login to the admin and view the models go to** + [admin login](eurymedon-inventory.herokuapp.com/admin) + ### login : demo + ### Password:inventory + + + # A quick Navigation and feature info + [Charts](http://eurymedon-inventory.herokuapp.com/dashboard/) - This is where you can dyanamically view charts in different ways, these are easily customizable according to the user needs. + + [Encryption](http://eurymedon-inventory.herokuapp.com/encryption/encryption/) - This is the menu for the encryption system. + + [Categories](http://eurymedon-inventory.herokuapp.com/categories) - This is menu for categories and product information page. + + [People List and Pdf](http://eurymedon-inventory.herokuapp.com/users/user-list) - This is place where you can use our filter option and also elastisearch to find a specific product or person. This page can also show you the pdf option by which you can download any record. + + [The Chatbot](http://eurymedon-inventory.herokuapp.com/thechatbot/thechatbot) - GET/POST/PUT/DELETE for Questionaires - Use for listing questionaires + + [Chat list](http://eurymedon-inventory.herokuapp.com/chat/thechatbotchat/) - GET/POST/PUT/DELETE for Chat history of User + + [Chat instance](http://eurymedon-inventory.herokuapp.com/chat/thechatbotchat/chatbot/) - Uploading json file of dialog tree + + + + diff --git a/chart.html b/chart.html new file mode 100644 index 0000000..4308a4a --- /dev/null +++ b/chart.html @@ -0,0 +1,78 @@ +{% extends 'interface/base.html'%} + +{% block title %} Item ranking {% endblock title %} + +{% block scripts %} + + + +{% endblock scripts %} + +{% block content %} + + + +
+
+

Chart.js Fun

+

Try to update the chart type and randomize the data!

+
+
+
Chart Type
+ + +
+
+ +
+
+{% endblock content %} + diff --git a/chat/admin.py b/chat/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/chat/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/chat/apps.py b/chat/apps.py new file mode 100644 index 0000000..8ebb9f0 --- /dev/null +++ b/chat/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class ChatConfig(AppConfig): + name = 'chat' diff --git a/chat/migrations/0001_initial.py b/chat/migrations/0001_initial.py new file mode 100644 index 0000000..371a936 --- /dev/null +++ b/chat/migrations/0001_initial.py @@ -0,0 +1,25 @@ +# Generated by Django 2.1.3 on 2018-12-04 07:32 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('questionaire', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Chat', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('status', models.PositiveIntegerField(default=1, null=True)), + ('log', models.TextField(default='')), + ('questionaire', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='questionaire.Questionaire')), + ], + ), + ] diff --git a/chat/models.py b/chat/models.py new file mode 100644 index 0000000..662d9be --- /dev/null +++ b/chat/models.py @@ -0,0 +1,12 @@ +from django.db import models +from questionaire.models import Questionaire + + +class Chat(models.Model): + questionaire = models.ForeignKey(Questionaire, on_delete=models.CASCADE) + status = models.PositiveIntegerField(default=1,null=True) + log = models.TextField(default='') + + def __str__(self): + return self.log + diff --git a/chat/serializers.py b/chat/serializers.py new file mode 100644 index 0000000..7350efa --- /dev/null +++ b/chat/serializers.py @@ -0,0 +1,8 @@ +from rest_framework import serializers +from .models import Chat + + +class ChatSerializer(serializers.ModelSerializer): + class Meta: + model = Chat + fields = '__all__' diff --git a/chat/tests.py b/chat/tests.py new file mode 100644 index 0000000..32fe29b --- /dev/null +++ b/chat/tests.py @@ -0,0 +1,220 @@ +from django.test import TestCase +from django.urls import reverse +from rest_framework import status +from .views import ChatTreeView,ChatbotView + + + +class ChatTreeViewTest(TestCase): + + def test_file_is_accepted(self): + + file_path = "chat/test_data/demo.json" + file_obj = open(file_path) + file_obj.seek(0) + url = reverse('chattree') + + + data = { + 'file': file_obj, + 'name': 'Food choices' + } + + response = self.client.post(url,data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + + def test_non_json_file_rejected(self): + + file_path = "chat/test_data/nonjson.js" + file_obj = open(file_path) + file_obj.seek(0) + url = reverse('chattree') + + + data = { + 'file': file_obj, + 'name': 'Food choices' + } + + response = self.client.post(url,data) + self.assertEqual(response.status_code, status.HTTP_415_UNSUPPORTED_MEDIA_TYPE) + + + def test_broken_json_rejected(self): + + file_path = "chat/test_data/demo_brokenjson.json" + file_obj = open(file_path) + file_obj.seek(0) + url = reverse('chattree') + + + data = { + 'file': file_obj, + 'name': 'Food choices' + } + + response = self.client.post(url,data) + self.assertEqual(response.status_code, status.HTTP_415_UNSUPPORTED_MEDIA_TYPE) + + + def test_db_value_insertion(self): + file_path = "chat/test_data/demo.json" + file_obj = open(file_path) + file_obj.seek(0) + url = reverse('chattree') + + data = { + 'file': file_obj, + 'name': 'Food' + } + + self.client.post(url, data) + + url = reverse('questions-list') + + import json + + file_obj.seek(0) + data = json.loads(file_obj.read()) + + count = len(data) + + response = self.client.get(url) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + + + self.assertEqual(len(response.json()),count) + + + + +class ChatbotTest(TestCase): + + def setUp(self): + file_path = "chat/test_data/demo.json" + file_obj = open(file_path) + file_obj.seek(0) + url = reverse('chattree') + + data = { + 'file': file_obj, + 'name': 'Food choices' + } + + self.client.post(url, data) + + + def test_query_completion(self): + queries = [ + "", + "Yes", + "Pizza", + "Yes", + "" + ] + + url = reverse('chatbot') + + for query in queries: + response = self.client.post(url, { + 'message': query, + 'questionaire' : 1 + }) + + + self.assertEqual(response.json(), "Restarting Conversation: Are you hungry?->Yes->Pizza->Yes") + + + def test_query_completion2(self): + queries = [ + "", + "Yes", + "Hamburger", + "" + ] + + url = reverse('chatbot') + + for query in queries: + response = self.client.post(url, { + 'message': query, + 'questionaire': 1 + }) + + + self.assertEqual(response.json(), "Restarting Conversation: Are you hungry?->Yes->Hamburger") + + + def test_query_completion_case_ignore(self): + queries = [ + "", + "no", + "" + ] + + url = reverse('chatbot') + + for query in queries: + response = self.client.post(url, { + 'message': query, + 'questionaire': 1 + }) + + + self.assertEqual(response.json(), "Restarting Conversation: Are you hungry?->no") + + + def test_query_invalid_option(self): + queries = [ + "", + "Yes", + "piza" + ] + + url = reverse('chatbot') + + for query in queries: + response = self.client.post(url, { + 'message': query, + 'questionaire': 1 + }) + + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + + def test_query_invalid_questionaire(self): + queries = [ + "", + ] + + url = reverse('chatbot') + + for query in queries: + response = self.client.post(url, { + 'message': query, + 'questionaire': 2 + }) + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + + def test_query_message_missing(self): + + + url = reverse('chatbot') + + + response = self.client.post(url, { + 'questionaire': 1 + }) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + + response = self.client.post(url, { + 'questionaire': 1 + }) + + self.assertEqual(response.json(), "Invalid input") diff --git a/chat/urls.py b/chat/urls.py new file mode 100644 index 0000000..7989364 --- /dev/null +++ b/chat/urls.py @@ -0,0 +1,14 @@ +from django.urls import path,include +from .views import ChatView,ChatTreeView,ChatbotView +from rest_framework.routers import DefaultRouter + + +router = DefaultRouter() + +router.register('chat',ChatView) + +urlpatterns = [ + path('thechatbot',include(router.urls)), + path('chattree',ChatTreeView.as_view(),name="chattree"), + path('chatbot',ChatbotView.as_view(),name="chatbot") +] diff --git a/chat/views.py b/chat/views.py new file mode 100644 index 0000000..616eab7 --- /dev/null +++ b/chat/views.py @@ -0,0 +1,144 @@ +from django.shortcuts import render +from .serializers import ChatSerializer +from .models import Chat +from rest_framework import viewsets +from rest_framework.views import APIView +from django.db import transaction +from questionaire.models import Questionaire,Questions,Responses +from rest_framework import status +from rest_framework.response import Response +from django.db.models.functions import Concat +from django.db.models import Value + + + +class ChatView(viewsets.ModelViewSet): + queryset = Chat.objects.all() + serializer_class = ChatSerializer + + + +class ChatTreeView(APIView): + + @transaction.atomic + def insertions(self, chat_nodes, questionaire_name): + try: + + with transaction.atomic(): + # Create Questionaire + questionaire = Questionaire(name=questionaire_name) + questionaire.save() + + options = [] + for node in chat_nodes: + + # Create Questions + question = Questions(question_text=node["question"], reference_id=node["id"], questionaire=questionaire) + question.save() #question id required + + for response, next in node["response"].items(): + options.append( + Responses(options=response, next=next, question=question, questionaire=questionaire)) + + # Create Responses + Responses.objects.bulk_create(options) #bulk insert all response options + + + except: + return False + + return True + + + def post(self,request): + + #data validation + if 'file' not in request.FILES or 'name' not in request.data: + return Response("Insufficient Parameters",status=status.HTTP_400_BAD_REQUEST) + + if not request.FILES['file'].name.lower().endswith('.json'): + return Response("Invalid File",status=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE) + + + import json + + file_obj = request.FILES['file'] + file_obj.seek(0) + data = file_obj.read() + + try: + data = json.loads(data) + except: + return Response("Invalid Json",status=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE) + + #inserting decoded json + if self.insertions(data,request.data["name"]): + return Response("File inserted",status=status.HTTP_201_CREATED) + + return Response("Internal Server Error",status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + + +class ChatbotView(APIView): + def post(self,request): + + if 'questionaire' not in request.data: + return Response("Insufficient Parameters",status=status.HTTP_400_BAD_REQUEST) + + try: + questionaire = Questionaire.objects.get(id=request.data["questionaire"]) + except Questionaire.DoesNotExist: + return Response("Invalid Questionaire", status=status.HTTP_400_BAD_REQUEST) + + + #If the status for last conversation is Null indicate the conversation was conpleted, else active conversation for questionaire + + try: + chat = Chat.objects.get(questionaire=questionaire,status__isnull= False) + except Chat.DoesNotExist: + chat = None + + + #A new chat + if not chat: + question = Questions.objects.get(reference_id=1,questionaire=questionaire) + + try: + Chat.objects.create(questionaire=questionaire,log=question.question_text) + except: + return Response("Internal Server Error", status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + + else: + question = Questions.objects.get(reference_id=chat.status,questionaire=questionaire) + + count = Responses.objects.filter(question=question.id, questionaire=questionaire)[:1] #check if there more stages in Conversation + + if not count: + Chat.objects.filter(id=chat.id).update(status=None) #ending conversation by setting status to null + return Response("Restarting Conversation: "+chat.log, status=status.HTTP_200_OK) + + if "message" not in request.data: + return Response("Invalid input", status=status.HTTP_400_BAD_REQUEST) + + valid_response = Responses.objects.filter(question=question.id,questionaire=questionaire,options__iexact=request.data["message"])[:1] #check if the user chose a valid option + if not valid_response: + return Response("Invalid Option", status=status.HTTP_400_BAD_REQUEST) + + try: + question = Questions.objects.get(reference_id=valid_response[0].next,questionaire=questionaire) #fetch next question for user + except Questions.DoesNotExist: + return Response("Internal Server Error", status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + + Chat.objects.filter(id=chat.id).update(status=question.reference_id,log=Concat('log', Value("->"+request.data["message"]))) #update chat state + + options = Responses.objects.values_list('options',flat=True).filter(question=question.id) #fetch option for current question + + result = { + "question" : question.question_text, + "response" : options + } + + + return Response(result,status=status.HTTP_200_OK) diff --git a/home/admin.py b/home/admin.py new file mode 100644 index 0000000..1e10798 --- /dev/null +++ b/home/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin +from home.models import AllData + +admin.site.register(AllData) diff --git a/home/apps.py b/home/apps.py new file mode 100644 index 0000000..90dc713 --- /dev/null +++ b/home/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class HomeConfig(AppConfig): + name = 'home' diff --git a/home/forms.py b/home/forms.py new file mode 100644 index 0000000..40e0508 --- /dev/null +++ b/home/forms.py @@ -0,0 +1,29 @@ +from django import forms +from .models import AllData + + +class EncryptForm(forms.Form): + decText = forms.CharField(widget=forms.Textarea(attrs={ + 'class': 'materialize-textarea', + 'id': 'textarea2', + 'rows': '5', + 'data-length': '5000', + })) + finder = forms.CharField(widget=forms.TextInput(attrs={ + 'type': 'password', + 'id': 'password', + 'class': 'validate' + })) + +class DecryptForm(forms.Form): + encText = forms.CharField(widget=forms.Textarea(attrs={ + 'class': 'materialize-textarea', + 'id': 'textarea2', + 'rows': '5', + 'data-length': '5000', + })) + finder = forms.CharField(widget=forms.TextInput(attrs={ + 'type': 'password', + 'id': 'password', + 'class': 'validate' + })) \ No newline at end of file diff --git a/home/migrations/0001_initial.py b/home/migrations/0001_initial.py new file mode 100644 index 0000000..aa63298 --- /dev/null +++ b/home/migrations/0001_initial.py @@ -0,0 +1,22 @@ +# Generated by Django 2.2.3 on 2019-07-01 18:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Data', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('decText', models.TextField(blank=True, null=True)), + ('encText', models.TextField(blank=True, null=True)), + ], + ), + ] diff --git a/home/migrations/0002_auto_20190702_0035.py b/home/migrations/0002_auto_20190702_0035.py new file mode 100644 index 0000000..76bc87f --- /dev/null +++ b/home/migrations/0002_auto_20190702_0035.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.3 on 2019-07-01 19:05 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0001_initial'), + ] + + operations = [ + migrations.RenameModel( + old_name='Data', + new_name='AllData', + ), + ] diff --git a/home/migrations/0003_alldata_finder.py b/home/migrations/0003_alldata_finder.py new file mode 100644 index 0000000..e3e0b77 --- /dev/null +++ b/home/migrations/0003_alldata_finder.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.3 on 2019-07-01 19:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0002_auto_20190702_0035'), + ] + + operations = [ + migrations.AddField( + model_name='alldata', + name='finder', + field=models.CharField(default='', max_length=50), + ), + ] diff --git a/home/migrations/0004_auto_20190702_0048.py b/home/migrations/0004_auto_20190702_0048.py new file mode 100644 index 0000000..f2e4160 --- /dev/null +++ b/home/migrations/0004_auto_20190702_0048.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.3 on 2019-07-01 19:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0003_alldata_finder'), + ] + + operations = [ + migrations.AlterField( + model_name='alldata', + name='finder', + field=models.CharField(max_length=50), + ), + ] diff --git a/home/migrations/0005_auto_20190702_0106.py b/home/migrations/0005_auto_20190702_0106.py new file mode 100644 index 0000000..921526b --- /dev/null +++ b/home/migrations/0005_auto_20190702_0106.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.3 on 2019-07-01 19:36 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0004_auto_20190702_0048'), + ] + + operations = [ + migrations.AlterField( + model_name='alldata', + name='finder', + field=models.CharField(max_length=50, unique=True), + ), + ] diff --git a/home/migrations/0006_alldata_keys.py b/home/migrations/0006_alldata_keys.py new file mode 100644 index 0000000..2c5ddaf --- /dev/null +++ b/home/migrations/0006_alldata_keys.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.2 on 2019-07-02 02:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0005_auto_20190702_0106'), + ] + + operations = [ + migrations.AddField( + model_name='alldata', + name='keys', + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/home/migrations/0007_auto_20190702_0750.py b/home/migrations/0007_auto_20190702_0750.py new file mode 100644 index 0000000..6b7fa28 --- /dev/null +++ b/home/migrations/0007_auto_20190702_0750.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.2 on 2019-07-02 02:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0006_alldata_keys'), + ] + + operations = [ + migrations.AlterField( + model_name='alldata', + name='finder', + field=models.CharField(max_length=50), + ), + ] diff --git a/home/migrations/0008_remove_alldata_dectext.py b/home/migrations/0008_remove_alldata_dectext.py new file mode 100644 index 0000000..6f23702 --- /dev/null +++ b/home/migrations/0008_remove_alldata_dectext.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.2 on 2019-07-03 06:51 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0007_auto_20190702_0750'), + ] + + operations = [ + migrations.RemoveField( + model_name='alldata', + name='decText', + ), + ] diff --git a/home/models.py b/home/models.py new file mode 100644 index 0000000..1713971 --- /dev/null +++ b/home/models.py @@ -0,0 +1,10 @@ +from django import forms +from django.db import models + +class AllData(models.Model): + finder = models.CharField(max_length=50) + encText = models.TextField(blank=True, null=True) + keys = models.TextField(blank=True, null=True) + + def __str__(self): + return self.finder diff --git a/home/tests.py b/home/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/home/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/home/urls.py b/home/urls.py new file mode 100644 index 0000000..a4cf17f --- /dev/null +++ b/home/urls.py @@ -0,0 +1,16 @@ +from django.urls import path +from .views import( + home, + encrypt, + decrypt, + encrypted, + decrypted +) + +urlpatterns = [ + path('encryption/', home, name='home'), + path('encrypt/', encrypt, name='encrypt'), + path('decrypt/', decrypt, name='decrypt'), + path('encrypted/', encrypted, name='encrypted'), + path('decrypted/', decrypted, name='decrypted'), +] diff --git a/home/views.py b/home/views.py new file mode 100644 index 0000000..0c0a07f --- /dev/null +++ b/home/views.py @@ -0,0 +1,117 @@ +from django.shortcuts import render, redirect +from django.contrib import messages +from .forms import EncryptForm, DecryptForm +from .models import AllData +import random +import string +import ast +from django.core.mail import send_mail +from django.conf import settings + + +def home(request): + return render(request, 'home.html') + +def encrypt(request): + form = EncryptForm() + if request.method == "POST": + form = EncryptForm(request.POST) + if form.is_valid(): + try: + pswdLen = len(request.POST.get("finder")) + i = 0 + d = {} + while i <= 255: + letters = string.ascii_lowercase + string.digits + code = ''.join(random.choice(letters) for i in range(pswdLen)) + d.update({i:code}) + + i += 1 + inputText = request.POST.get("decText") + text = "" + for i in inputText: + ascii_of_i = ord(i) + for key, value in d.items(): + if key == ascii_of_i: + text += value + query = AllData( + finder = request.POST.get("finder"), + keys = str(d), + encText = text + ) + query.save() + i = 0 + device_width = request.POST.get("device_width") + device_width = int(device_width) + device_width = int(device_width/11) + try: + x = text + y = "" + i = 0 + while i < len(x): + if i%device_width == 0 and i != 0: + y += x[i]+" " + i += 1 + else: + y += x[i] + i += 1 + subject = 'From EncryptionFog' + message = 'Someone used EncryptionFog' + email_from = settings.EMAIL_HOST_USER + recipient_list = ['your email..',] + try: + send_mail( subject, message, email_from, recipient_list) + except: + pass + messages.success(request, "Your text is encrypted") + return render(request, 'encrypted.html', {'result': y}) + except: + messages.success(request, 'Something went wrong try after some time.') + return redirect('/encrypt') + except: + messages.warning(request, 'Something went wrong try after some time.') + return redirect('/encrypt') + return render(request, 'encrypt.html', {'form': form}) + +def decrypt(request): + form = DecryptForm() + if request.method == "POST": + form = DecryptForm(request.POST) + if form.is_valid(): + try: + encText = str(request.POST.get("encText")) + encText = encText.replace(" ", "") + encText = encText.replace("\n", "") + q = AllData.objects.filter(finder = request.POST.get("finder"), encText=encText).first() + + d = ast.literal_eval(q.keys) + finderLen = len(request.POST.get("finder")) + encTextLen = len(encText) + + i = 0 + data = "" + while i <= encTextLen: + encText_parts = encText[i : i + finderLen] + for key,val in d.items(): + if val == encText_parts: + data += chr(key) + i += finderLen + + messages.success(request, "Your decrypted text:") + + messages.success(request, data) + + return redirect('/decrypted') + except: + messages.warning(request, 'Incorrect password or text.') + return redirect('/decrypt') + else: + messages.success(request, "Incorrect password or text") + return redirect('/decrypt') + return render(request, 'decrypt.html', {'form': form}) + +def encrypted(request): + return render(request, 'encrypted.html') + +def decrypted(request): + return render(request, 'decrypted.html') diff --git a/interface/urls.py b/interface/urls.py index 2146b2a..cd2ce3a 100644 --- a/interface/urls.py +++ b/interface/urls.py @@ -1,11 +1,14 @@ from django.urls import path from interface import views +from item.views import ItemChartView urlpatterns = [ path('', views.cover, name='cover'), path('dashboard', views.dashboard, name='dashboard'), path('categories', views.categories, name='categories'), path('check', views.check, name='check'), - path('arsenal', views.arsenal, name='arsenal') + path('arsenal', views.arsenal, name='arsenal'), + # path('', ItemChartView.as_view(), name='home'), + path('chart', ItemChartView.as_view(), name = 'chart') ] diff --git a/interface/views.py b/interface/views.py index c88dfcb..ee369aa 100644 --- a/interface/views.py +++ b/interface/views.py @@ -16,4 +16,7 @@ def check(request): def arsenal(request): - return render(request, "interface/arsenal.html") \ No newline at end of file + return render(request, "interface/arsenal.html") + +def chart(request): + return render(request,"chart.html") \ No newline at end of file diff --git a/item/admin.py b/item/admin.py new file mode 100644 index 0000000..d0026e2 --- /dev/null +++ b/item/admin.py @@ -0,0 +1,5 @@ +from django.contrib import admin +from .models import Item + +# Register your models here. +admin.site.register(Item) \ No newline at end of file diff --git a/item/apps.py b/item/apps.py new file mode 100644 index 0000000..a6a2273 --- /dev/null +++ b/item/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class ItemConfig(AppConfig): + name = 'item' diff --git a/item/migrations/0001_initial.py b/item/migrations/0001_initial.py new file mode 100644 index 0000000..1396a4c --- /dev/null +++ b/item/migrations/0001_initial.py @@ -0,0 +1,22 @@ +# Generated by Django 2.1.4 on 2020-09-19 08:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Item', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=220)), + ('quantity', models.IntegerField()), + ], + ), + ] diff --git a/item/models.py b/item/models.py new file mode 100644 index 0000000..10c66f3 --- /dev/null +++ b/item/models.py @@ -0,0 +1,10 @@ +from django.db import models + +# Create your models here. +class Item(models.Model): + name=models.CharField(max_length=220) + quantity=models.IntegerField() + + + def __str__(self): + return "{}-{}".format(self.name, self.quantity) \ No newline at end of file diff --git a/item/tests.py b/item/tests.py new file mode 100644 index 0000000..de8bdc0 --- /dev/null +++ b/item/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/item/views.py b/item/views.py new file mode 100644 index 0000000..b73dd2d --- /dev/null +++ b/item/views.py @@ -0,0 +1,11 @@ +from django.shortcuts import render +from django.views.generic import TemplateView +from .models import Item +# Create your views here. +class ItemChartView(TemplateView): + template_name='chart.html' + + def get_context_data(self, **kwargs): + context =super().get_context_data(**kwargs) + context["qs"]= Item.objects.all() + return context diff --git a/questionaire/admin.py b/questionaire/admin.py new file mode 100644 index 0000000..93e90d9 --- /dev/null +++ b/questionaire/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin +from .models import Questionaire, Questions, Responses + +# Register your models here. +admin.site.register(Questions) +admin.site.register(Questionaire) +admin.site.register(Responses) diff --git a/questionaire/apps.py b/questionaire/apps.py new file mode 100644 index 0000000..2c2ad07 --- /dev/null +++ b/questionaire/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class QuestionaireConfig(AppConfig): + name = 'questionaire' diff --git a/questionaire/migrations/0001_initial.py b/questionaire/migrations/0001_initial.py new file mode 100644 index 0000000..ae66b37 --- /dev/null +++ b/questionaire/migrations/0001_initial.py @@ -0,0 +1,45 @@ +# Generated by Django 2.1.3 on 2018-12-04 05:01 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Questionaire', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200, unique=True)), + ], + ), + migrations.CreateModel( + name='Questions', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('question_text', models.CharField(max_length=200)), + ('reference_id', models.PositiveIntegerField(null=True)), + ('questionaire', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='questionaire.Questionaire')), + ], + ), + migrations.CreateModel( + name='Responses', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('options', models.CharField(max_length=200)), + ('next', models.PositiveIntegerField(null=True)), + ('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='questionaire.Questions')), + ('questionaire', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='questionaire.Questionaire')), + ], + ), + migrations.AlterUniqueTogether( + name='questions', + unique_together={('reference_id', 'questionaire')}, + ), + ] diff --git a/questionaire/models.py b/questionaire/models.py new file mode 100644 index 0000000..bd76534 --- /dev/null +++ b/questionaire/models.py @@ -0,0 +1,29 @@ +from django.db import models + +class Questionaire(models.Model): + name = models.CharField(max_length=200,unique=True) + + def __str__(self): + return self.name + + +class Questions(models.Model): + question_text = models.CharField(max_length=200) + reference_id = models.PositiveIntegerField(null=True) + questionaire = models.ForeignKey(Questionaire, on_delete=models.CASCADE) + + class Meta: + unique_together = ('reference_id', 'questionaire',) + + def __str__(self): + return self.question_text + + +class Responses(models.Model): + options = models.CharField(max_length=200) + next = models.PositiveIntegerField(null=True) + question = models.ForeignKey(Questions, on_delete=models.CASCADE) + questionaire = models.ForeignKey(Questionaire, on_delete=models.CASCADE) + + def __str__(self): + return self.options diff --git a/questionaire/serializers.py b/questionaire/serializers.py new file mode 100644 index 0000000..131a681 --- /dev/null +++ b/questionaire/serializers.py @@ -0,0 +1,22 @@ +from rest_framework import serializers +from .models import Questionaire,Questions,Responses + + +class QuestionaireSerializer(serializers.ModelSerializer): + class Meta: + model = Questionaire + fields = '__all__' + + + +class QuestionsSerializer(serializers.ModelSerializer): + class Meta: + model = Questions + fields = '__all__' + + + +class ResponsesSerializer(serializers.ModelSerializer): + class Meta: + model = Responses + fields = '__all__' \ No newline at end of file diff --git a/questionaire/tests.py b/questionaire/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/questionaire/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/questionaire/urls.py b/questionaire/urls.py new file mode 100644 index 0000000..95eb9ee --- /dev/null +++ b/questionaire/urls.py @@ -0,0 +1,15 @@ +from django.urls import path,include +from .views import QuestionaireView,QuestionsView,ResponsesView +from rest_framework.routers import DefaultRouter + + +router = DefaultRouter() + +router.register('questionaire',QuestionaireView) +router.register('questions',QuestionsView) +router.register('responses',ResponsesView) + + +urlpatterns = [ + path('thechatbot',include(router.urls)) +] diff --git a/questionaire/views.py b/questionaire/views.py new file mode 100644 index 0000000..f896a68 --- /dev/null +++ b/questionaire/views.py @@ -0,0 +1,21 @@ +from django.shortcuts import render +from .serializers import QuestionaireSerializer,QuestionsSerializer,ResponsesSerializer +from .models import Questionaire,Questions,Responses +from rest_framework import viewsets + +class QuestionaireView(viewsets.ModelViewSet): + queryset = Questionaire.objects.all() + serializer_class = QuestionaireSerializer + + +class QuestionsView(viewsets.ModelViewSet): + queryset = Questions.objects.all() + serializer_class = QuestionsSerializer + + +class ResponsesView(viewsets.ModelViewSet): + queryset = Responses.objects.all() + serializer_class = ResponsesSerializer + + + diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..e3c5cab --- /dev/null +++ b/templates/base.html @@ -0,0 +1,54 @@ +{% load static %} + + + + + + + + + + The inventory {% block title %}{% endblock %} + + {% block extra_head %} + {% endblock %} + + + + +{% if messages %} +
+
+
+
+
+
+ {% for message in messages %} +

{{message}}

+ {% endfor %} +
+
+
+ +
+
+
+
+
+{% else %} + +
+{% endif %} + +{% block content %} +{% endblock%} +

+ + + + + \ No newline at end of file diff --git a/templates/chart.html b/templates/chart.html new file mode 100644 index 0000000..bf81d87 --- /dev/null +++ b/templates/chart.html @@ -0,0 +1,201 @@ +{% extends 'interface/base.html'%} + +{% block title %} Item ranking {% endblock title %} + +{% block scripts %} + + + +{% endblock scripts %} + +{% block content %} + + +
+
+
+
+ +
+
+
+
+
+ +
+
+ + +
+ +
+ + +
+ + +
+ +
+ +{% endblock content %} diff --git a/templates/decrypt.html b/templates/decrypt.html new file mode 100644 index 0000000..475db6c --- /dev/null +++ b/templates/decrypt.html @@ -0,0 +1,39 @@ +{% extends 'home/base.html'%} +{% block title %} + | Decrypt +{% endblock %} +{% block extra_head %} + +{% endblock %} +{% block content %} +
+
+
+ {% csrf_token %} +
+
+ + {{ form.encText }} + +
+
+
+
+ + {{ form.finder }} + +
+
+ + +
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/templates/decrypted.html b/templates/decrypted.html new file mode 100644 index 0000000..6b0d1a9 --- /dev/null +++ b/templates/decrypted.html @@ -0,0 +1,16 @@ +{% extends 'home/base.html'%} +{% block title %} + | Decrypted +{% endblock %} +{% block extra_head %} + +{% endblock %} +{% block content %} +
+
+ +
+
+{% endblock %} \ No newline at end of file diff --git a/templates/encrypt.html b/templates/encrypt.html new file mode 100644 index 0000000..e1404cd --- /dev/null +++ b/templates/encrypt.html @@ -0,0 +1,42 @@ +{% extends 'home/base.html' %} +{% block title %} + | Encrypt +{% endblock %} +{% block extra_head %} + +{% endblock %} +{% block content %} +
+
+
+ {% csrf_token %} +
+
+ + {{ form.decText }} + +
+
+
+
+ + {{ form.finder }} + +
+
+ + + +
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/templates/encrypted.html b/templates/encrypted.html new file mode 100644 index 0000000..3d5226c --- /dev/null +++ b/templates/encrypted.html @@ -0,0 +1,18 @@ +{% extends 'home/base.html' %} +{% block title %} + | Encrypted +{% endblock %} +{% block extra_head %} + +{% endblock %} +{% block content %} +
+ {% if result %} +

----------XXX----------

+

{{result}}

+

----------XXX----------

+ {% endif %} +
+{% endblock %} \ No newline at end of file diff --git a/templates/home.html b/templates/home.html new file mode 100644 index 0000000..cd1fefd --- /dev/null +++ b/templates/home.html @@ -0,0 +1,62 @@ +{% extends 'home/base.html'%} +{% block title %} + | Home +{% endblock %} +{% block extra_head %} + +{% endblock %} +{% block content %} +
+
+ + +
+ + lock + Encrypt + + + + lock_open + Decrypt + +
+ +
+{% endblock %} \ No newline at end of file diff --git a/templates/interface/base.html b/templates/interface/base.html index bc61598..f2d11af 100644 --- a/templates/interface/base.html +++ b/templates/interface/base.html @@ -2,142 +2,205 @@ - + + + + + + + + {% block title %}{% endblock title %} + + - - - - Inventory - + + + + + + + + - + + - - - - - - + + + -
-
- + + +
+ + +
+ {% block content %}{% endblock %} +
+
+ + + + + + + + + + + + -
- {% block content %}{% endblock %} -
- - - - - - - - - - diff --git a/templates/interface/more_info.html b/templates/interface/more_info.html new file mode 100644 index 0000000..3052628 --- /dev/null +++ b/templates/interface/more_info.html @@ -0,0 +1,522 @@ +{% extends "interface/base.html" %} +{% block content %} + + + + + Arsenal: Product 1 + + + + + + + + + + + + + + +
+
+
+

Product Details

+
+
+
+ + +
+
+
+
+
Variable Product
+ +
+
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

+
+ +
+ + +
+
+
+ +
+
-
+ +
+
+
+ Generate Report +
+
+
+
+
+ +
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam. +
+
+
Other Info
+

Clients

+
+
+ +
+
+ + + + + + + + + + +
+
+
+
+ + +
+
+
+
+ +
+
+
+
+ +
+
+
+ +
+
+
+
+ + +
+ + + + + + + + + + + +{% endblock %} diff --git a/templates/pswd_generation.html b/templates/pswd_generation.html new file mode 100644 index 0000000..e5c6148 --- /dev/null +++ b/templates/pswd_generation.html @@ -0,0 +1,24 @@ +{% extends 'home/base.html'%} +{% block title %} + | Password +{% endblock %} +{% block extra_head %} + +{% endblock %} +{% block content %} +
+
+ {% csrf_token %} +
+
+ + {{ form.finder }} + +
+
+ +
+
+{% endblock %} \ No newline at end of file diff --git a/templates/pswd_matching.html b/templates/pswd_matching.html new file mode 100644 index 0000000..3f5c161 --- /dev/null +++ b/templates/pswd_matching.html @@ -0,0 +1,22 @@ +{% extends 'home/base.html'%} +{% block title %} + | Password +{% endblock %} +{% block extra_head %} + +{% endblock %} +{% block content %} +
+
+
+
+ + +
+
+ +
+
+{% endblock %} \ No newline at end of file