Commit 98a2d956 authored by John Red Medrano's avatar John Red Medrano

intro version 2

parent ba610cc3
File added
from django.apps import AppConfig
class AccesslayerConfig(AppConfig):
name = 'accesslayer'
from app.middleware.current_user.data import set_current_user
from rest_framework.authentication import TokenAuthentication
from rest_framework import exceptions
from datetime import datetime, timedelta
from django.conf import settings
class AppTokenAuthentication(TokenAuthentication):
keyword = 'Bearer'
def authenticate_credentials(self, key):
user, token = super(AppTokenAuthentication,
self).authenticate_credentials(key)
if token.created < datetime.now() - timedelta(minutes=int(settings.SESSION_TIMEOUT)):
token.delete()
raise exceptions.AuthenticationFailed('Token has expired')
else:
token.created = datetime.now()
token.save()
set_current_user(user)
return (user, token)
from django.urls import path, re_path
from app.accesslayer import views
urlpatterns = (
path(r'login/', views.Login.as_view(), name="API Login"),
re_path(r'^logout/', views.Logout.as_view(), name="API Logout"),
re_path(r'^refresh-token/(?P<token>\w+)/$', views.RefreshToken.as_view(), name="Refresh Token"),
path(r'current-user/', views.CurrentUser.as_view(), name="Current User"),
re_path(r'^forgot-password/(?P<username>\w+)/$', views.ForgotPassword.as_view(), name="Forgot Password"),
re_path(r'^validate-forgot-password-reset-token/(?P<token>\w+)/$', views.ValidateForgotPasswordResetToken.as_view(), name="Validate Forgot Password Reset Token"),
re_path(r'^forgot-password-reset/(?P<token>\w+)/$', views.ForgotPasswordReset.as_view(), name="Forgot Password Reset"),
)
import json
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import AllowAny
from django.db import transaction
from app.helper import decorators
from app.applicationlayer.management.user.serializers import (
UserManagementRetreiveSerializer
)
from app.entities.models import User, AuthToken
from datetime import datetime
from random import randrange
from django.conf import settings
from app.helper.email_service import sender
class Login(ObtainAuthToken):
@decorators.error_safe
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data,
context={'request': request})
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
token, created = Token.objects.get_or_create(user=user)
if not created:
token.created = datetime.now()
token.save()
return Response({
'token': token.key,
# 'user_id': user.pk,
# 'email': user.email
})
class Logout(APIView):
@decorators.error_safe
def post(self, request, *args, **kwargs):
existingUser = self.request.user
if existingUser:
existingToken = Token.objects.filter(user=existingUser).first()
if existingToken:
existingToken.delete()
return Response(data={"detail": "User was logged out"},
status=status.HTTP_200_OK)
else:
return Response(data={"detail": "User session not found"},
status=status.HTTP_404_NOT_FOUND)
else:
return Response(data={"detail": "User not found"},
status=status.HTTP_404_NOT_FOUND)
class RefreshToken(APIView):
@decorators.error_safe
def post(self, request, token=None, *args, **kwargs):
existingToken = Token.objects.filter(key=token).first()
if existingToken:
if existingToken.user == request.user:
existingToken.created = datetime.now()
existingToken.save()
return Response(data={"detail": "Token refreshed"},
status=status.HTTP_200_OK)
else:
return Response(data={"detail": "Token user not match"},
status=status.HTTP_401_UNAUTHORIZED)
else:
return Response(data={"detail": "Token not found"},
status=status.HTTP_404_NOT_FOUND)
class CurrentUser(APIView):
@decorators.error_safe
def get(self, request, token=None, *args, **kwargs):
serializer = UserManagementRetreiveSerializer
context = {"request": request}
serializer = serializer(request.user, context=context)
serializer.data['key'] = 'value'
print(request.user)
serialized = serializer.data
return Response(data=serialized,
status=status.HTTP_200_OK)
'''
***********************
** RESET CREDENTIALS **
***********************
'''
class ForgotPassword(APIView):
permission_classes = (AllowAny,)
@decorators.error_safe
@transaction.atomic
def post(self, request, username=None, *args, **kwargs):
existingUser = User.objects.filter(username=username).first()
if existingUser:
# Check if there's existing request
exToken = AuthToken\
.objects\
.filter(
user_id=existingUser.id,
is_active=True)\
.first()
if exToken:
raise Exception(
'There is an existing password reset for this user.')
REF = 'AUTH'
TOKEN = ''
TIMEOUT = 10000
PASSCODE = 0
# Generate Random token for TOKEN
TOKEN = Token().generate_key()
# Generate Random number for PASSCODE
rands = []
rands.append(randrange(10))
rands.append(randrange(10))
rands.append(randrange(10))
rands.append(randrange(10))
PASSCODE = f"{rands[0]}{rands[1]}{rands[2]}{rands[3]}"
AuthToken(
ref=REF,
token=TOKEN,
passcode=PASSCODE,
timeout=TIMEOUT,
is_active=True,
user=existingUser,
).save()
url = f"{settings.FRONT_END_URL}/account/forgot-password-reset"\
f"?token={TOKEN}"
sender.forgot_password(
str(PASSCODE),
str(url),
str(existingUser.email))
return Response(data={"detail": "Forgot Password Sent"},
status=status.HTTP_200_OK)
else:
return Response(data={"error": "User not found"},
status=status.HTTP_404_NOT_FOUND)
class ValidateForgotPasswordResetToken(APIView):
permission_classes = (AllowAny,)
@decorators.error_safe
@transaction.atomic
def post(self, request, token=None, *args, **kwargs):
existingToken = AuthToken.objects.filter(token=token).first()
if existingToken:
if not existingToken.is_active:
raise Exception('Request is no longer active')
return Response(data={
"username": existingToken.user.username,
"email": existingToken.user.email
},
status=status.HTTP_200_OK)
else:
return Response(data={"error": "Token not found"},
status=status.HTTP_404_NOT_FOUND)
class ForgotPasswordReset(APIView):
permission_classes = (AllowAny,)
@decorators.error_safe
@transaction.atomic
def post(self, request, token=None, *args, **kwargs):
body_unicode = request.body.decode('utf-8')
body_data = json.loads(body_unicode)
username = body_data['username']
password = body_data['password']
password_confirm = body_data['password_confirm']
passcode = body_data['passcode']
if not username:
raise Exception('Username is required')
if not passcode:
raise Exception('Passcode is required')
if password != password_confirm:
raise Exception('Passwords must match')
existingToken = AuthToken.objects.filter(token=token).first()
if existingToken:
if existingToken.user.username != username:
raise Exception('Username does not match')
if not existingToken.is_active:
raise Exception('Request is no longer active')
if existingToken.passcode != passcode:
raise Exception('Invalid Passcode')
# TODO: Reset password here
exUser = User.objects.filter(id=existingToken.user.id).first()
exUser.set_password(password_confirm)
exUser.save()
existingToken.is_active = False
existingToken.save()
sender.password_changed(
str(existingToken.user.username),
str(datetime.now()),
str(existingToken.user.email))
return Response(data={"detail": "Forgot Password Reset Success"},
status=status.HTTP_200_OK)
else:
return Response(data={"error": "Token not found"},
status=status.HTTP_404_NOT_FOUND)
from django.apps import AppConfig
class ApplicationLayerConfig(AppConfig):
name = 'application_layer'
from django.apps import AppConfig
class AuthenticationConfig(AppConfig):
name = 'authentication'
from django.db import models
# Create your models here.
from django.shortcuts import render
# Create your views here.
from rest_framework import serializers
from app.entities.models import Application
import ast
class ApplicationSerializer(serializers.ModelSerializer):
class Meta:
model = Application
fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
from django_filters import rest_framework as filters
from django.db.models import Count
from app.entities.models import Application
from django.db.models import Q
class ApplicationFilterSet(filters.FilterSet):
# search = filters.CharFilter(method='search_bar', label='search')
# def search_bar(self, queryset, name, value):
# return queryset.filter(
# Q(username__icontains=value) |
# Q(first_name__icontains=value) |
# Q(last_name__icontains=value))
class Meta:
model = Application
fields = '__all__'
from app.entities import enums
from django.db import transaction
from app.helper import decorators
from rest_framework import viewsets, status
from rest_framework.response import Response
from django.forms.models import model_to_dict
from rest_framework.filters import SearchFilter
from django_filters import rest_framework as filters
from app.entities.models import Application, EntityLog
from app.applicationlayer.utils import (
CustomPagination, status_message_response, log_save
)
from django_filters.rest_framework import DjangoFilterBackend
from app.applicationlayer.management.application import serializer
from app.applicationlayer.management.application.table_filters import ApplicationFilterSet
class ApplicationViewSet(viewsets.ModelViewSet):
queryset = Application.objects.all()
serializer_class = serializer.ApplicationSerializer
pagination_class = CustomPagination
filter_backends = (DjangoFilterBackend,)
filterset_class = ApplicationFilterSet
# search_fields = ('name',)
@transaction.atomic
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
message = status_message_response(
201, 'success',
'New application created', serializer.data
)
return Response(
message
)
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
message = status_message_response(
200,
'success',
'list of applications found',
serializer.data
)
return self.get_paginated_response(message)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
@decorators.error_safe
@transaction.atomic
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
new_instance = model_to_dict(instance)
self.perform_destroy(instance)
log_save(
enums.LogEnum.DELETED.value,
enums.LogEntitiesEnum.APPLICATION.value,
new_instance['id'],
new_instance,
''
)
return Response(status=status.HTTP_204_NO_CONTENT)
@transaction.atomic
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
old_instance = model_to_dict(instance)
self.perform_update(serializer)
new_instance = serializer.data
log_save(
enums.LogEnum.UPDATE.value,
enums.LogEntitiesEnum.APPLICATION.value,
new_instance['id'],
old_instance,
new_instance
)
return Response(serializer.data)
from rest_framework import serializers
from app.entities.models import Company
class CompanySerializer(serializers.ModelSerializer):
class Meta:
model = Company
fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
from django_filters import rest_framework as filters
from django.db.models import Count
from app.entities.models import Company
from django.db.models import Q
class CompanyFilterSet(filters.FilterSet):
# search = filters.CharFilter(method='search_bar', label='search')
# def search_bar(self, queryset, name, value):
# return queryset.filter(
# Q(username__icontains=value) |
# Q(first_name__icontains=value) |
# Q(last_name__icontains=value))
class Meta:
model = Company
fields = '__all__'
from app.entities import enums
from django.db import transaction
from rest_framework import viewsets, status
from rest_framework.response import Response
from django.forms.models import model_to_dict
from rest_framework.filters import SearchFilter
from django_filters import rest_framework as filters
from app.entities.models import Company, EntityLog
from app.applicationlayer.utils import (
CustomPagination, status_message_response, log_save
)
from django_filters.rest_framework import DjangoFilterBackend
from app.applicationlayer.management.company import serializer
from app.applicationlayer.management.company.table_filters import CompanyFilterSet
from app.helper import decorators
class CompanyViewSet(viewsets.ModelViewSet):
queryset = Company.objects.all()
serializer_class = serializer.CompanySerializer
pagination_class = CustomPagination
filter_backends = (DjangoFilterBackend, SearchFilter,)
filterset_class = CompanyFilterSet
# search_fields = ('name',)
@transaction.atomic
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
message = status_message_response(
201, 'success',
'New Company created', serializer.data
)
return Response(
message
)
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
message = status_message_response(
200,
'success',
'list of Company found',
serializer.data
)
return self.get_paginated_response(message)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
@decorators.error_safe
@transaction.atomic
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
new_instance = model_to_dict(instance)
self.perform_destroy(instance)
log_save(
enums.LogEnum.DELETED.value,
enums.LogEntitiesEnum.COMPANY.value,
new_instance['id'],
new_instance,
''
)
return Response(status=status.HTTP_204_NO_CONTENT)
@transaction.atomic
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
old_instance = model_to_dict(instance)
self.perform_update(serializer)
new_instance = serializer.data
log_save(
enums.LogEnum.DELETED.value,
enums.LogEntitiesEnum.COMPANY.value,
new_instance['id'],
old_instance,
new_instance
)
return Response(serializer.data)
from rest_framework import serializers
from app.entities.models import Department
class DepartmentSerializer(serializers.ModelSerializer):
class Meta:
model = Department
fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
from django_filters import rest_framework as filters
from django.db.models import Count
from app.entities.models import Department
from django.db.models import Q
class DepartmentFilterSet(filters.FilterSet):
# search = filters.CharFilter(method='search_bar', label='search')
# def search_bar(self, queryset, name, value):
# return queryset.filter(
# Q(username__icontains=value) |
# Q(first_name__icontains=value) |
# Q(last_name__icontains=value))
class Meta:
model = Department
fields = '__all__'
from app.entities import enums
from django.db import transaction
from rest_framework import viewsets, status
from rest_framework.response import Response
from django.forms.models import model_to_dict
from rest_framework.filters import SearchFilter
from django_filters import rest_framework as filters
from app.entities.models import Department, EntityLog
from app.applicationlayer.utils import (
CustomPagination, status_message_response, log_save
)
from django_filters.rest_framework import DjangoFilterBackend
from app.applicationlayer.management.department import serializer
from app.applicationlayer.management.department.table_filters import DepartmentFilterSet
from app.helper import decorators
class DepartmentViewSet(viewsets.ModelViewSet):
queryset = Department.objects.all()
serializer_class = serializer.DepartmentSerializer
pagination_class = CustomPagination
filter_backends = (DjangoFilterBackend, SearchFilter,)
filterset_class = DepartmentFilterSet
# search_fields = ('name',)
@transaction.atomic
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
message = status_message_response(
201, 'success',
'New Department created', serializer.data
)
return Response(
message
)
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
message = status_message_response(
200,
'success',
'list of Department found',
serializer.data
)
return self.get_paginated_response(message)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
@decorators.error_safe
@transaction.atomic
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
new_instance = model_to_dict(instance)
self.perform_destroy(instance)
log_save(
enums.LogEnum.DELETED.value,
enums.LogEntitiesEnum.DEPARTMENT.value,
new_instance['id'],
new_instance,
''
)
return Response(status=status.HTTP_204_NO_CONTENT)
@transaction.atomic
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
old_instance = model_to_dict(instance)
self.perform_update(serializer)
new_instance = serializer.data
log_save(
enums.LogEnum.DELETED.value,
enums.LogEntitiesEnum.DEPARTMENT.value,
new_instance['id'],
old_instance,
new_instance
)
return Response(serializer.data)
from rest_framework import serializers
from app.entities.models import Module
class ModuleSerializer(serializers.ModelSerializer):
class Meta:
model = Module
fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
from django_filters import rest_framework as filters
from django.db.models import Count
from app.entities.models import Module
from django.db.models import Q
class ModuleFilterSet(filters.FilterSet):
# search = filters.CharFilter(method='search_bar', label='search')
# def search_bar(self, queryset, name, value):
# return queryset.filter(
# Q(username__icontains=value) |
# Q(first_name__icontains=value) |
# Q(last_name__icontains=value))
class Meta:
model = Module
fields = '__all__'
from app.entities import enums
from django.db import transaction
from rest_framework import viewsets, status
from rest_framework.response import Response
from django.forms.models import model_to_dict
from rest_framework.filters import SearchFilter
from django_filters import rest_framework as filters
from app.entities.models import Module, EntityLog
from app.applicationlayer.utils import (
CustomPagination, status_message_response, log_save
)
from django_filters.rest_framework import DjangoFilterBackend
from app.applicationlayer.management.module import serializer
from app.applicationlayer.management.module.table_filters import ModuleFilterSet
from app.helper import decorators
from django.db.models import F
class ModuleViewSet(viewsets.ModelViewSet):
queryset = Module.objects.order_by('parent', 'sort_id')
serializer_class = serializer.ModuleSerializer
pagination_class = CustomPagination
filter_backends = (DjangoFilterBackend, SearchFilter,)
filterset_class = ModuleFilterSet
# search_fields = ('name',)
@transaction.atomic
def create(self, request, *args, **kwargs):
mutable = request.POST._mutable
request.POST._mutable = True
list_submodules = Module.objects.filter(
parent=request.data['parent'], sort_id__gt=0
).order_by('sort_id')
new_sort_id = request.data['sort_id']
# for sorting
if list_submodules.count() == 0:
request.data['sort_id'] = 1
elif int(new_sort_id) > list_submodules.count():
request.data['sort_id'] = list_submodules.count() + 1
else:
list_submodules.filter(
sort_id__gte=new_sort_id
).update(sort_id=F('sort_id') + 1)
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
message = status_message_response(
201, 'success',
'New module created', serializer.data
)
return Response(message)
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
message = status_message_response(
200,
'success',
'list of Module found',
serializer.data
)
return self.get_paginated_response(message)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
@transaction.atomic
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
list_submodules = Module.objects.filter(
parent=request.data['parent'],
sort_id__gt=0
).order_by('sort_id')
old_sort_id = instance.sort_id
old_parent = instance.parent
update_sort_id = request.data['sort_id']
update_parent = request.data['parent']
# for sorting
if old_parent != update_parent:
list_submodules_old = Module.objects.filter(
parent=old_parent,
sort_id__gt=0).order_by('sort_id')
# "sort the (instance) submodule's sort_id"
if int(old_sort_id) != list_submodules_old.count():
list_submodules_old.filter(
sort_id__gt=old_sort_id).update(
sort_id=F('sort_id') - 1
)
# "sort the (request) submodule's sort_id"
if list_submodules.count() == 0:
request.data['sort_id'] = 1
elif int(update_sort_id) > list_submodules.count():
request.data['sort_id'] = list_submodules.count() + 1
else:
list_submodules.filter(
sort_id__gte=update_sort_id).update(
sort_id=F('sort_id') + 1)
else:
if int(update_sort_id) > list_submodules.count():
request.data['sort_id'] = list_submodules.count()
list_submodules.filter(
sort_id__gt=old_sort_id
).update(sort_id=F('sort_id') - 1)
elif int(update_sort_id) < old_sort_id:
list_submodules.filter(
sort_id__gte=update_sort_id, sort_id__lt=old_sort_id
).update(sort_id=F('sort_id') + 1)
else:
list_submodules.filter(
sort_id__gt=old_sort_id, sort_id__lte=update_sort_id
).update(sort_id=F('sort_id') - 1)
serializer = self.get_serializer(instance, data=request.data,
partial=partial)
serializer.is_valid(raise_exception=True)
old_instance = model_to_dict(instance)
self.perform_update(serializer)
new_instance = serializer.data
log_save(
enums.LogEnum.UPDATE.value,
enums.LogEntitiesEnum.MODULE.value,
new_instance['id'],
old_instance,
new_instance
)
message = status_message_response(
200, 'success', 'Module updated',
serializer.data
)
return Response(message)
@transaction.atomic
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
new_instance = model_to_dict(instance)
self.perform_destroy(instance)
log_save(
enums.LogEnum.DELETED.value,
enums.LogEntitiesEnum.MODULE.value,
new_instance['id'],
new_instance,
''
)
return Response(status=status.HTTP_204_NO_CONTENT)
from django.apps import AppConfig
class UserManagementConfig(AppConfig):
name = 'user_management'
from rest_framework import serializers
from app.applicationlayer import serializers as app_serializers
from app.entities import models
from django.db.models import Q
# Used for Create and Update
class UserManagementSerializer(serializers.ModelSerializer):
image = serializers.SerializerMethodField()
class Meta:
model = models.User
exclude = ['password']
def get_image(self, user):
request = self.context.get('request')
primayPic = user.user_images.filter(is_primary=True).first()
if primayPic:
print(primayPic.image.url)
return request.build_absolute_uri(primayPic.image.url)
else:
return request.build_absolute_uri('/media/no-user.png')
# Used for Retrieve and List
class UserManagementRoleSerializer(serializers.ModelSerializer):
permissions = serializers.SlugRelatedField(many=True,
read_only=True,
slug_field='code')
class Meta:
model = models.Role
fields = '__all__'
read_only_fields = ['createdby', 'modifiedby', 'created', 'modified']
# Used for Retrieve and List
class UserManagementRetreiveSerializer(serializers.ModelSerializer):
image = serializers.SerializerMethodField()
applications = serializers.SerializerMethodField()
department_name = serializers.ReadOnlyField(source='department.name')
department_id = serializers.ReadOnlyField(source='department.id')
# role = UserManagementRoleSerializer()
# special_permissions = serializers.SlugRelatedField(many=True,
# read_only=True,
# slug_field='code')
class Meta:
model = models.User
fields = (
'id', 'image', 'applications',
'last_login', 'is_superuser',
'first_name', 'last_name',
'is_staff', 'is_active',
'date_joined', 'user_type',
'code', 'name',
'username', 'contact_no',
'email', 'department_name',
'doa', 'department_id'
)
# exclude = ['password', 'application', 'groups', 'user_permissions']
def get_image(self, user):
request = self.context.get('request')
primayPic = user.user_images.filter(is_primary=True).first()
if primayPic:
print(primayPic.image.url)
return request.build_absolute_uri(primayPic.image.url)
else:
return request.build_absolute_uri('/media/no-user.png')
def get_applications(self, user):
app = user.application.all()
list_app = []
for data in app:
if user.user_type == 'USR' and data.name == 'RMS':
pass
else:
remove = ['Module', 'Company', 'Department', 'Application']
if user.user_type == 'SU':
mod = data.modules.all().values('name')
else:
mod = data.modules.exclude(name__in=remove).values(
"id", 'name', 'parent'
)
# mod = mod.exclude(~Q(parent=0))
mod = mod.order_by('parent', 'sort_id')
# list_mod = []
# for body in mod:
# parent_id = body['id']
# child_module = models.Module.objects.filter(
# parent=parent_id
# )
# if child_module:
# body['sub_modules'] = child_module.values(
# "id", 'name', 'parent'
# )
# list_mod.append(body)
app_body = {}
app_body['name'] = data.name
# app_body['modules'] = list_mod
app_body['modules'] = mod
list_app.append(app_body)
return list_app
class ChangePasswordSerializer(serializers.Serializer):
old_password = serializers.CharField(max_length=100, required=True)
new_password = serializers.CharField(max_length=100, required=True)
new_password_confirm = serializers.CharField(max_length=100, required=True)
class Meta:
fields = '__all__'
# class UserSpecialPermissionSerializer(serializers.Serializer):
# special_permissions = app_serializers.PermissionSerializer(required=True,
# many=True)
# class Meta:
# fields = '__all__'
from django_filters import rest_framework as filters
from django.db.models import Count
from app.entities import models
from django.db.models import Q
class UserManagementFilter(filters.FilterSet):
search = filters.CharFilter(method='search_bar', label='search')
def search_bar(self, queryset, name, value):
return queryset.filter(
Q(username__icontains=value) |
Q(first_name__icontains=value) |
Q(last_name__icontains=value))
class Meta:
model = models.User
fields = '__all__'
import copy
import json
from app.entities import enums
from app.businesslayer import logger
from django.forms.models import model_to_dict
from django.shortcuts import render
from rest_framework.response import Response
from app.entities import models
from django.db import transaction
from app.helper import decorators
from rest_framework import viewsets, status
from rest_framework.decorators import action
from app.applicationlayer import table_filters
from django_filters.rest_framework import DjangoFilterBackend
from app.applicationlayer import paginators
from app.applicationlayer import serializers as app_serializers
from . import serializers, table_filters
from django.conf import settings
from django.contrib.auth import authenticate
from app.helper.file_manager import FileHelper
from app.applicationlayer.utils import (
CustomPagination, status_message_response, log_save, QuerySetHelper
)
from django.db.models import (Q, F, Sum, OuterRef, Subquery, Q, Case, When,
Value, Func, Count,
CharField,
IntegerField,
DecimalField,
BooleanField)
# Create your views here.
class UsersManagementViewSet(viewsets.ModelViewSet):
"""ViewSet for the Requisition"""
queryset = models.User.objects.all()
serializer_class = serializers.UserManagementSerializer
filter_backends = (DjangoFilterBackend,)
filter_class = table_filters.UserManagementFilter
pagination_class = CustomPagination
@decorators.error_safe
def list(self, request, *args, **kwargs):
self.serializer_class = serializers.UserManagementRetreiveSerializer
self.queryset = QuerySetHelper.Sort(self)
return super(UsersManagementViewSet, self).list(request)
@decorators.error_safe
def retrieve(self, request, *args, **kwargs):
self.serializer_class = serializers.UserManagementRetreiveSerializer
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
@decorators.error_safe
@transaction.atomic
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
pk = serializer.data['id']
createdUser = models.User.objects.filter(id=pk).first()
createdUser.set_password(settings.USER_DEFAULT_PASSWORD)
createdUser.save()
# LOG ADD
logger.log_save(
enums.LogEnum.ADD.value,
enums.LogEntitiesEnum.USER.value,
model_to_dict(createdUser))
return Response(serializer.data,
status=status.HTTP_201_CREATED,
headers=headers)
@decorators.error_safe
@transaction.atomic
def perform_update(self, serializer):
fromObj = copy.copy(serializer.instance)
serializer.save()
toObj = copy.copy(serializer.instance)
logger.log_save(
enums.LogEnum.UPDATE.value,
enums.LogEntitiesEnum.USER.value,
model_to_dict(fromObj),
model_to_dict(toObj))
@action(detail=True,
methods=['put'],
url_path='upload-profile-picture',
name="Uploads Profile Picture of User")
@decorators.error_safe
@transaction.atomic
def UploadProfilePicture(self, request, pk=None):
existingUser = models.User.objects.filter(id=pk).first()
if existingUser:
eximages = models.UserImage.objects.filter(user_id=pk)
if (eximages):
for item in eximages:
item.delete()
# DELETE FROM PHYSICAL
FileHelper.DeleteFile(path=item.image.path)
self.serializer_class = app_serializers.UserImageSerializer
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data,
status=status.HTTP_201_CREATED,
headers=headers)
else:
raise Exception('User not found')
return Response(data={"detail": "Success"})
@action(detail=True,
methods=['put'],
url_path='reset-password',
name="Reset Password of User")
@decorators.error_safe
@transaction.atomic
def ResetPassword(self, request, pk=None):
existingUser = models.User.objects.filter(id=pk).first()
if existingUser:
existingUser.set_password(settings.USER_DEFAULT_PASSWORD)
fromObj = copy.copy(existingUser)
existingUser.save()
toObj = copy.copy(existingUser)
logger.log_save(
enums.LogEnum.UPDATE.value,
enums.LogEntitiesEnum.ROBOT.value,
model_to_dict(fromObj),
model_to_dict(toObj))
else:
raise Exception('User not found')
return Response(data={"detail": "Success"})
@action(detail=True,
methods=['put'],
url_path='change-password',
name="Change Password of User")
@decorators.error_safe
@transaction.atomic
def ChangePassword(self, request, pk=None):
self.serializer_class = serializers\
.ChangePasswordSerializer
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
form = copy.deepcopy(serializer.validated_data)
if form['new_password'] != form['new_password_confirm']:
raise Exception('Passwords must match')
existingUser = models.User.objects.filter(id=pk).first()
if existingUser:
user = authenticate(
username=existingUser.username,
password=form['old_password'])
if user:
existingUser.set_password(form['new_password_confirm'])
fromObj = copy.copy(existingUser)
existingUser.save()
toObj = copy.copy(existingUser)
logger.log_save(
enums.LogEnum.UPDATE.value,
enums.LogEntitiesEnum.ROBOT.value,
model_to_dict(fromObj),
model_to_dict(toObj))
return Response(data={"detail": "Success"},
status=200)
else:
raise Exception("Invalid Old Password")
else:
raise Exception('User not found')
else:
serializer.is_valid(raise_exception=True)
return Response(data={"detail": "Error"}, status=500)
@action(detail=True,
methods=['put'],
url_path='add-special-permissions',
name="Adds special permissions to user")
@decorators.error_safe
@transaction.atomic
def UserSpecialPermissions(self, request, pk=None):
user = models.User.objects.filter(id=pk).first()
if not user:
raise Exception('User not found')
# CLEARES ALL USER'S SPECIAL PERMISSION'
for i in user.special_permissions.all():
i.delete()
user.save()
# LOAD NEW USER'S NEW SPECIAL PERMISSIONS
form = copy.deepcopy(request.data)
for spid in form['special_permissions']:
sp = models.Permission.objects.filter(id=spid).first()
if not sp:
raise Exception(F"{spid} does not exists")
return Response(data={"detail": "Success"}, status=200)
# # Lists ALL Application Permissions (No Pagination)
# @action(detail=False,
# methods=['get'],
# url_path='all-permissions',
# name="Lists all Application's Permissions")
# @decorators.error_safe
# def AllPermissions(self, request, *args, **kwargs):
# return Response(
# models.Permission.objects.values(
# permissionId=F('id'),
# permissionCode=F('code')
# )
# )
from rest_framework import pagination
from collections import OrderedDict
from rest_framework.response import Response
from django.core.paginator import InvalidPage
from rest_framework.exceptions import NotFound
from django.utils import six
from django.utils.translation import ugettext_lazy as _
class SimplePageNumberPagination(pagination.PageNumberPagination):
page_query_param = 'page'
page_size_query_param = 'page-size'
max_page_size = 1000
invalid_page_message = _('Invalid page.')
def paginate_queryset(self, queryset, request, view=None):
"""
Paginate a queryset if required, either returning a
page object, or `None` if pagination is not configured for this view.
"""
page_size = self.get_page_size(request)
if not page_size:
return None
paginator = self.django_paginator_class(queryset, page_size)
page_number = request.query_params.get(self.page_query_param, 1)
if page_number in self.last_page_strings:
page_number = paginator.num_pages
try:
if len(queryset) < page_size:
page_number = 1
self.page = paginator.page(page_number)
except InvalidPage as exc:
msg = self.invalid_page_message.format(
page_number=page_number, message=six.text_type(exc)
)
raise NotFound(msg)
if paginator.num_pages > 1 and self.template is not None:
# The browsable API should display pagination controls.
self.display_page_controls = True
self.request = request
return list(self.page)
def get_paginated_response(self, data, additional_info=None):
content = [
('count', self.page.paginator.count),
('next', self.get_next_link()),
('previous', self.get_previous_link()),
('results', data),
('page', self.page.number),
('additional_info', additional_info)
]
return Response(OrderedDict(content))
from rest_framework import serializers
from app.entities import models
class DepartmentSerializer(serializers.ModelSerializer):
class Meta:
model = models.Department
fields = ('__all__')
depth = 0
from django.urls import path, include
from rest_framework import routers
from app.applicationlayer.management.application.views import ApplicationViewSet
from app.applicationlayer.management.company.views import CompanyViewSet
from app.applicationlayer.management.department.views import DepartmentViewSet
from app.applicationlayer.management.module.views import ModuleViewSet
# from app.applicationlayer.management.user.views import UsersManagementViewSet
router = routers.DefaultRouter()
router.register(r'applications', ApplicationViewSet)
router.register(r'companies', CompanyViewSet)
router.register(r'departments', DepartmentViewSet)
router.register(r'modules', ModuleViewSet)
# router.register(r'users', UsersManagementViewSet)
urlpatterns = (
path('', include(router.urls)),
)
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from functools import wraps
from app.entities import enums
from app.entities.models import EntityLog
from django.forms.models import model_to_dict
class CustomPagination(PageNumberPagination):
page_size = 5
max_page_size = 50
page_query_param = 'page'
page_size_query_param = 'page_size'
def get_paginated_response(self, data):
return Response({
'page_number': self.page.number,
'size_per_page': self.page.paginator.per_page,
'total_pages': self.page.paginator.num_pages,
'total': self.page.paginator.count,
'code': data['code'],
'status': data['status'],
'message': data['message'],
'results': data['results']
})
# def entitylogs_decorator(function):
# @wraps(function)
# def wrapper(self, request, *args, **kwargs):
# req_method = request.method
# print(req_method)
# if req_method.upper() == 'DELETE':
# req_method = enums.LogEnum.DELETED.value
# elif req_method.upper == 'PUT':
# req_method = enums.LogEnum.UPDATE.value
# from_instance = model_to_dict(self.get_object())
# print("self.serializer.data['id']")
# print(self.serializer.data['id'])
# EntityLog.objects.create(
# action=req_method,
# entity=enums.LogEntitiesEnum.APPLICATION.value,
# row_id=from_instance['id'],
# fromValue=from_instance
# )
# return function(self, request, *args, **kwargs)
# return wrapper
def log_save(action, entity, row_id, fromValue, toValue):
EntityLog.objects.create(
action=action,
entity=entity,
row_id=row_id,
fromValue=fromValue,
toValue=toValue
)
return True
def status_message_response(code, status, message, results):
message = {
'code': code,
'status': status,
'message': message,
'results': results
}
return message
\ No newline at end of file
from django.apps import AppConfig
class BusinessLayerConfig(AppConfig):
name = 'business_layer'
from django.apps import AppConfig
class DataLayerConfig(AppConfig):
name = 'data_layer'
from rest_framework.views import exception_handler
def custom_exception_handler(exc, context):
# Call REST framework's default exception handler first,
# to get the standard error response.
response = exception_handler(exc, context)
# Update the structure of the response data.
if response is not None:
error_message = {}
for key, value in response.data.items():
if type(value) == list and value[0].code == 'blank':
value = value[0].replace('This field', key)
# elif type(value) == dict:
# value = value['non_field_errors']
# print(value['non_field_errors'])
# print("value['non_field_errors']")
elif type(value) == list:
value = value[0]
error_message['code'] = response.status_code
error_message['status'] = 'failed'
error_message['message'] = value
response.data = error_message
return response
from django.contrib.auth.models import BaseUserManager
class UserManager(BaseUserManager):
"""
Django requires that custom users define their own Manager class. By
inheriting from `BaseUserManager`, we get a lot of the same code used by
Django to create a `User`.
All we have to do is override the `create_user` function which we will use
to create `User` objects.
"""
def create_user(self, username, email, password=None):
"""Create and return a `User` with an email, username and password."""
if username is None:
raise TypeError('Users must have a username.')
if email is None:
raise TypeError('Users must have an email address.')
user = self.model(username=username, email=self.normalize_email(email))
user.set_password(password)
user.save()
return user
def create_superuser(self, username, email, password):
"""
Create and return a `User` with superuser (admin) permissions.
"""
if password is None:
raise TypeError('Superusers must have a password.')
user = self.create_user(username, email, password)
user.is_superuser = True
user.is_staff = True
user.save()
return user
\ No newline at end of file
from django.contrib import admin
# Register your models here.
from django.apps import AppConfig
class EntitiesConfig(AppConfig):
name = 'entities'
from enum import Enum
class ModelSeriesEnum(Enum):
USER = "USR"
# CLIENT = "CLI"
# CONSUMABLEPRODUCTS = "CSP"
# PROJECT = "PRJ"
# SERIALIZEITEM = "ITM"
# SERIALIZEPRODUCT = "SRP"
# SUPPLIER = "SUP"
# WAREHOUSE = "WHL"
# ACQUISITION = 'AQN'
# REQUISITION = 'RQN'
# PURCHASEREQUEST = 'PR'
# STOCKTAKE = 'STK'
# CHECKOUT = 'CHK'
class UserTypeEnum(Enum):
SUPER_USER = "SU"
OVERALL_USER_ADMIN = "OUA"
COMPANY_USER_ADMIN = "CUA"
DEPARTMENT_USER_ADMIN = "DUA"
USER = "USR"
class GenerateCode(Enum):
APP = 'APP'
MODULE = 'MODULE'
COMPANY = 'COMPANY'
DEPARTMENT = 'DEPARTMENT'
USER = 'USER'
'''
*********
LOG ENUMS
*********
'''
class LogEnum(Enum):
ADD = "Add"
UPDATE = "Update"
DELETED = "DELETED"
class LogEntitiesEnum(Enum):
USER = "USER"
APPLICATION = "APPLICATION"
COMPANY = "COMPANY"
DEPARTMENT = "DEPARTMENT"
MODULE = "MODULE"
# BRAND = "Brand"
# CATEGORY = "Category"
# CURRENCY = "Currency"
# UNIT_MATERIAL = "Unit Material"
# NEWS = "News"
# PROJECT = "Project"
# PROJECT_LOCATION = "Project Location"
# WAREHOUSE = "Warehouse"
# SUPPLIER = "Supplier"
# CLIENT = "Client"
# PRODUCT = "Product"
# ACQUISITION_ITEM = "Acquisition Item"
# STOCK = "Stock"
# STOCK_ITEM = "Stock Item"
# REQUISITION = "Requisition Header"
This diff is collapsed.
from django.db import models
from datetime import datetime
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
# Ordering of | null=True, blank=True | is IMPORTANT!:
#
# Order 1 : null=True, blank=True
# NULL as default value
#
# Order 2 : blank=True, null=True
# Requires to add 'default="your_default_val_here"
# else, it will error upon saving
'''
BaseAuditClass
The base class that will give:
created, createdby, updated, updatedby, deleted & deletedby COLUMNS
to whoever inehrits it.
'''
from app.middleware.current_user.data import get_current_user
class BaseAuditClass(models.Model):
created = models.DateTimeField(auto_now_add=True)
createdby = models.CharField(max_length=255)
modified = models.DateTimeField(auto_now=True)
modifiedby = models.CharField(max_length=255)
def save(self, *args, **kwargs):
username = 'Anonymous User'
user = get_current_user()
# user.is_authenticated():
if user and user.username:
username = user.username
self.modifiedby = username
if self._state.adding:
self.createdby = user
super(BaseAuditClass, self).save(*args, **kwargs)
class Meta:
abstract = True
'''
Status Table
Inherits BaseAuditClass
Hence, it will get all the proterties of its parent.
This is a standalone table.
Purpose:
To tag the status of all rows in a specific tables as:
ACT - Active
DCT - Deactivated
DEL - Deleted
ARC - Archived
'''
class Status(BaseAuditClass):
ref = models.CharField(max_length=10)
code = models.CharField(unique=True, max_length=10)
name = models.CharField(unique=True, max_length=10)
description = models.CharField(max_length=100, blank=False, null=True)
def __str__():
return self.name
class Meta:
db_table = 'status_set'
'''
AuditClass
Combination of BaseAuditClass & Status.
Extends 'BaseAuditClass' to get the auditing columns.
References 'Status' table to attach Status to each rows of the inheriting
table.
This is the class who will be inherited by the tables in this project
instead of 'models.Model' (which is the default).
'''
class AuditClass(BaseAuditClass):
# status = models.ForeignKey(Status, on_delete=models.PROTECT)
class Meta:
abstract = True
def _str__(self):
return self.name
from django.db import models
from django.contrib.auth.models import AbstractUser
from .modelcommon import AuditClass
from .UserManager import UserManager
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from datetime import datetime
from . import enums
from django.utils.text import slugify
# ********************* AUTH TABLES *********************
def number_generator(prefix, id):
date = '{:%Y%m%d}'.format(datetime.now())
id_num = '{:07}'.format(id)
autogenerated_no = prefix + '-' + date + '-' + id_num
return autogenerated_no
class Application(AuditClass):
code = models.CharField(
unique=True,
max_length=255
)
name = models.CharField(unique=True, max_length=255)
class Meta:
db_table = 'applications'
def __str__(self):
return f'{self.name}'
def save(self, *args, **kwargs):
super(Application, self).save(*args, **kwargs)
code = enums.GenerateCode.APP.value
code = number_generator(enums.GenerateCode.APP.value, self.id)
Application.objects.filter(id=self.id).update(code=code)
class Module(AuditClass):
application = models.ForeignKey(
Application,
related_name='modules',
on_delete=models.PROTECT
)
code = models.CharField(
unique=True,
max_length=255,
default='mod'
)
name = models.CharField(
unique=True,
max_length=255,
blank=True,
null=True
)
parent = models.IntegerField()
sort_id = models.IntegerField()
class Meta:
db_table = 'modules'
def __str__(self):
return f'{self.name}'
def save(self, *args, **kwargs):
super(Module, self).save(*args, **kwargs)
code = enums.GenerateCode.APP.value
code = number_generator(enums.GenerateCode.MODULE.value, self.id)
Module.objects.filter(id=self.id).update(code=code)
class Company(AuditClass):
code = models.CharField(
unique=True,
max_length=255,
default='com'
)
name = models.CharField(unique=True, max_length=255)
contact_details = models.TextField(blank=True, null=True)
class Meta:
db_table = 'companies'
def __str__(self):
return f'{self.name}'
def save(self, *args, **kwargs):
super(Company, self).save(*args, **kwargs)
code = enums.GenerateCode.APP.value
code = number_generator(enums.GenerateCode.COMPANY.value, self.id)
Company.objects.filter(id=self.id).update(code=code)
class Department(AuditClass):
# parent = models.ForeignKey(
# 'Department',
# related_name='departments_parent',
# on_delete=models.PROTECT,
# blank=True, null=True
# )
company = models.ForeignKey(
Company,
related_name='companies',
on_delete=models.PROTECT
)
code = models.CharField(
unique=True,
max_length=255,
default='dept'
)
name = models.CharField(unique=True, max_length=255)
class Meta:
db_table = 'departments'
def __str__(self):
return f'{self.name}'
def save(self, *args, **kwargs):
super(Department, self).save(*args, **kwargs)
code = enums.GenerateCode.APP.value
code = number_generator(enums.GenerateCode.DEPARTMENT.value, self.id)
Department.objects.filter(id=self.id).update(code=code)
# class Position(AuditClass):
# parent = models.ForeignKey('Position',
# related_name='position_subs',
# on_delete=models.PROTECT,
# blank=True, null=True)
# code = models.CharField(unique=True, max_length=255)
# name = models.CharField(unique=True, max_length=255)
# description = models.CharField(max_length=255, blank=True, null=True)
# department = models.ForeignKey(Department,
# related_name='positions',
# on_delete=models.PROTECT)
# class Meta:
# db_table = 'positions'
class Role(AuditClass):
description = models.CharField(
max_length=255,
blank=True,
null=True
)
code = models.CharField(
unique=True,
max_length=255,
default='role'
)
name = models.CharField(max_length=255)
class Meta:
db_table = 'roles'
class Permission(AuditClass):
name = models.CharField(max_length=255, blank=False, null=True)
code = models.CharField(
unique=True,
max_length=255,
blank=True,
null=True
)
description = models.CharField(
max_length=255,
blank=False,
null=True
)
class Meta:
db_table = 'permissions'
class RolePermission(AuditClass):
role = models.ForeignKey(
Role,
related_name='role_permissions',
on_delete=models.PROTECT
)
permission = models.ForeignKey(
Permission,
related_name='role_permissions',
on_delete=models.PROTECT
)
class Meta:
db_table = 'role_permissions'
class User(AbstractUser):
application = models.ManyToManyField(
Application
)
department = models.ForeignKey(
Department, related_name='department_users',
on_delete=models.PROTECT,
default=1
)
# role = models.ForeignKey(
# Role,
# related_name='role_users',
# on_delete=models.PROTECT,
# default=1
# )
user_type = models.CharField(
choices=[(tag.value, tag.value) for tag in enums.UserTypeEnum],
default=enums.UserTypeEnum.USER.value,
max_length=100
)
code = models.CharField(
unique=True,
max_length=255,
default='acct'
)
name = models.CharField(max_length=255)
username = models.CharField(max_length=255, unique=True)
password = models.CharField(
max_length=255,
blank=True,
null=True
)
doa = models.ForeignKey(
'User', related_name='doa_users',
on_delete=models.PROTECT,
blank=True,
null=True
)
contact_no = models.CharField(blank=True, null=True, max_length=255)
email = models.EmailField(max_length=255, unique=False)
objects = UserManager()
class Meta:
db_table = 'auth_user'
def __str__(self):
return f'{self.name}'
def save(self, *args, **kwargs):
super(User, self).save(*args, **kwargs)
code = enums.GenerateCode.APP.value
code = number_generator(enums.GenerateCode.USER.value, self.id)
User.objects.filter(id=self.id).update(code=code)
class UserImage(AuditClass):
user = models.ForeignKey(
User,
related_name='user_images',
on_delete=models.PROTECT
)
name = models.CharField(blank=True, null=True, max_length=255)
image = models.ImageField(upload_to='user_images/', null=True,
max_length=255)
is_primary = models.BooleanField(default=True)
class Meta:
db_table = 'auth_user_images'
class Attachment(AuditClass):
code = models.FileField(
upload_to='file_attachments/',
null=True,
max_length=255
)
name = models.CharField(unique=True, max_length=255)
description = models.CharField(
max_length=255,
blank=True,
null=True
)
class Meta:
db_table = 'attachments'
"""
**********************
*** UTILITY TABLES ***
**********************
"""
class AuthToken(models.Model):
ref = models.CharField(max_length=255)
token = models.TextField()
passcode = models.CharField(max_length=255)
timeout = models.IntegerField()
is_active = models.BooleanField(default=False)
user = models.ForeignKey(User,
related_name='auth_access_token',
on_delete=models.PROTECT)
class Meta:
db_table = 'auth_access_token'
class EntityLog(AuditClass):
action = models.CharField(
choices=[
(tag.value, tag.value) for tag in enums.LogEnum],
default=enums.LogEnum.ADD.value,
max_length=50)
entity = models.CharField(
choices=[
(tag.value, tag.value) for tag in enums.LogEntitiesEnum],
default=enums.LogEnum.ADD.value,
max_length=50)
row_id = models.IntegerField()
fromValue = models.TextField(blank=True, null=True)
toValue = models.TextField(blank=True, null=True)
def __str__(self):
return self.entity
class Meta:
db_table = 'entity_logs'
from django.apps import AppConfig
class HelperConfig(AppConfig):
name = 'helper'
_DAYS_IN_MONTH = [-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
_DAYS_BEFORE_MONTH = [-1] # -1 is a placeholder for indexing purposes.
dbm = 0
for dim in _DAYS_IN_MONTH[1:]:
_DAYS_BEFORE_MONTH.append(dbm)
dbm += dim
del dbm, dim
def _is_leap(year):
"year -> 1 if leap year, else 0."
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
def days_in_month(year, month):
"year, month -> number of days in that month in that year."
assert 1 <= month <= 12, month
if month == 2 and _is_leap(year):
return 29
return _DAYS_IN_MONTH[month]
from rest_framework.response import Response
from rest_framework import status
import json
def error_safe(function):
def wrap(request, *args, **kwargs):
stat = status.HTTP_500_INTERNAL_SERVER_ERROR
try:
return function(request, *args, **kwargs)
# except 'DoesNotExist' as ex:
# print('ddd')
# stat = status.HTTP_404_NOT_FOUND
except Exception as ex:
data = ''
try:
data = str(ex)
print(f'ERROR: {data}')
except Exception as ex2:
pass
return Response(data={"message": data},
status=stat)
wrap.__doc__ = function.__doc__
wrap.__name__ = function.__name__
return wrap
from django.apps import AppConfig
class EmailServiceConfig(AppConfig):
name = 'email_service'
This diff is collapsed.
<html>
<body style="background-color: #ccc;">
<div style="background-color: rgba(255,255,255,0.7); padding: 10px; margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" style="margin: 10px auto; max-width: 200px; height: auto;" />
<br><br>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<br/>
<p>Your account for the Inventory Management System have been successfully <br>created.</p>
<br/>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<table>
<tr><td> <br> URL:</td><td > <br> <span style="margin-left:65px;"> <a href="[URL]">[URL]</a> </span></td></tr>
<tr><td> <br> Username: </td><td> <br> <span style="margin-left:65px;">[Username]</span></td></tr>
<tr><td> <br> Password: </td><td> <br> <span style="margin-left:65px;">[Password]</span></td><td><span><small style="color:red;"><br>(Upon login, please change your password)</small> </span></tr>
</table>
<br>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>**This is a system generated email, do not reply to this email.**</small>
</td>
</tr>
</table>
</div>
</body>
</html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;" >
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7); padding: 10px; margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td width="100px">Subject:</td>
<td>Confirmed Order <span style="background-color: yellow;">[PO Number]</span>: Project Number, Supplier, Item</td>
</tr>
<tr bgcolor="#FFFFFF">
<td width="100px">Attachment:</td>
<td><span style="background-color: yellow;">[Authorised Purchase Order]</span></td>
</tr>
</table>
</div>
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7); padding: 10px; margin-bottom: 10px;">
<h3 style="text-align: center;">Email Template</h3>
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://inventory.tirapp.com/cds/image.ashx?id=CDS_IMAGE_39117a66-0738-40cb-9bf4-51a7d53abe50&v=20170125071840" style="margin: 10px auto;" />
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Dear [Supplier]</p>
<br/>
<p>We would like to confirm our order of the items, please see our PO as attached.</p>
<p>Kindly please deliver the items with the related invoice.</p>
<br/>
<p>Thank you,</p>
<p>[Purchasing] </p>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>Template Created by TIR Solutions</small>
</td>
</tr>
</table>
</div>
</body></html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7); padding: 10px; margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td width="100px">Subject:</td>
<td><span style="background-color: yellow;">[Stock Requisition No.]</span> Collection </td>
</tr>
</table>
</div>
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);" >
<h3 style="text-align: center;">Email Template</h3>
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://inventory.tirapp.com/cds/image.ashx?id=CDS_IMAGE_39117a66-0738-40cb-9bf4-51a7d53abe50&v=20170125071840" style="margin: 10px auto;" />
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Dear [Requestor]</p>
<br/>
<p>In regards to <span style="background-color: yellow;">[Stock Requisition No.]</span>, your order is ready for pick up at the following details: </p>
<table>
<tr><td>Location: </td><td><span style="background-color: yellow;">[Location]</span></td></tr>
<tr><td>Date: </td><td><span style="background-color: yellow;">[Date]</span></td></tr>
<tr><td>Time: </td><td><span style="background-color: yellow;">[Time]</span></td></tr>
</table>
<p><span style="background-color: yellow;">[Copy the items list from Stock Request Email and paste here]<span></p>
<br/>
<p>Thank you,</p>
<p>[Storekeeper] </p>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>Template Created by TIR Solutions</small>
</td>
</tr>
</table>
</div>
</body></html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td width="100px">Subject:</td>
<td>Order Query: <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">Project Number</span>, Supplier, Item</td>
</tr>
<tr bgcolor="#FFFFFF">
<td width="100px">Attachment:</td>
<td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Draft Purchase Order]</span></td>
</tr>
</table>
</div>
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<h3 style="text-align: center;">Email Template</h3>
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://inventory.tirapp.com/cds/image.ashx?id=CDS_IMAGE_39117a66-0738-40cb-9bf4-51a7d53abe50&v=20170125071840" style="margin: 10px auto;" />
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Dear [Supplier]</p>
<br/>
<p>We would like to purchase the following items, please see details attached. </p>
<p>Please confirm or complete the details on our attached request</p>
<p>On confirmation of the above, we will then issue an authorised purchase order. </p>
<br/>
<p>Thank you,</p>
<p>[Purchasing] </p>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>Template Created by TIR Solutions</small>
</td>
</tr>
</table>
</div>
</body></html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div style="background-color: rgba(255,255,255,0.7); padding: 10px; margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" style="margin: 10px auto; max-width: 200px; height: auto;" />
<br><br>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align='center'>
<br/>
<p>You have requested to reset your password.</p>
<br/>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align='center'>
<br>
<h1>Reset Code</h1>
<h1>[reset_code]</h1>
<br><br>
<span> <a href="[URL]">[URL]</a> </span>
<br>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>**This is a system generated email, do not reply to this email.**</small>
</td>
</tr>
</table>
</div>
</body>
</html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td width="100px">Subject:</td>
<td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[PO Number]</span> Items Received</td>
</tr>
</table>
</div>
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<h3 style="text-align: center;">Email Template</h3>
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://inventory.tirapp.com/cds/image.ashx?id=CDS_IMAGE_39117a66-0738-40cb-9bf4-51a7d53abe50&v=20170125071840" style="margin: 10px auto;" />
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Dear [Purchasing/Janet & Finance/Suzanna]</p>
<br/>
<p>In regards to <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[PO number]</span>, items were well received at <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[location]</span> on <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[date]</span> and inventory has been recorded in the system</p>
<br/>
<p>Thank you,</p>
<p>[Storekeeper] </p>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>Template Created by TIR Solutions</small>
</td>
</tr>
</table>
</div>
</body></html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td width="100px">Subject:</td>
<td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[PO Number]</span> Items Delivered</td>
</tr>
</table>
</div>
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<h3 style="text-align: center;">Email Template</h3>
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://inventory.tirapp.com/cds/image.ashx?id=CDS_IMAGE_39117a66-0738-40cb-9bf4-51a7d53abe50&v=20170125071840" style="margin: 10px auto;" />
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Dear [Requestor]</p>
<br/>
<p>With regards to <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[PO number]</span>, items have been delivered to <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[location]</span> and recorded in the system.</p>
<p>Please login and apply the Stock Requisition.</p>
<br/>
<p>Thank you,</p>
<p>[Storekeeper] </p>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>Template Created by TIR Solutions</small>
</td>
</tr>
</table>
</div>
</body></html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td width="100px">Subject:</td>
<td>Order Request for <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Project Number]</span> NEW Items</td>
</tr>
</table>
</div>
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<h3 style="text-align: center;">Email Template</h3>
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://inventory.tirapp.com/cds/image.ashx?id=CDS_IMAGE_39117a66-0738-40cb-9bf4-51a7d53abe50&v=20170125071840" style="margin: 10px auto;" />
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Dear [Requestor]</p>
<br/>
<p>The items you have requested is now on the system.</p>
<table>
<tr><td>Project: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Project Number]</span></td></tr>
<tr><td>Required by Date: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Date]</span></td></tr>
</table>
<br/>
<p>Here are the <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">Product Details</span>, Brand, Model, <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">Specifications</span>, Estimated Cost, and Reference Photos:
<p><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Product 1]<span></p>
<p>[Product 2]</p>
<br/>
<p>Please login to do a formal request. </p>
<br/>
<p>Thank you,</p>
<p>[Purchasing] </p>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>Template Created by TIR Solutions</small>
</td>
</tr>
</table>
</div>
</body></html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td width="100px">To:</td>
<td>ims@oneberry.com</td>
</tr>
<tr bgcolor="#FFFFFF">
<td width="100px">Subject:</td>
<td>New Project, <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Project Number]</span></td>
</tr>
</table>
</div>
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<h3 style="text-align: center;">Email Template</h3>
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://inventory.tirapp.com/cds/image.ashx?id=CDS_IMAGE_39117a66-0738-40cb-9bf4-51a7d53abe50&v=20170125071840" style="margin: 10px auto;" />
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Dear System Admin,</p>
<p>I would like to create a project below:</p>
<table>
<tr><td>Client: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Client]</span></td></tr>
<tr><td>Contact Number: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Contact Number]</span></td></tr>
<tr><td>Email: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Email]</span></td></tr>
<tr><td>Contact Person: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Contact Person]</span></td></tr>
</table>
<br/>
<table>
<tr><td>Project: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Project Number]</span></td></tr>
<tr><td>Project Description: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Project Description]</span></td></tr>
<tr><td>Start Date: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Start Date]</span></td></tr>
<tr><td>End Date: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[End Date]</span></td></tr>
</table>
<p>Locations (Optional)</p>
<table width='100%' bgcolor="#EEEEEE" cellpadding='0' cellspacing='1'>
<tr bgcolor="#FFFFFF">
<th>Name</th>
<th>Address</th>
<th>Coordinate</th>
</tr>
<tr bgcolor="#FFFFFF">
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
<br/>
<p>Thank you,</p>
<p>[Requestor]</p>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>Template Created by TIR Solutions</small>
</td>
</tr>
</table>
</div>
</body></html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td width="100px">To:</td>
<td>ims@oneberry.com</td>
</tr>
<tr bgcolor="#FFFFFF">
<td width="100px">Subject:</td>
<td>New User Account</td>
</tr>
</table>
</div>
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<h3 style="text-align: center;">Email Template</h3>
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://inventory.tirapp.com/cds/image.ashx?id=CDS_IMAGE_39117a66-0738-40cb-9bf4-51a7d53abe50&v=20170125071840" style="margin: 10px auto;" />
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Dear System Admin,</p>
<p>I would like to create an account below:</p>
<table>
<tr><td>Username: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Username]</span></td></tr>
<tr><td>Contact Number: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Contact Number]</span></td></tr>
<tr><td>Email: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Email]</span></td></tr>
<tr><td>Position/Designation: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Position/Designation]</span></td></tr>
</table>
<br/>
<p>Thank you,</p>
<p>[Requestor]</p>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>Template Created by TIR Solutions</small>
</td>
</tr>
</table>
</div>
</body></html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div style="background-color: rgba(255,255,255,0.7); padding: 10px; margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" style="margin: 10px auto; max-width: 200px; height: auto;" />
<br><br>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<br/>
<p>Hello [Username], Your password has been changed on [Datetime].</p>
<p>If you did not perform this action, Please contact the Administrator.</p>
<p>You may login in this url <a href="[URL]">[URL]</a> .</p>
<br/>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>**This is a system generated email, do not reply to this email.**</small>
</td>
</tr>
</table>
</div>
</body>
</html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td width="100px">Subject:</td>
<td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[PO number]</span> mismatch from DO/Invoice</td>
</tr>
</table>
</div>
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<h3 style="text-align: center;">Email Template</h3>
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://inventory.tirapp.com/cds/image.ashx?id=CDS_IMAGE_39117a66-0738-40cb-9bf4-51a7d53abe50&v=20170125071840" style="margin: 10px auto;" />
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Dear [Purchasing/Janet]</p>
<br/>
<p>We received these items at <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[location]</span> on <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[date]</span> where DO/Invoice is mismatch.</p>
<p><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Quantity in PO is more than DO/Invoice]<span></p>
<p><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Price in Invoice is lower than PO]<span></p>
<br/>
<p>Please update your records accordingly or contact supplier for any issues.</p>
<br/>
<p>Thank you,</p>
<p>[Storekeeper]</p>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>Template Created by TIR Solutions</small>
</td>
</tr>
</table>
</div>
</body></html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td width="100px">Subject:</td>
<td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[PO Number]</span>: Project Number, Supplier, Item </td>
</tr>
<tr bgcolor="#FFFFFF">
<td width="100px">Subject:</td>
<td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Authorised Purchase Order]</span></td>
</tr>
</table>
</div>
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<h3 style="text-align: center;">Email Template</h3>
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://inventory.tirapp.com/cds/image.ashx?id=CDS_IMAGE_39117a66-0738-40cb-9bf4-51a7d53abe50&v=20170125071840" style="margin: 10px auto;" />
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Dear [Authoriser]</p>
<br/>
<p>Please approve this PO as attached. </p>
<br/>
<p>Thank you,</p>
<p>[Purchasing] </p>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>Template Created by TIR Solutions</small>
</td>
</tr>
</table>
</div>
</body></html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td width="100px">Subject:</td>
<td>Order Request for <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Project Number]</span> – Not Approved </td>
</tr>
</table>
</div>
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<h3 style="text-align: center;">Email Template</h3>
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://inventory.tirapp.com/cds/image.ashx?id=CDS_IMAGE_39117a66-0738-40cb-9bf4-51a7d53abe50&v=20170125071840" style="margin: 10px auto;" />
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Dear [Requestor]</p>
<br/>
<p>Your order request for the below items are not approved by <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[John/Ken]</span> because of <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Reason]</span>. Please check with them directly on the next steps.</p>
<table>
<tr><td>Project: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Project Number]</span></td></tr>
<tr><td>Required by Date: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Date]</span></td></tr>
</table>
<br/>
<p>Here are the Product Details & Specifications:</p>
<p><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Product 1]<span></p>
<p>[Product 2]</p>
<br/>
<p>Thank you,</p>
<p>[Purchasing] </p>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>Template Created by TIR Solutions</small>
</td>
</tr>
</table>
</div>
</body></html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div style="background-color: rgba(255,255,255,0.7); padding: 10px; margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" style="margin: 10px auto; max-width: 200px; height: auto;" />
<br><br>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<br/>
<p>Your password has been reset as of [Reset Datetime].</p>
<br/>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<table>
<tr><td> <br> Username: </td><td> <br> <span style="margin-left:65px;">[Username]</span></td></tr>
<tr><td> <br> Password: </td><td> <br> <span style="margin-left:65px;">[Password]</span></td><td><span><small style="color:red;"><br>(Upon login, please change your password)</small> </span></tr>
</table>
<br>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>**This is a system generated email, do not reply to this email.**</small>
</td>
</tr>
</table>
</div>
</body>
</html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div style="background-color: rgba(255,255,255,0.7); padding: 10px; margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" style="margin: 10px auto; max-width: 200px; height: auto;" />
<h3 style="text-align: center;">Stock Requisition Approved <br> [SR No]</h3>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<table>
<tr><td>Stock Requisition No: </td><td><span>[SR No]</span></td></tr>
<tr><td>Requestor: </td><td><span>[Requestor]</span></td></tr>
<tr><td>Requested On: </td><td><span>[Requested On]</span></td></tr>
<tr><td>Project: </td><td><span>[Project]</span></td></tr>
<tr><td>Remarks: </td><td><span>[Remarks]</span></td></tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<table>
<tr><td>Approved By: </td><td><span >[Approved By]</span></td></tr>
<tr><td>Approved On: </td><td><span >[Approved On]</span></td></tr>
<tr><td>Partial Reject Reason: </td><td><span >[Partial Reject Reason]</span></td></tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Approved Stock Request Items:</p>
<table width='100%' bgcolor="#EEEEEE" cellpadding='0' cellspacing='1'>
<tr bgcolor="#EEEEEE" align="left">
<th>Product No.</th>
<th>Product Name</th>
<th>Brand</th>
<th>Qty</th>
<th>Unit</th>
</tr>
<tr bgcolor="#FFFFFF" id="sr">
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Partial Rejected Stock Request Items:</p>
<table width='100%' bgcolor="#EEEEEE" cellpadding='0' cellspacing='1'>
<tr bgcolor="#EEEEEE" align="left">
<th>Product No.</th>
<th>Product Name</th>
<th>Brand</th>
<th>Qty</th>
<th>Unit</th>
</tr>
<tr bgcolor="#FFFFFF" id="sr">
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Approved Purchase Request Items (Required by [Required Date]):</p>
<table width='100%' bgcolor="#EEEEEE" cellpadding='0' cellspacing='1'>
<tr bgcolor="#EEEEEE" align="left">
<th>Product No.</th>
<th>Product Name</th>
<th>Brand</th>
<th>Qty</th>
<th>Unit</th>
</tr>
<tr bgcolor="#FFFFFF" id="pr">
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Partial Rejected Purchase Request Items:</p>
<table width='100%' bgcolor="#EEEEEE" cellpadding='0' cellspacing='1'>
<tr bgcolor="#EEEEEE" align="left">
<th>Product No.</th>
<th>Product Name</th>
<th>Brand</th>
<th>Qty</th>
<th>Unit</th>
</tr>
<tr bgcolor="#FFFFFF" id="pr">
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Note: Please contact the <b>requestor</b> on the collection details.</p>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>**This is a system generated email, do not reply to this email.**</small>
</td>
</tr>
</table>
</div>
</body>
</html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div style="background-color: rgba(255,255,255,0.7); padding: 10px; margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" style="margin: 10px auto; max-width: 200px; height: auto;" />
<h3 style="text-align: center;">Stock Requisition Approved <br> [SR No]</h3>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<table>
<tr><td>Stock Requisition No: </td><td><span>[SR No]</span></td></tr>
<tr><td>Requestor: </td><td><span>[Requestor]</span></td></tr>
<tr><td>Requested On: </td><td><span>[Requested On]</span></td></tr>
<tr><td>Project: </td><td><span>[Project]</span></td></tr>
<tr><td>Remarks: </td><td><span>[Remarks]</span></td></tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<table>
<tr><td>Approved By: </td><td><span style="margin-left:50px;">[Approved By]</span></td></tr>
<tr><td>Approved On: </td><td><span style="margin-left:50px;">[Approved On]</span></td></tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Approved Stock Request Items:</p>
<table width='100%' bgcolor="#EEEEEE" cellpadding='0' cellspacing='1'>
<tr bgcolor="#EEEEEE" align="left">
<th>Product No.</th>
<th>Product Name</th>
<th>Brand</th>
<th>Qty</th>
<th>Unit</th>
</tr>
<tr bgcolor="#FFFFFF" id="sr">
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Approved Purchase Request Items (Required by [Required Date]):</p>
<table width='100%' bgcolor="#EEEEEE" cellpadding='0' cellspacing='1'>
<tr bgcolor="#EEEEEE" align="left">
<th>Product No.</th>
<th>Product Name</th>
<th>Brand</th>
<th>Qty</th>
<th>Unit</th>
</tr>
<tr bgcolor="#FFFFFF" id="pr">
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Note: Please contact the <b>requestor</b> on the collection details.</p>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>**This is a system generated email, do not reply to this email.**</small>
</td>
</tr>
</table>
</div>
</body>
</html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td width="100px">Subject:</td>
<td>Order Request for <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Project Number]</span> NEW Items</td>
</tr>
<tr bgcolor="#FFFFFF">
<td width="100px">CC:</td>
<td>ken@oneberry.com, john@oneberry.com, jennifer@oneberry.com</td>
</tr>
</table>
</div>
<div class="ob_EmailTemplatePanel" style="background-color: rgba(255,255,255,0.7);
padding: 10px;
margin-bottom: 10px;">
<h3 style="text-align: center;">Email Template</h3>
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://inventory.tirapp.com/cds/image.ashx?id=CDS_IMAGE_39117a66-0738-40cb-9bf4-51a7d53abe50&v=20170125071840" style="margin: 10px auto;" />
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Dear [Purchasing/Janet]</p>
<br/>
<p>I would like to request to purchase the following items, please see below:</p>
<table>
<tr><td>Project: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Project Number]</span></td></tr>
<tr><td>Required by Date: </td><td><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Date]</span></td></tr>
</table>
<br/>
<p>Here are the <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">Product Details</span>, Brand, Model, <span class="ob_EmailTemplateHighlight" style="background-color: yellow;">Specifications</span>, Estimated Cost, and Reference Photos:
<p><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Product 1]<span></p>
<p>[Product 2]</p>
<br/>
<p>Intended use of these items:</p>
<p><span class="ob_EmailTemplateHighlight" style="background-color: yellow;">[Information on application]<span></p>
<br>
<p>Here are the suggested suppliers:</p>
<p>[List Suppliers]</p>
<br>
<p>[Any other information eg. Product of origin]</p>
<p>OR</p>
<p>Please help us source suppliers</p>
<br/>
<p>Thank you,</p>
<p>[Requestor]</p>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>Template Created by TIR Solutions</small>
</td>
</tr>
</table>
</div>
<div class="ob_EmailTemplatePanel">
<h3>Additional Template to paste to <span class="ob_EmailTemplateHighlight">[Product ?]</span></h3>
<table width="570px" bgcolor="#FFFFFF" style="border: 1px solid #999999;">
<tr>
<td width="100px">Product Details:</td>
<td><span class="ob_EmailTemplateHighlight">[Product Details]</span></td>
</tr>
<tr>
<td width="100px">Brand:</td>
<td>[Brand]</td>
</tr>
<tr>
<td width="100px">Model:</td>
<td>[Model]</td>
</tr>
<tr>
<td width="100px">Specifications:</td>
<td><span class="ob_EmailTemplateHighlight">[Specifications]</span></td>
</tr>
<tr>
<td width="100px">Estimated Cost:</td>
<td>[Estimated Cost]</td>
</tr>
<tr>
<td width="100px">Reference Photos:</td>
<td>[Reference Photos]</td>
</tr>
</table>
</div>
</body></html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div style="background-color: rgba(255,255,255,0.7); padding: 10px; margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" style="margin: 10px auto; max-width: 200px; height: auto;" />
<h3 style="text-align: center;">Stock Requisition Rejected <br> [SR No]</h3>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<table>
<tr><td>Stock Requisition No: </td><td><span>[SR No]</span></td></tr>
<tr><td>Requestor: </td><td><span>[Requestor]</span></td></tr>
<tr><td>Requested On: </td><td><span>[Requested On]</span></td></tr>
<tr><td>Project: </td><td><span>[Project]</span></td></tr>
<tr><td>Remarks: </td><td><span>[Remarks]</span></td></tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<table>
<tr><td>Rejected By: </td><td><span style="margin-left:30px;">[Rejected By]</span></td></tr>
<tr><td>Rejected On: </td><td><span style="margin-left:30px;">[Rejected On]</span></td></tr>
<tr><td>Rejected Reason: </td><td><span style="margin-left:30px;">[Rejected On]</span></td></tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Rejected Stock Request Items:</p>
<table width='100%' bgcolor="#EEEEEE" cellpadding='0' cellspacing='1'>
<tr bgcolor="#EEEEEE" align="left">
<th>Product No.</th>
<th>Product Name</th>
<th>Brand</th>
<th>Qty</th>
<th>Unit</th>
</tr>
<tr bgcolor="#FFFFFF" id="sr">
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Rejected Purchase Request Items (Required by [Required Date]):</p>
<table width='100%' bgcolor="#EEEEEE" cellpadding='0' cellspacing='1'>
<tr bgcolor="#EEEEEE" align="left">
<th>Product No.</th>
<th>Product Name</th>
<th>Brand</th>
<th>Qty</th>
<th>Unit</th>
</tr>
<tr bgcolor="#FFFFFF" id="pr">
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>**This is a system generated email, do not reply to this email.**</small>
</td>
</tr>
</table>
</div>
</body>
</html>
\ No newline at end of file
<html>
<body style="background-color: #ccc;">
<div style="background-color: rgba(255,255,255,0.7); padding: 10px; margin-bottom: 10px;">
<table bgcolor="#EEEEEE" width="600px" cellpadding="10px" style="border: 1px solid #999999; margin: 0 auto;">
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" style="margin: 10px auto; max-width: 200px; height: auto;" />
<h3 style="text-align: center;">Stock Requisition</h3>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<table>
<tr><td>Stock Requisition No: </td><td><span>[SR No]</span></td></tr>
<tr><td>Requestor: </td><td><span>[Requestor]</span></td></tr>
<tr><td>Requested On: </td><td><span>[Requested On]</span></td></tr>
<tr><td>Project: </td><td><span>[Project]</span></td></tr>
<tr><td>Remarks: </td><td><span>[Remarks]</span></td></tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Stock Request Items:</p>
<table width='100%' bgcolor="#EEEEEE" cellpadding='0' cellspacing='1'>
<tr bgcolor="#EEEEEE" align="left">
<th>Product No.</th>
<th>Product Name</th>
<th>Brand</th>
<th>Qty</th>
<th>Unit</th>
</tr>
<tr bgcolor="#FFFFFF" id="sr">
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2">
<p>Purchase Request Items (Required by [Required Date]):</p>
<table width='100%' bgcolor="#EEEEEE" cellpadding='0' cellspacing='1'>
<tr bgcolor="#EEEEEE" align="left">
<th>Product No.</th>
<th>Product Name</th>
<th>Brand</th>
<th>Qty</th>
<th>Unit</th>
</tr>
<tr bgcolor="#FFFFFF" id="pr">
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<span>
<button style="cursor: pointer; font-weight: bold; background-color:#E52129; border-color:#E52129; padding: 15px 25px 15px 25px; border-radius: 8px; font-size: 15px;" ><a href="RejectToken" style="color: white; text-decoration: none;">REJECT</a></button>
&nbsp;
&nbsp;
<button style="cursor: pointer; font-weight: bold; background-color:#008000; border-color:#008000; padding: 15px 95px 15px 95px; border-radius: 8px; font-size: 15px;"><a href="ApproveToken" style="color: white; text-decoration: none;">APPROVE</a></button>
</span>
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td colspan="2" align="center">
<small>**This is a system generated email, do not reply to this email.**</small>
</td>
</tr>
</table>
</div>
</body>
</html>
\ No newline at end of file
import os
class FileHelper:
@staticmethod
def DeleteFile(path):
if os.path.isfile(path):
os.remove(path)
# elif os.path.isdir(path):
# shutil.rmtree(path) # remove dir and all contains
else:
pass
# raise ValueError("file {} is not a file or dir.".format(path))
from django.apps import AppConfig
class MiddlewareConfig(AppConfig):
name = 'middleware'
import threading
_thread_locals = threading.local()
def set_current_user(user):
_thread_locals.user = user
def get_current_user():
return getattr(_thread_locals, 'user', None)
def remove_current_user():
_thread_locals.user = None
from .data import set_current_user, remove_current_user
class CurrentUserMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
set_current_user(getattr(request, 'user', None))
response = self.get_response(request)
# Code to be executed for each request/response after
# the view is called.
remove_current_user()
return response
"""
Django settings for ams project.
Generated by 'django-admin startproject' using Django 2.2.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/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.dirname(
os.path.abspath(__file__))))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'w!dkk7gc*dk#4!6ow3s1wc32%_yp$=osgybm=n0vw6k1j^sqo&'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'corsheaders',
'rest_framework.authtoken',
'app.accesslayer',
'app.entities'
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'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',
'app.middleware.current_user.main.CurrentUserMiddleware'
]
ROOT_URLCONF = 'config.urls'
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',
],
},
},
]
WSGI_APPLICATION = 'config.wsgi.application'
AUTH_USER_MODEL = 'entities.User'
# Password validation
# https://docs.djangoproject.com/en/2.2/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.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Asia/Singapore'
USE_I18N = True
USE_L10N = True
USE_TZ = False
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, "static")
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
CORS_ORIGIN_ALLOW_ALL = True
REST_SESSION_LOGIN = True
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.AdminRenderer',
'rest_framework.renderers.BrowsableAPIRenderer'
],
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
'rest_framework.permissions.AllowAny',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
# 'rest_framework.authentication.TokenAuthentication',
'app.accesslayer.authentication.AppTokenAuthentication',
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
),
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',),
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
# 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
'EXCEPTION_HANDLER': 'app.datalayer.serializer_handler.custom_exception_handler',
'PAGE_SIZE': 10
}
EMAIL_TEMPLATES_ROOT = os.path.join(BASE_DIR, "app/helper/email_service/templates")
EMAIL_HOST = 'email-smtp.us-west-2.amazonaws.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'AKIAIPRWQKYV6N5SMLUA'
EMAIL_HOST_PASSWORD = 'ApK1dtH2qpT/oMl9MEauFvyN9XZDQ1fjzd8TumIs71NG'
EMAIL_USE_SSL = False
EMAIL_USE_TLS = True
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_DEFAULT_SENDER = 'ims.noreply@oneberrysystem.com'
from .base import *
import configparser
DEBUG = True
ALLOWED_HOSTS = ['*']
config = configparser.ConfigParser()
config_file = os.path.join('./', 'env.ini')
config.read(config_file)
DATABASES = {
'default': {
'ENGINE': config['DEV']['DATABASE_ENGINE'],
'NAME': config['DEV']['DATABASE_NAME'],
'USER': config['DEV']['DATABASE_USER'],
'PASSWORD': config['DEV']['DATABASE_PASSWORD'],
'HOST': config['DEV']['DATABASE_HOST'],
'PORT': config['DEV']['DATABASE_PORT'],
}
}
# ****************
# PROGRAM SETTINGS
# ****************
SESSION_TIMEOUT = config['DEV']['SESSION_TIMEOUT']
FRONT_END_URL = config['DEV']['FRONT_END_URL']
AUTH_ACCESSS_TOKEN_TIMEOUT = config['DEV']['AUTH_ACCESSS_TOKEN_TIMEOUT']
USER_DEFAULT_PASSWORD = config['DEV']['USER_DEFAULT_PASSWORD']
from .base import *
import configparser
DEBUG = True
config = configparser.ConfigParser()
config_file = os.path.join(BASE_DIR, 'env.ini')
config.read(config_file)
DATABASES = {
'default': {
'ENGINE': config['LOCAL']['DATABASE_ENGINE'],
'NAME': config['LOCAL']['DATABASE_NAME'],
'USER': config['LOCAL']['DATABASE_USER'],
'PASSWORD': config['LOCAL']['DATABASE_PASSWORD'],
'HOST': config['LOCAL']['DATABASE_HOST'],
'PORT': config['LOCAL']['DATABASE_PORT'],
}
}
# ****************
# PROGRAM SETTINGS
# ****************
SESSION_TIMEOUT = config['LOCAL']['SESSION_TIMEOUT']
FRONT_END_URL = config['LOCAL']['FRONT_END_URL']
AUTH_ACCESSS_TOKEN_TIMEOUT = config['LOCAL']['AUTH_ACCESSS_TOKEN_TIMEOUT']
USER_DEFAULT_PASSWORD = config['LOCAL']['USER_DEFAULT_PASSWORD']
from .base import *
import configparser
DEBUG = False
ALLOWED_HOSTS = ['*']
config = configparser.ConfigParser()
config_file = os.path.join('./', 'env.ini')
config.read(config_file)
DATABASES = {
'default': {
'ENGINE': config['PRODUCTION']['DATABASE_ENGINE'],
'NAME': config['PRODUCTION']['DATABASE_NAME'],
'USER': config['PRODUCTION']['DATABASE_USER'],
'PASSWORD': config['PRODUCTION']['DATABASE_PASSWORD'],
'HOST': config['PRODUCTION']['DATABASE_HOST'],
'PORT': config['PRODUCTION']['DATABASE_PORT'],
}
}
# ****************
# PROGRAM SETTINGS
# ****************
SESSION_TIMEOUT = config['PRODUCTION']['SESSION_TIMEOUT']
FRONT_END_URL = config['PRODUCTION']['FRONT_END_URL']
AUTH_ACCESSS_TOKEN_TIMEOUT = config['PRODUCTION']['AUTH_ACCESSS_TOKEN_TIMEOUT']
USER_DEFAULT_PASSWORD = config['PRODUCTION']['USER_DEFAULT_PASSWORD']
from .base import *
import configparser
DEBUG = True
ALLOWED_HOSTS = ['*']
config = configparser.ConfigParser()
config_file = os.path.join('./', 'env.ini')
config.read(config_file)
DATABASES = {
'default': {
'ENGINE': config['UAT']['DATABASE_ENGINE'],
'NAME': config['UAT']['DATABASE_NAME'],
'USER': config['UAT']['DATABASE_USER'],
'PASSWORD': config['UAT']['DATABASE_PASSWORD'],
'HOST': config['UAT']['DATABASE_HOST'],
'PORT': config['UAT']['DATABASE_PORT'],
}
}
# ****************
# PROGRAM SETTINGS
# ****************
SESSION_TIMEOUT = config['UAT']['SESSION_TIMEOUT']
FRONT_END_URL = config['UAT']['FRONT_END_URL']
AUTH_ACCESSS_TOKEN_TIMEOUT = config['UAT']['AUTH_ACCESSS_TOKEN_TIMEOUT']
USER_DEFAULT_PASSWORD = config['UAT']['USER_DEFAULT_PASSWORD']
"""ams URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.2/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
urlpatterns = [
# path('admin/', admin.site.urls),
path('api-auth/', include('rest_framework.urls')),
path('api/v1/auth/', include('app.accesslayer.urls')),
path('api/v1/', include('app.applicationlayer.urls')),
]
"""
WSGI config for ams 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.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
application = get_wsgi_application()
[PRODUCTION]
DATABASE_ENGINE = django.db.backends.mysql
DATABASE_NAME =
DATABASE_USER =
DATABASE_PASSWORD =
DATABASE_HOST =
DATABASE_PORT =
SESSION_TIMEOUT =
FRONT_END_URL =
AUTH_ACCESSS_TOKEN_TIMEOUT =
USER_DEFAULT_PASSWORD =
[UAT]
DATABASE_ENGINE = django.db.backends.mysql
DATABASE_NAME =
DATABASE_USER =
DATABASE_PASSWORD =
DATABASE_HOST =
DATABASE_PORT =
SESSION_TIMEOUT =
FRONT_END_URL =
AUTH_ACCESSS_TOKEN_TIMEOUT =
USER_DEFAULT_PASSWORD =
[DEV]
DATABASE_ENGINE = django.db.backends.mysql
DATABASE_NAME =
DATABASE_USER =
DATABASE_PASSWORD =
DATABASE_HOST =
DATABASE_PORT =
SESSION_TIMEOUT =
FRONT_END_URL =
AUTH_ACCESSS_TOKEN_TIMEOUT =
USER_DEFAULT_PASSWORD =
[LOCAL]
DATABASE_ENGINE = django.db.backends.mysql
DATABASE_NAME = rms_db
DATABASE_USER = root
DATABASE_PASSWORD = password
DATABASE_HOST = localhost
DATABASE_PORT = 3306
SESSION_TIMEOUT = 30
FRONT_END_URL =
AUTH_ACCESSS_TOKEN_TIMEOUT = 3600
USER_DEFAULT_PASSWORD = password
[SETTINGS]
CONFIG = config.settings.local
#!/usr/bin/env python
import os
import sys
import configparser
config = configparser.ConfigParser()
config_file = os.path.join(os.path.dirname(__file__), 'env.ini')
config.read(config_file)
if __name__ == "__main__":
os.environ.setdefault('DJANGO_SETTINGS_MODULE',
config['SETTINGS']['CONFIG'])
# os.system('start chrome.exe --kiosk --kiosk-printing
# http://localhost:8000/')
try:
from django.core.management import execute_from_command_line
except ImportError:
# The above import may fail for some other reason. Ensure that the
# issue is really that Django is missing to avoid masking other
# exceptions on Python 2.
try:
import django
except ImportError:
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?"
)
raise
execute_from_command_line(sys.argv)
This diff is collapsed.
astroid==2.2.5
Django==2.2
django-cors-headers==2.5.2
django-filter==2.1.0
djangorestframework==3.9.2
isort==4.3.17
lazy-object-proxy==1.3.1
Markdown==3.1
mccabe==0.6.1
mysqlclient==1.4.2.post1
pep8==1.7.1
Pillow==6.0.0
pylint==2.3.1
pytz==2018.9
six==1.12.0
sqlparse==0.3.0
typed-ast==1.3.1
wrapt==1.11.1
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment