Browse Source

init commit

Abdo Farag 6 years ago
commit
f4e522884e
56 changed files with 1378 additions and 0 deletions
  1. 8 0
      LICENSE
  2. 2 0
      README.md
  3. 11 0
      docker-back/Dockerfile
  4. 0 0
      docker-back/back/barcode/__init__.py
  5. 186 0
      docker-back/back/barcode/settings.py
  6. 42 0
      docker-back/back/barcode/urls.py
  7. 16 0
      docker-back/back/barcode/wsgi.py
  8. 0 0
      docker-back/back/frontendtexts/__init__.py
  9. 4 0
      docker-back/back/frontendtexts/admin.py
  10. 5 0
      docker-back/back/frontendtexts/apps.py
  11. 62 0
      docker-back/back/frontendtexts/migrations/0001_initial.py
  12. 0 0
      docker-back/back/frontendtexts/migrations/__init__.py
  13. 56 0
      docker-back/back/frontendtexts/models.py
  14. 8 0
      docker-back/back/frontendtexts/serializers.py
  15. 3 0
      docker-back/back/frontendtexts/tests.py
  16. 11 0
      docker-back/back/frontendtexts/urls.py
  17. 15 0
      docker-back/back/frontendtexts/views.py
  18. 0 0
      docker-back/back/language/__init__.py
  19. 7 0
      docker-back/back/language/admin.py
  20. 5 0
      docker-back/back/language/apps.py
  21. 98 0
      docker-back/back/language/migrations/0001_initial.py
  22. 20 0
      docker-back/back/language/migrations/0002_auto_20180402_0156.py
  23. 0 0
      docker-back/back/language/migrations/__init__.py
  24. 25 0
      docker-back/back/language/models.py
  25. 18 0
      docker-back/back/language/serializers.py
  26. 3 0
      docker-back/back/language/tests.py
  27. 13 0
      docker-back/back/language/urls.py
  28. 22 0
      docker-back/back/language/views.py
  29. 15 0
      docker-back/back/manage.py
  30. 0 0
      docker-back/back/myauth/__init__.py
  31. 5 0
      docker-back/back/myauth/admin.py
  32. 5 0
      docker-back/back/myauth/apps.py
  33. 30 0
      docker-back/back/myauth/migrations/0001_initial.py
  34. 0 0
      docker-back/back/myauth/migrations/__init__.py
  35. 18 0
      docker-back/back/myauth/models.py
  36. 28 0
      docker-back/back/myauth/serializers.py
  37. 3 0
      docker-back/back/myauth/tests.py
  38. 14 0
      docker-back/back/myauth/urls.py
  39. 19 0
      docker-back/back/myauth/views.py
  40. 45 0
      docker-back/back/readme.md
  41. 27 0
      docker-back/back/requirements.txt
  42. 3 0
      docker-back/back/scanapp/.gitignore
  43. 0 0
      docker-back/back/scanapp/__init__.py
  44. 15 0
      docker-back/back/scanapp/admin.py
  45. 5 0
      docker-back/back/scanapp/apps.py
  46. 23 0
      docker-back/back/scanapp/middlewares.py
  47. 117 0
      docker-back/back/scanapp/models.py
  48. 139 0
      docker-back/back/scanapp/serializers.py
  49. 3 0
      docker-back/back/scanapp/tests.py
  50. 18 0
      docker-back/back/scanapp/urls.py
  51. 26 0
      docker-back/back/scanapp/utils.py
  52. 114 0
      docker-back/back/scanapp/views.py
  53. 8 0
      docker-back/docker-entrypoint
  54. 41 0
      docker-compose.yml
  55. 13 0
      docker-front/Dockerfile
  56. 4 0
      docker-front/docker-entrypoint

+ 8 - 0
LICENSE

@@ -0,0 +1,8 @@
+MIT License
+Copyright (c) <year> <copyright holders>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 2 - 0
README.md

@@ -0,0 +1,2 @@
+# barcode
+

+ 11 - 0
docker-back/Dockerfile

@@ -0,0 +1,11 @@
+FROM python:3
+ENV PYTHONUNBUFFERED 1
+RUN mkdir /barcode-back
+WORKDIR /barcode-back
+ADD ./back/requirements.txt /barcode-back
+ADD docker-entrypoint /usr/local/bin/
+RUN chmod a+x /usr/local/bin/docker-entrypoint
+RUN pip install -r requirements.txt
+ADD ./back/ /barcode-back
+CMD ["docker-entrypoint"]
+EXPOSE 8000

+ 0 - 0
docker-back/back/barcode/__init__.py


+ 186 - 0
docker-back/back/barcode/settings.py

@@ -0,0 +1,186 @@
+"""
+Django settings for barcode project.
+
+Generated by 'django-admin startproject' using Django 2.0.3.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/2.0/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/2.0/ref/settings/
+"""
+
+import os
+
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = '-#5(dek!ea$q1^_skd^0@=m-5$mmp91y#l!h#n11g21#prk-v7'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = False
+
+ALLOWED_HOSTS = [
+    '*',
+    'app-test.trashiskey.com',
+]
+
+
+# Application definition
+
+INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'rest_framework',
+    'rest_framework.authtoken',
+    'rest_auth',
+    'scanapp',
+    'language',
+    'frontendtexts',
+    'myauth',
+    'django.contrib.sites',
+    'allauth',
+    'allauth.account',
+    'allauth.socialaccount.providers.google',
+    'rest_auth.registration',
+    'corsheaders',
+    'oauth2_provider',
+    #'social_django',
+    #'rest_framework_social_oauth2',
+]
+
+MIDDLEWARE = [
+    'django.middleware.security.SecurityMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    #'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+    'scanapp.middlewares.ActivityMiddleware',
+    'corsheaders.middleware.CorsMiddleware',
+]
+
+ROOT_URLCONF = 'barcode.urls'
+CORS_ORIGIN_ALLOW_ALL = True   
+TEMPLATES = [
+    {
+       'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        'DIRS': [],
+        'APP_DIRS': True,
+        'OPTIONS': {
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.contrib.messages.context_processors.messages',
+                #'social_django.context_processors.backends',
+                #'social_django.context_processors.login_redirect',
+            ],
+        },
+    },
+]
+SOCIAL_AUTH_STORAGE = 'scanapp.models.User'
+SOCIAL_AUTH_ADMIN_USER_SEARCH_FIELDS = ['user_id', 'social', 'token']
+LOGIN_URL = 'login'
+#LOGIN_REDIRECT_URL = 'home'
+
+WSGI_APPLICATION = 'barcode.wsgi.application'
+
+
+SITE_ID = 2
+# Database
+# https://docs.djangoproject.com/en/2.0/ref/settings/#databases
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.sqlite3',
+        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+    }
+}
+REST_FRAMEWORK = {
+    'DEFAULT_AUTHENTICATION_CLASSES': (
+        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
+        'rest_framework.authentication.TokenAuthentication',
+        'rest_framework.authentication.BasicAuthentication',
+        'django.contrib.auth.backends.ModelBackend',
+        #'scanapp.myauth.TokenAuth',
+        #'rest_framework_social_oauth2.authentication.SocialAuthentication',
+        #'oauth2_provider.contrib.rest_framework.OAuth2Authentication'
+    ),
+    'DEFAULT_PERMISSION_CLASS' : (
+        #'rest_framework.permissions.IsAuthenticated',
+    )
+}
+
+AUTHENTICATION_BACKENDS = (
+        'allauth.account.auth_backends.AuthenticationBackend',
+   #'rest_framework_social_oauth2.backends.DjangoOAuth2',
+   #'django.contrib.auth.backends.ModelBackend',
+   #'social_core.backends.google.GoogleOAuth2',
+)
+
+SOCIALACCOUNT_PROVIDERS = {
+    'google': {
+        'SCOPE': [
+            'profile',
+            'email',
+        ],
+        'AUTH_PARAMS': {
+            'access_type': 'online',
+        }
+    }
+}
+
+
+
+# Password validation
+# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    },
+]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/2.0/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_L10N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/2.0/howto/static-files/
+
+STATIC_URL = '/static/'
+# STATIC_ROOT = os.path.join(BASE_DIR,'static/')
+STATICFILES_DIRS = [
+    os.path.join(BASE_DIR,'static/')
+]

+ 42 - 0
docker-back/back/barcode/urls.py

@@ -0,0 +1,42 @@
+"""barcode URL Configuration
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+    https://docs.djangoproject.com/en/2.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.conf.urls import url, include
+from django.urls import path
+from rest_framework_jwt.views import obtain_jwt_token
+from rest_framework_jwt.views import refresh_jwt_token
+from rest_framework_jwt.views import verify_jwt_token
+from scanapp.views import download_product_picture
+
+_urlpatterns = [
+    path('admin/', admin.site.urls),
+    url(r'^accounts/', include('allauth.urls')),
+    url(r'^rest-auth/', include('rest_auth.urls')),
+    url(r'^rest-auth/registration/', include('rest_auth.registration.urls')),
+    url(r'^scanapp/', include('scanapp.urls', namespace='scanapp')),
+    url(r'^language/', include('language.urls', namespace='language')),
+    url(r'^frontend/', include('frontendtexts.urls', namespace='frontend')),
+    url(r'^myauth/', include('myauth.urls', namespace='myauth')),    
+    url(r'^auth-jwt/', obtain_jwt_token),
+    url(r'^auth-jwt-refresh/', refresh_jwt_token),
+    url(r'^auth-jwt-verify/', verify_jwt_token),
+    path(r'product_picture/<int:pk>/', download_product_picture, name='download_product_picture'),
+]
+
+
+urlpatterns = [
+    url(r'', include(_urlpatterns)),
+]

+ 16 - 0
docker-back/back/barcode/wsgi.py

@@ -0,0 +1,16 @@
+"""
+WSGI config for barcode project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "barcode.settings")
+
+application = get_wsgi_application()

+ 0 - 0
docker-back/back/frontendtexts/__init__.py


+ 4 - 0
docker-back/back/frontendtexts/admin.py

@@ -0,0 +1,4 @@
+from django.contrib import admin
+from .models import *
+# Register your models here.
+admin.site.register(FrontendText)

+ 5 - 0
docker-back/back/frontendtexts/apps.py

@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class FrontendtextsConfig(AppConfig):
+    name = 'frontendtexts'

+ 62 - 0
docker-back/back/frontendtexts/migrations/0001_initial.py

@@ -0,0 +1,62 @@
+# Generated by Django 2.0.3 on 2018-04-02 01:56
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('language', '0002_auto_20180402_0156'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='FrontendText',
+            fields=[
+                ('id', models.CharField(max_length=10, primary_key=True, serialize=False)),
+                ('page1_change', models.CharField(max_length=50)),
+                ('page1_change_detail', models.CharField(max_length=50)),
+                ('page1_scan', models.CharField(max_length=50)),
+                ('page2_scan', models.CharField(max_length=50)),
+                ('page2_logout', models.CharField(max_length=50)),
+                ('scan_scan_instruction', models.CharField(max_length=50)),
+                ('scan_scan', models.CharField(max_length=50)),
+                ('scan_not_detected', models.CharField(max_length=50)),
+                ('scan_back', models.CharField(max_length=50)),
+                ('scan_continue', models.CharField(max_length=50)),
+                ('scan_found_text', models.CharField(max_length=50)),
+                ('scan_add_new', models.CharField(max_length=50)),
+                ('scan_yes', models.CharField(max_length=50)),
+                ('scan_no', models.CharField(max_length=50)),
+                ('scan_create_new', models.CharField(max_length=50)),
+                ('scan_no_product_text', models.CharField(max_length=50)),
+                ('new_instruction', models.CharField(max_length=50)),
+                ('new_snap', models.CharField(max_length=50)),
+                ('new_done', models.CharField(max_length=50)),
+                ('save_save', models.CharField(max_length=50)),
+                ('save_save_and_continue', models.CharField(max_length=50)),
+                ('save_name', models.CharField(max_length=50)),
+                ('save_length', models.CharField(max_length=50)),
+                ('save_width', models.CharField(max_length=50)),
+                ('save_height', models.CharField(max_length=50)),
+                ('save_is_generic', models.CharField(max_length=50)),
+                ('save_weight', models.CharField(max_length=50)),
+                ('save_description', models.CharField(max_length=50)),
+                ('save_no_product_selected', models.CharField(max_length=50)),
+                ('save_change', models.CharField(max_length=50)),
+                ('save_product_type', models.CharField(max_length=50)),
+                ('save_no_packaging_selected', models.CharField(max_length=50)),
+                ('save_packaging_materials', models.CharField(max_length=50)),
+                ('page1_change_language', models.CharField(max_length=50)),
+                ('login_login', models.CharField(max_length=30)),
+                ('login_username', models.CharField(max_length=30)),
+                ('login_password', models.CharField(max_length=30)),
+                ('login_submit', models.CharField(max_length=30)),
+                ('login_login_with', models.CharField(max_length=30)),
+                ('language', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='language.Language')),
+            ],
+        ),
+    ]

+ 0 - 0
docker-back/back/frontendtexts/migrations/__init__.py


+ 56 - 0
docker-back/back/frontendtexts/models.py

@@ -0,0 +1,56 @@
+from django.db import models
+
+# Create your models here.
+class FrontendText(models.Model):
+    id = models.CharField(max_length=10, primary_key=True)
+    language = models.ForeignKey('language.Language', on_delete=models.CASCADE)
+    page1_change = models.CharField(max_length=50)
+    page1_change_detail = models.CharField(max_length=50)
+    page1_scan = models.CharField(max_length=50)
+    page2_scan = models.CharField(max_length=50)
+    page2_logout = models.CharField(max_length=50)
+    scan_scan_instruction = models.CharField(max_length=50)
+    scan_scan = models.CharField(max_length=50)
+    scan_back = models.CharField(max_length=50)
+    scan_found_text = models.CharField(max_length=50)
+    scan_not_detected = models.CharField(max_length=50)
+    scan_back = models.CharField(max_length=50)
+    scan_continue = models.CharField(max_length=50)
+    scan_add_new = models.CharField(max_length=50)
+    scan_found_text = models.CharField(max_length=50)
+    scan_add_new = models.CharField(max_length=50)
+    scan_yes = models.CharField(max_length=50)
+    scan_no = models.CharField(max_length=50)
+    scan_create_new = models.CharField(max_length=50)
+    scan_no_product_text = models.CharField(max_length=50)
+    new_instruction = models.CharField(max_length=50)
+    new_snap = models.CharField(max_length=50)
+    new_done = models.CharField(max_length=50)
+    save_product_type = models.CharField(max_length=50)
+    save_save = models.CharField(max_length=50)
+    save_save_and_continue = models.CharField(max_length=50)
+    save_name = models.CharField(max_length=50)
+    save_length = models.CharField(max_length=50)
+    save_width = models.CharField(max_length=50)
+    save_height = models.CharField(max_length=50)
+    save_is_generic = models.CharField(max_length=50)
+    save_weight = models.CharField(max_length=50)
+    save_description = models.CharField(max_length=50)
+    save_no_product_selected = models.CharField(max_length=50)
+    save_change = models.CharField(max_length=50)
+    save_product_type = models.CharField(max_length=50)
+    save_no_packaging_selected = models.CharField(max_length=50)
+    save_packaging_materials = models.CharField(max_length=50)
+
+    page1_change_language = models.CharField(max_length=50)
+    page1_change_language = models.CharField(max_length=50)
+    page1_change_language = models.CharField(max_length=50)
+    page1_change_language = models.CharField(max_length=50)
+    login_login = models.CharField(max_length=30)
+    login_username = models.CharField(max_length=30)
+    login_password = models.CharField(max_length=30)
+    login_submit = models.CharField(max_length=30)
+    login_login_with = models.CharField(max_length=30)
+
+    def getAll(language):
+        return [FrontendText.objects.get(language=language)]

+ 8 - 0
docker-back/back/frontendtexts/serializers.py

@@ -0,0 +1,8 @@
+from rest_framework import serializers
+from .models import *
+
+class FrontendTextSerializer(serializers.ModelSerializer):
+    id = serializers.ReadOnlyField()
+    class Meta:
+        model = FrontendText
+        fields = '__all__'

+ 3 - 0
docker-back/back/frontendtexts/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 11 - 0
docker-back/back/frontendtexts/urls.py

@@ -0,0 +1,11 @@
+from rest_framework import routers
+from django.conf.urls import url, include
+from .views import FrontendTextViewSet
+
+app_name = 'frontend'
+router = routers.DefaultRouter()
+router.register(r'', FrontendTextViewSet)
+
+urlpatterns = [
+    url(r'^[a-zA-Z-]+/', include(router.urls)),
+]

+ 15 - 0
docker-back/back/frontendtexts/views.py

@@ -0,0 +1,15 @@
+from django.shortcuts import render
+from rest_framework import viewsets
+from .serializers import FrontendTextSerializer
+from .models import FrontendText
+from scanapp.utils import get_language
+# Create your views here.
+
+class FrontendTextViewSet(viewsets.ModelViewSet):
+    queryset = FrontendText.objects.all()
+    serializer_class = FrontendTextSerializer
+    model_class = FrontendText
+
+    def get_queryset(self):
+        language = get_language(self.request)
+        return self.model_class.getAll(language)

+ 0 - 0
docker-back/back/language/__init__.py


+ 7 - 0
docker-back/back/language/admin.py

@@ -0,0 +1,7 @@
+from django.contrib import admin
+from .models import *
+# Register your models here.
+
+admin.site.register(WeightUnit)
+admin.site.register(LengthUnit)
+admin.site.register(Language)

+ 5 - 0
docker-back/back/language/apps.py

@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class LanguageConfig(AppConfig):
+    name = 'language'

+ 98 - 0
docker-back/back/language/migrations/0001_initial.py

@@ -0,0 +1,98 @@
+# Generated by Django 2.0.3 on 2018-04-02 01:05
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='FrontendText',
+            fields=[
+                ('id', models.CharField(max_length=10, primary_key=True, serialize=False)),
+                ('page1_change', models.CharField(max_length=50)),
+                ('page1_change_detail', models.CharField(max_length=50)),
+                ('page1_scan', models.CharField(max_length=50)),
+                ('page2_scan', models.CharField(max_length=50)),
+                ('page2_logout', models.CharField(max_length=50)),
+                ('scan_scan_instruction', models.CharField(max_length=50)),
+                ('scan_scan', models.CharField(max_length=50)),
+                ('scan_not_detected', models.CharField(max_length=50)),
+                ('scan_back', models.CharField(max_length=50)),
+                ('scan_continue', models.CharField(max_length=50)),
+                ('scan_found_text', models.CharField(max_length=50)),
+                ('scan_add_new', models.CharField(max_length=50)),
+                ('scan_yes', models.CharField(max_length=50)),
+                ('scan_no', models.CharField(max_length=50)),
+                ('scan_create_new', models.CharField(max_length=50)),
+                ('scan_no_product_text', models.CharField(max_length=50)),
+                ('new_instruction', models.CharField(max_length=50)),
+                ('new_snap', models.CharField(max_length=50)),
+                ('new_done', models.CharField(max_length=50)),
+                ('save_save', models.CharField(max_length=50)),
+                ('save_save_and_continue', models.CharField(max_length=50)),
+                ('save_name', models.CharField(max_length=50)),
+                ('save_length', models.CharField(max_length=50)),
+                ('save_width', models.CharField(max_length=50)),
+                ('save_height', models.CharField(max_length=50)),
+                ('save_is_generic', models.CharField(max_length=50)),
+                ('save_weight', models.CharField(max_length=50)),
+                ('save_description', models.CharField(max_length=50)),
+                ('save_no_product_selected', models.CharField(max_length=50)),
+                ('save_change', models.CharField(max_length=50)),
+                ('save_product_type', models.CharField(max_length=50)),
+                ('save_no_packaging_selected', models.CharField(max_length=50)),
+                ('save_packaging_materials', models.CharField(max_length=50)),
+                ('page1_change_language', models.CharField(max_length=50)),
+                ('login_login', models.CharField(max_length=30)),
+                ('login_username', models.CharField(max_length=30)),
+                ('login_password', models.CharField(max_length=30)),
+                ('login_submit', models.CharField(max_length=30)),
+                ('login_login_with', models.CharField(max_length=30)),
+            ],
+        ),
+        migrations.CreateModel(
+            name='Language',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=30)),
+            ],
+        ),
+        migrations.CreateModel(
+            name='LengthUnit',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=30)),
+                ('conversion_rate', models.FloatField()),
+            ],
+        ),
+        migrations.CreateModel(
+            name='WeightUnit',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=30)),
+                ('conversion_rate', models.FloatField()),
+            ],
+        ),
+        migrations.AddField(
+            model_name='language',
+            name='length_unit',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='language.LengthUnit'),
+        ),
+        migrations.AddField(
+            model_name='language',
+            name='weight_unit',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='language.WeightUnit'),
+        ),
+        migrations.AddField(
+            model_name='frontendtext',
+            name='language',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='language.Language'),
+        ),
+    ]

+ 20 - 0
docker-back/back/language/migrations/0002_auto_20180402_0156.py

@@ -0,0 +1,20 @@
+# Generated by Django 2.0.3 on 2018-04-02 01:56
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('language', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='frontendtext',
+            name='language',
+        ),
+        migrations.DeleteModel(
+            name='FrontendText',
+        ),
+    ]

+ 0 - 0
docker-back/back/language/migrations/__init__.py


+ 25 - 0
docker-back/back/language/models.py

@@ -0,0 +1,25 @@
+from django.db import models
+
+# Create your models here.
+class WeightUnit(models.Model):
+    name = models.CharField(max_length=30)
+    conversion_rate = models.FloatField()
+    def convert_to(self, value):
+        return self.conversion_rate * float(value)
+    def convert_from(self, value):
+        return self.conversion_rate / float(value)
+
+class LengthUnit(models.Model):
+    name = models.CharField(max_length=30)
+    conversion_rate = models.FloatField()
+    def convert_to(self, value):
+        return self.conversion_rate * float(value)
+    def convert_from(self, value):
+        return self.conversion_rate / float(value)
+
+class Language(models.Model):
+    name =  models.CharField(max_length=30)
+    weight_unit =  models.ForeignKey(WeightUnit, on_delete=models.CASCADE)
+    length_unit = models.ForeignKey(LengthUnit, on_delete=models.CASCADE)
+    def __str__(self):
+        return self.name

+ 18 - 0
docker-back/back/language/serializers.py

@@ -0,0 +1,18 @@
+from rest_framework import serializers
+from .models import *
+
+
+class LanguageSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = Language
+        fields = '__all__'
+
+class WeightUnitSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = WeightUnit
+        fields = '__all__'
+
+class LengthUnitSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = LengthUnit
+        fields = '__all__'

+ 3 - 0
docker-back/back/language/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 13 - 0
docker-back/back/language/urls.py

@@ -0,0 +1,13 @@
+from rest_framework import routers
+from django.conf.urls import url, include
+from .views import *
+
+app_name = 'language'
+router = routers.DefaultRouter()
+router.register(r'languages', LanguageViewSet)
+router.register(r'length', LengthUnitViewSet)
+router.register(r'weight', WeightUnitViewSet)
+
+urlpatterns = [
+    url(r'^[a-zA-Z-]+/', include(router.urls)),
+]

+ 22 - 0
docker-back/back/language/views.py

@@ -0,0 +1,22 @@
+from rest_framework import viewsets
+from .models import Language, WeightUnit, LengthUnit
+from .serializers import LanguageSerializer, WeightUnitSerializer, LengthUnitSerializer
+from scanapp.utils import get_language
+# Create your views here.
+
+class LanguageViewSet(viewsets.ModelViewSet):
+    queryset = Language.objects.all()
+    serializer_class = LanguageSerializer
+    model_class = Language
+    
+
+class WeightUnitViewSet(viewsets.ModelViewSet):
+    queryset = WeightUnit.objects.all()
+    serializer_class = WeightUnitSerializer
+    model_class = WeightUnit
+
+class LengthUnitViewSet(viewsets.ModelViewSet):
+    queryset = LengthUnit.objects.all()
+    serializer_class = LengthUnitSerializer
+    model_class = LengthUnit
+

+ 15 - 0
docker-back/back/manage.py

@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+import os
+import sys
+
+if __name__ == "__main__":
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "barcode.settings")
+    try:
+        from django.core.management import execute_from_command_line
+    except ImportError as exc:
+        raise ImportError(
+            "Couldn't import Django. Are you sure it's installed and "
+            "available on your PYTHONPATH environment variable? Did you "
+            "forget to activate a virtual environment?"
+        ) from exc
+    execute_from_command_line(sys.argv)

+ 0 - 0
docker-back/back/myauth/__init__.py


+ 5 - 0
docker-back/back/myauth/admin.py

@@ -0,0 +1,5 @@
+from django.contrib import admin
+from .models import *
+from allauth.models import *
+# Register your models here.
+admin.site.register(OAuth)

+ 5 - 0
docker-back/back/myauth/apps.py

@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class MyauthConfig(AppConfig):
+    name = 'myauth'

+ 30 - 0
docker-back/back/myauth/migrations/0001_initial.py

@@ -0,0 +1,30 @@
+# Generated by Django 2.0.3 on 2018-04-02 02:29
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='OAuth',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=30)),
+                ('clientId', models.CharField(max_length=100)),
+                ('clientSecret', models.CharField(max_length=30)),
+                ('accessTokenUri', models.CharField(max_length=50)),
+                ('authorizationUri', models.CharField(max_length=50)),
+                ('redirectUri', models.CharField(max_length=50)),
+                ('state', models.CharField(max_length=50)),
+                ('scopes', models.CharField(max_length=50)),
+                ('responseType', models.CharField(max_length=50)),
+                ('loginPath', models.CharField(max_length=50)),
+            ],
+        ),
+    ]

+ 0 - 0
docker-back/back/myauth/migrations/__init__.py


+ 18 - 0
docker-back/back/myauth/models.py

@@ -0,0 +1,18 @@
+from django.db import models
+
+# Create your models here.
+
+class OAuth(models.Model):
+    name = models.CharField(max_length=30)
+    clientId = models.CharField(max_length=100)
+    clientSecret = models.CharField(max_length=30)
+    accessTokenUri = models.CharField(max_length=50)
+    authorizationUri = models.CharField(max_length=50)
+    redirectUri = models.CharField(max_length=50)
+    state = models.CharField(max_length=50)
+    scopes = models.CharField(max_length=50)
+    responseType = models.CharField(max_length=50)
+    loginPath = models.CharField(max_length=50)
+
+    def __str__(self):
+        return self.name

+ 28 - 0
docker-back/back/myauth/serializers.py

@@ -0,0 +1,28 @@
+from rest_framework import serializers
+from .models import OAuth
+
+
+class OAuthSerializer(serializers.ModelSerializer):
+    scopes = serializers.SerializerMethodField()
+    loginPath = serializers.SerializerMethodField()
+    auth_data = serializers.SerializerMethodField()
+    class Meta:
+        model = OAuth
+        fields = '__all__'
+    def get_scopes(self, obj):
+        return obj.scopes.split(',')
+    def get_auth_data(self, obj):
+        a = {
+            'clientId': obj.clientId,
+            'clientSecret': obj.clientSecret,
+            'accessTokenUri': obj.accessTokenUri,
+            'state': obj.state,
+            'authorizationUri': obj.authorizationUri,
+            'redirectUri': obj.redirectUri,
+            'scopes': self.get_scopes(obj),
+            'responseType': obj.responseType
+        }
+        return a
+    def get_loginPath(self, obj):
+        return reverse(obj.loginPath)
+

+ 3 - 0
docker-back/back/myauth/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 14 - 0
docker-back/back/myauth/urls.py

@@ -0,0 +1,14 @@
+from rest_framework import routers
+from django.conf.urls import url, include
+from django.urls import path
+from .views import *
+
+
+app_name = 'myauth'
+router = routers.DefaultRouter()
+router.register(r'providers', OAuthViewSet)
+
+urlpatterns = [
+    url(r'', include(router.urls)),
+    path(r'provider/google', GoogleLogin.as_view()),
+]

+ 19 - 0
docker-back/back/myauth/views.py

@@ -0,0 +1,19 @@
+from django.shortcuts import render
+from rest_framework import viewsets
+from django.utils.decorators import method_decorator
+from django.views.decorators.csrf import csrf_exempt
+from .models import OAuth
+from .serializers import OAuthSerializer
+# Create your views here.
+
+from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter
+from rest_auth.registration.views import SocialLoginView
+@method_decorator(csrf_exempt, name='dispatch')
+class GoogleLogin(SocialLoginView):
+    adapter_class = GoogleOAuth2Adapter
+
+class OAuthViewSet(viewsets.ModelViewSet):
+    queryset = OAuth.objects.all()
+    serializer_class = OAuthSerializer
+    model_class = OAuth
+    

+ 45 - 0
docker-back/back/readme.md

@@ -0,0 +1,45 @@
+## BARCODE SCANNER BACKEND
+It contains the following 
+* MyAuth
+* Scanapp
+* Language
+* Frontends
+
+### Installation
+`Run pip -r requirements.txt`
+`Run python manage.py makemigrations`
+`Run python manage.py migrate`
+
+Then create a superuser account using
+`python manage.py createsuperuser`
+
+Then start the app using
+`python manage.py runserver`
+
+### Language App
+It contains list of supported languages, weight unit and length unit
+At least a record of language model must be created before the app can be used.
+
+To create a new record go to
+`host/api/admin/language`
+
+#### FrontendText App
+It contains all the list of texts at the frontend.
+Atlease a record of it is needed before the frontend can work
+
+To create a new record go to
+`host/api/admin/FrontendText`
+
+### Scanapp App
+It contains the following endpoints all of which require authorization.
+
+* product_types
+* ean_codes
+* products
+* product_pictures
+* product_hier
+* bom
+
+All endpoints are located at host/api/scanapp/{LANG}/{endpoint}/ where 
+* {LANG} is the name of the requested language
+* {endpoint} is the endpoint as written above

+ 27 - 0
docker-back/back/requirements.txt

@@ -0,0 +1,27 @@
+certifi==2018.1.18
+chardet==3.0.4
+defusedxml==0.5.0
+Django==2.0.3
+django-allauth==0.35.0
+django-cors==0.1
+django-cors-headers==2.2.0
+django-hashers-passlib==0.4
+django-oauth-toolkit==1.0.0
+django-rest-auth==0.9.3
+django-rest-framework==0.1.0
+djangorestframework==3.7.7
+djangorestframework-jwt==1.11.0
+idna==2.6
+oauthlib==2.0.7
+passlib==1.7.1
+PyJWT==1.6.1
+python-mimeparse==1.6.0
+python3-openid==3.1.0
+pytz==2018.3
+requests==2.18.4
+requests-oauthlib==0.8.0
+RestAuthCommon==0.7.0
+six==1.11.0
+South==1.0.2
+urllib3==1.22
+gunicorn==19.7.1

+ 3 - 0
docker-back/back/scanapp/.gitignore

@@ -0,0 +1,3 @@
+__pycache__/
+migrations/
+*.ipynb

+ 0 - 0
docker-back/back/scanapp/__init__.py


+ 15 - 0
docker-back/back/scanapp/admin.py

@@ -0,0 +1,15 @@
+from django.contrib import admin
+from scanapp.models import *
+# Register your models here.
+admin.site.register(User)
+admin.site.register(Product)
+admin.site.register(ProductType)
+admin.site.register(ProductTypeTranslation)
+admin.site.register(ProductTypeHier)
+admin.site.register(EAN_Code)
+admin.site.register(BOM)
+admin.site.register(ProductPicture)
+admin.site.register(UserActivity)
+
+
+

+ 5 - 0
docker-back/back/scanapp/apps.py

@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class ScanappConfig(AppConfig):
+    name = 'scanapp'

+ 23 - 0
docker-back/back/scanapp/middlewares.py

@@ -0,0 +1,23 @@
+from scanapp.models import User, UserActivity
+
+class ActivityMiddleware:
+    # This middleware run on all scanapp endpoint and record acivities on UserActivity Table
+    def __init__(self, get_response):
+        self.get_response = get_response
+
+    def __call__(self, request):
+        response = self.get_response(request)
+        print(request.path)
+        if request.path.split('/')[0] == 'admin':
+            return response
+        if not 'scanapp' in request.path:
+            return response 
+        try:
+            activity = UserActivity()
+            user = User.getUser(request.user)
+            activity.user = user 
+            activity.activity = request.path
+            activity.save()
+            return response
+        except Exception as e:
+            return response

+ 117 - 0
docker-back/back/scanapp/models.py

@@ -0,0 +1,117 @@
+from django.db import models
+from django.contrib.auth.models import User as NormalUser
+import secrets
+# Create your models here.
+# from model import *
+
+
+class User(models.Model):
+    user_id = models.CharField(max_length=30, unique=True)
+    _social = models.CharField(max_length=30, default="none")
+    created_at = models.DateTimeField(auto_now_add=True)
+    updated_at = models.DateTimeField(auto_now=True)
+    def getUser(user_model):
+        user = None
+        if isinstance(user_model, NormalUser):
+            try:
+                object = User.objects.get(user_id = 'normal_'+ user_model.username)
+                return object
+            except Exception as e:
+                user = User()
+                user.user_id = 'normal_' + user_model.username
+                user.social = 'normal'
+                user.save()
+                return user
+        return user
+    def __str__(self):
+        return self.user_id
+
+class UserActivity(models.Model):
+    user = models.ForeignKey(User, on_delete=models.CASCADE)
+    activity = models.CharField(max_length=30)
+    created_at = models.DateTimeField(auto_now_add=True)
+
+    def __str__(self):
+        return "{0}:{1}".format(self.user, self.created_at)
+    
+class ProductType(models.Model):
+    is_packaging_material = models.BooleanField(default=False)
+    icon = models.CharField(max_length=30)
+    deleted = models.BooleanField(default=False)
+    name = models.CharField(max_length=30)
+    def getAll(language):
+        objects = ProductType.objects.all()
+        [object.get_with_locale(language) for object in objects]
+        return objects
+
+    def get_with_locale(self, language):
+        try:
+            self.title = ProductTypeTranslation.objects.get(word_id=self.id, language=language.id ).translation
+        except:
+            self.title = ProductTypeTranslation.objects.get(word_id=self.id, language=1 ).translation
+        return self
+
+    def __str__(self):
+        return self.name
+class ProductTypeTranslation(models.Model):
+    word_id = models.ForeignKey(ProductType, on_delete=models.CASCADE)
+    language = models.ForeignKey('language.Language', on_delete=models.CASCADE)
+    translation = models.CharField(max_length=40)
+
+    def __str__(self):
+        return str(self.word_id) + '-' + str(self.language)
+
+class EAN_Code(models.Model):
+    #product_type = models.ForeignKey(ProductType, on_delete=models.CASCADE)
+    user = models.ForeignKey(User, on_delete=models.CASCADE)
+    deleted = models.BooleanField(default=False)
+    barcode = models.CharField(max_length=50)
+
+class Product(models.Model):
+    name = models.CharField(max_length=30)
+    packaging_material = models.ForeignKey(ProductType, related_name='materials', on_delete=models.CASCADE)
+    EAN_code = models.ForeignKey(EAN_Code, related_name='products', on_delete=models.CASCADE)
+    weight = models.CharField(max_length=20)
+    length = models.FloatField()
+    width = models.FloatField()
+    height = models.FloatField()
+    is_generic = models.BooleanField()
+    deleted = models.BooleanField(default=False)
+    user = models.ForeignKey(User, on_delete=models.CASCADE)
+    created_at = models.DateTimeField(auto_now_add=True)
+    updated_at = models.DateTimeField(auto_now=True)
+    product_type = models.ForeignKey('scanapp.ProductType', on_delete=models.CASCADE)
+
+    def __str__(self):
+        return self.name
+
+class ProductPicture(models.Model):
+    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='pictures')
+    name = models.CharField(max_length=30)
+    image = models.FileField(upload_to='image/')
+    user = models.ForeignKey(User, on_delete=models.CASCADE)
+    created_at = models.DateTimeField(auto_now_add=True)
+    updated_at = models.DateTimeField(auto_now=True)
+
+    def get_url(self):
+        return '/' + self.image.url
+    
+    def __str__(self):
+        return str(self.product) + "_picture"
+
+class ProductTypeHier(models.Model):
+    parent = models.ForeignKey(ProductType, on_delete=models.CASCADE, related_name='parent')
+    child = models.ForeignKey(ProductType, on_delete=models.CASCADE)
+    def __str__(self):
+        return str(self.parent) + '  -  ' + str(self.child)
+
+class BOM(models.Model):
+    product = models.ForeignKey(Product, on_delete=models.CASCADE)
+    product_type = models.ForeignKey(ProductType, on_delete=models.CASCADE)
+    weight = models.CharField(max_length=30)
+    user = models.ForeignKey(User, on_delete=models.CASCADE)
+    created_at = models.DateTimeField(auto_now_add=True)
+    updated_at = models.DateTimeField(auto_now=True) 
+
+    def __str__(self):
+        return str(self.product) + '-bom'

+ 139 - 0
docker-back/back/scanapp/serializers.py

@@ -0,0 +1,139 @@
+from scanapp.models import *
+from scanapp.utils import get_language
+from rest_framework import serializers
+from django.urls import reverse
+
+
+
+class UserSerializer(serializers.ModelSerializer):
+    _token = serializers.ReadOnlyField()
+    password = serializers.CharField(write_only=True)
+    class Meta:
+        model = User
+        fields = ('user_id', '_token', 'password')
+
+class UserActivitySerializer(serializers.ModelSerializer):
+    class Meta:
+        model = UserActivity
+        fields = ('id', 'user_id', 'activity')
+
+class ProductTypeSerializer(serializers.ModelSerializer):
+    title = serializers.ReadOnlyField()
+    class Meta:
+        model = ProductType
+        fields = ('id','is_packaging_material', 'title', 'name', 'deleted', 'product_set')
+    def get_url(self, obj):
+        request = self.context['request']
+        return reverse('download-image', kwargs={'image_id': obj.id, image_folder: 'product_type_icon'}, request=request)
+class ProductPictureSerializer(serializers.ModelSerializer):
+    url = serializers.SerializerMethodField()
+    image = serializers.FileField(write_only=True)
+    class Meta:
+        model = ProductPicture
+        fields = ('id', 'url', 'name', 'image', 'product')
+    
+    def get_url(self, obj):
+        request = self.context['request']
+        return reverse('download_product_picture', kwargs={'pk': obj.id}) 
+class ProductPictureLinkField(serializers.ModelSerializer):
+    url = serializers.SerializerMethodField()
+
+    class Meta:
+        model = ProductPicture
+        fields = ('url',)
+    
+    def to_representation(self, value):
+        return self.get_url(value)
+    
+    def get_url(self, obj):
+        request = self.context['request']
+        return reverse('download_product_picture', kwargs={'pk': obj.id}) 
+
+class ProductWriteSerializer(serializers.ModelSerializer):
+    
+    class Meta:
+        model = Product
+        fields = '__all__'
+        write_only_fields = ('weight',)
+        read_only_fields = ('user',)
+
+    def to_internal_value(self, data):
+        
+        return super(ProductWriteSerializer, self).to_internal_value(data)
+
+class ProductSerializer(serializers.ModelSerializer):
+    user = serializers.PrimaryKeyRelatedField(read_only=True)
+    weight = serializers.SerializerMethodField()
+    length = serializers.SerializerMethodField()
+    width = serializers.SerializerMethodField()
+    height = serializers.SerializerMethodField()
+    icon_link = serializers.SerializerMethodField()
+    pictures = ProductPictureLinkField(many=True, read_only=True)
+    class Meta:
+        model = Product
+        fields = '__all__'
+        write_only_fields = ('weight',)
+        read_only_fields = ('icon_link',)
+    def get_weight(self, obj):
+        language = get_language(self.context['request'])
+        return str(language.weight_unit.convert_to(obj.weight)) + language.weight_unit.name
+    def get_length(self, obj):
+        language = get_language(self.context['request'])
+        return str(language.length_unit.convert_to(obj.length)) + language.length_unit.name
+    def get_width(self, obj):
+        language = get_language(self.context['request'])
+        return str(language.length_unit.convert_to(obj.width)) + language.length_unit.name
+    def get_height(self, obj):
+        language = get_language(self.context['request'])
+        return str(language.length_unit.convert_to(obj.height)) + language.length_unit.name
+    def get_icon_link(self, obj):
+        icon = None
+        try:
+            icon = obj.pictures.all()[0]
+        except:
+            icon = ProductPicture.objects.get(pk=1)
+        return reverse('download_product_picture', kwargs={'pk': icon.id})
+
+class EAN_CodeSerializer(serializers.ModelSerializer):
+    user = serializers.PrimaryKeyRelatedField(read_only=True)
+    products = ProductSerializer(many=True, read_only=True)
+    class Meta:
+        model = EAN_Code
+        fields = ('id', 'user', 'barcode', 'deleted', 'products')
+
+
+class ProductTypeHierSerializer(serializers.ModelSerializer):
+
+    class Meta:
+        model = ProductTypeHier
+        fields = '__all__'
+
+class BOMSerializer(serializers.ModelSerializer):
+    user = serializers.PrimaryKeyRelatedField(read_only=True)
+    class Meta:
+        model = BOM
+        fields = ('product', 'product_type', 'weight')
+
+class ProductTypeHierMainSerializer(serializers.ModelSerializer):
+    children = serializers.SerializerMethodField(read_only=True)
+    name = serializers.SerializerMethodField(read_only=True)
+    label = serializers.SerializerMethodField()
+    title = serializers.ReadOnlyField()
+    
+    class Meta:
+        model = ProductType
+        fields = ('children','name', 'title', 'label', 'id')
+
+    def get_label(self, obj):
+        language = get_language(self.context['request'])
+        return obj.get_with_locale(language).title
+        
+
+    def get_name(self, obj):
+        return obj.name
+    def get_children(self, obj):
+        product_type_hiers = ProductTypeHier.objects.filter(parent=obj)
+        product_children = []
+        [product_children.append(temp.child) for temp in product_type_hiers]
+        product_types = ProductTypeHierMainSerializer(product_children, many=True, context=self.context)
+        return product_types.data

+ 3 - 0
docker-back/back/scanapp/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 18 - 0
docker-back/back/scanapp/urls.py

@@ -0,0 +1,18 @@
+from django.conf.urls import url, include
+from rest_framework import routers
+from scanapp.views import *
+from django.urls import path
+
+app_name = 'scanapp'
+router = routers.DefaultRouter()
+router.register(r'product_types', ProductTypeViewSet)
+router.register(r'ean_codes', EAN_CodeViewSet)
+router.register(r'products', ProductViewSet)
+router.register(r'product_pictures', ProductPictureViewSet)
+router.register(r'product_hier', ProductTypeHierMainViewSet)
+router.register(r'bom', BOMViewSet)
+urlpatterns = [
+    url(r'^[a-zA-Z-]+/', include(router.urls)),
+    path(r'<slug:language>/product_type_children/<int:pk>/', get_product_types),
+    path(r'<slug:language>/units/', get_units),
+]

+ 26 - 0
docker-back/back/scanapp/utils.py

@@ -0,0 +1,26 @@
+from language.models import Language, WeightUnit, LengthUnit
+
+def get_language(request):
+    '''
+     return language by path or return default language
+     if the language specified in 
+     the request does not exist
+    '''
+    path = request.path
+    lang = path.split('/')[2]
+    try:
+        return Language.objects.get(name=lang.upper())
+    except:
+        return Language.objects.get(pk=1)
+    
+
+def get_weight_unit(data):
+    try:
+        return WeightUnit.objects.get(name=data)
+    except:
+        return WeightUnit.objects.get(pk=1)
+def get_length_unit(data):
+    try:
+        return LengthUnit.objects.get(name=data)
+    except:
+        return LengthUnit.objects.get(pk=1)

+ 114 - 0
docker-back/back/scanapp/views.py

@@ -0,0 +1,114 @@
+import json
+from django.views.decorators.csrf import csrf_exempt
+from django.shortcuts import render
+from django.http import HttpResponse
+from django.utils.decorators import method_decorator
+from scanapp.serializers import *
+from rest_framework import viewsets, status
+from rest_framework.decorators import api_view
+from rest_framework.response import Response
+from rest_framework.permissions import IsAuthenticated, AllowAny
+# Create your views here.
+
+@api_view(['GET'])
+def get_units(request, language):
+    units = {
+        'weight': [
+            {'label': 'kg', 'value': 'kg'},
+            {'label': 'lb', 'value': 'lb'}
+        ],
+        'length': [
+            {'label': 'm', 'value': 'm'},
+            {'label': 'in', 'value': 'in'}        ]
+    }
+    return Response(units)
+
+@api_view(['GET'])
+def get_product_types(request, pk, language):
+    product_type = ProductType.objects.get(pk=pk)
+    #print(product_type)
+    product_type_hiers = ProductTypeHier.objects.filter(parent=product_type)
+    product_children = []
+    [product_children.append(temp.child) for temp in product_type_hiers]
+    product_types = ProductTypeSerializer(product_children, many=True)
+    response = Response(product_types.data)
+    return response
+
+def download_product_picture(request, pk):
+    image = ProductPicture.objects.get(pk=pk)
+    response = HttpResponse()
+    #print(image)
+    response['X-Accel-Redirect'] =  image.get_url()
+    response['Content-Disposition'] = 'attachment; filename="{}"'.format(image.name)
+    return response
+
+class MyViewSet(viewsets.ModelViewSet):
+    model_class = None
+    permission_classes = (IsAuthenticated,)
+    def list(self, request):
+        return super(viewsets.ModelViewSet, self).list(request)
+class TranslationViewSet(object):
+    """docstring for TranslationViewSet"""
+        
+    def get_queryset(self):
+        language = get_language(self.request)
+        return self.model_class.getAll(language)
+
+    def get_object(self):
+        object = super(viewsets.ModelViewSet, self).get_object()
+        language = get_language(self.request)
+        return object.get_with_locale(language)
+
+class AutoSetUser(object):
+    def perform_create(self, serializer):
+        serializer.save(user=User.getUser(self.request.user))
+
+def create_viewset(base, name, queryset, serializer_class, model_class):
+    return type(name, (base,), {'queryset': queryset,
+                'serializer_class': serializer_class, 'model_class':model_class})
+
+class ProductTypeViewSet(AutoSetUser, TranslationViewSet, MyViewSet):
+    queryset = ProductType.objects.all()
+    serializer_class = ProductTypeSerializer
+    model_class = ProductType
+
+class EAN_CodeViewSet(AutoSetUser, MyViewSet):
+    queryset = EAN_Code.objects.all()
+    serializer_class = EAN_CodeSerializer
+    model_class = EAN_Code
+    lookup_field = 'barcode'
+
+
+class ProductViewSet(AutoSetUser, MyViewSet):
+    queryset = Product.objects.all()
+    write_serializer_class = ProductWriteSerializer
+    read_serializer_class = ProductSerializer
+    model_class = Product
+
+    def get_serializer(self, *args, **kwargs):
+        if(self.request.method == 'PUT' or self.request.method == 'PATCH' or self.request.method == 'POST'):
+            self.serializer_class = self.write_serializer_class
+        else:
+            self.serializer_class = self.read_serializer_class
+        return super(MyViewSet, self).get_serializer(*args, **kwargs)
+
+class ProductPictureViewSet(AutoSetUser, MyViewSet):
+    queryset = ProductPicture.objects.all()
+    serializer_class = ProductPictureSerializer
+    model_class = ProductPicture
+
+class ProductTypeHierViewSet(AutoSetUser, MyViewSet):
+    queryset = ProductTypeHier.objects.all()
+    serializer_class = ProductTypeHierSerializer
+    model_class = ProductTypeHier
+
+class ProductTypeHierMainViewSet(AutoSetUser, MyViewSet):
+    queryset = ProductType.objects.all()
+    serializer_class = ProductTypeHierMainSerializer
+    model_class = ProductType
+
+class BOMViewSet(AutoSetUser, MyViewSet):
+    queryset = BOM.objects.all()
+    serializer_class = BOMSerializer
+    model_class = BOM
+

+ 8 - 0
docker-back/docker-entrypoint

@@ -0,0 +1,8 @@
+#!/bin/sh
+set -e
+python manage.py makemigrations
+python manage.py makemigrations scanapp
+python manage.py migrate
+python manage.py runserver 0.0.0.0:8000
+
+exec "$@"

+ 41 - 0
docker-compose.yml

@@ -0,0 +1,41 @@
+version: "2"
+services:
+
+  django:
+    restart: always
+    build: docker-back/ 
+    image: barcode-back
+    container_name: "barcode-back"
+    expose:
+      - "8000"
+    volumes:
+      - /opt/barcode-back:/barcode-back:rw
+    environment:
+      DEBUG: 'true'
+
+  nodejs:
+    restart: always
+    build: docker-front/
+    image: barcode-front
+    container_name: "barcode-front"
+    expose:
+      - "8080"
+    #volumes:
+    #  - /opt/barcode-front:/opt/barcode-front:rw
+
+  nginx:
+    restart: always
+    image: nginx:latest
+    container_name: "barcode-nginx"
+    ports:
+      - "80:80"
+      - "443:443"
+    volumes:
+      - /opt/nginx/conf.d:/etc/nginx/conf.d:rw
+      - /opt/logs/nginx/:/var/log/nginx:rw
+      - /etc/letsencrypt:/etc/letsencrypt:rw
+      - /etc/letsencrypt/dhparam.pem:/etc/nginx/certs/dhparam.pem:ro
+    links:
+      - nodejs:nodejs
+      - django:django
+

+ 13 - 0
docker-front/Dockerfile

@@ -0,0 +1,13 @@
+FROM node:8
+
+RUN mkdir -p /barcode-front
+WORKDIR /barcode-front
+ADD ./front/ /barcode-front
+RUN npm install -g vue-cli
+RUN npm install -g quasar-cli
+RUN npm install
+ADD docker-entrypoint /usr/local/bin/
+RUN chmod a+x /usr/local/bin/docker-entrypoint
+EXPOSE 8080
+CMD ["docker-entrypoint"]
+

+ 4 - 0
docker-front/docker-entrypoint

@@ -0,0 +1,4 @@
+#!/bin/sh
+set -e
+quasar dev
+exec "$@"