Commit d1c80aa6 authored by John Red Medrano's avatar John Red Medrano

Merge pull request #772 in RMS/api-main-service from staging to demo

* commit '82413744': (54 commits)
  rms31 bugfix removed transaction atomic and transaction.savepoint do manual the acid
  RMS32: User Management Download List, exclude the id number 1 to not include the superuser on list of user download
  RMS31: Upload User No Error Message for Incomplete File, make the keys for user priviledge string to make it lower
  added new command to clear the keys on redis
  {dev bugfix} fix validation_vendor_unique_level
  {dev bugfix} remove prints
  {dev bugfix} remove fields in model (company_desc, requested_desc, department_desc)
  removed redundant configs on base.py
  comment
  {dev bugfix} fix server error 500 on form post due to remove key company_desc, deprtment_desc, requested_desc
  remove docker
  reconstruct the env.ini, try to load all the configuration on base.py
  {dev bugfix} added separate validation for checking of atleast 1 approver
  {dev bugfix} custom pagination set to 1000 max
  {dev bugfix} validation save submit
  {dev bugfix} template validation patch
  {dev bugfix} Fix validation for Vendor with same level delegation
  {dev bugfix} code refactor on checking of account and applications
  {dev bugfix} strip fix
  {dev bugfix} add validations on patch
  ...
parents 585ee9ce 82413744
FROM python:3.6
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ADD . /code
COPY . /code
WORKDIR /code
RUN pip install -r requirements/local.txt
EXPOSE 7020
RUN python manage.py migrate
......@@ -8,7 +8,7 @@ class ChangeRequestFormApproversSerializer(
):
def to_representation(self, instance):
ret = super().to_representation(instance)
print(instance)
try:
ret['company'] = {
"id": instance.user.department.company.id,
......@@ -38,17 +38,17 @@ class ChangeRequestFormApproversSerializer(
if instance.form_code.status == 'Draft':
if instance.tmp_approver:
if instance.tmp_approver.user or instance.tmp_approver.delegation.name.lower() == 'requestor':
if instance.tmp_approver.user:
ret['editable_user'] = False
else:
ret['editable_user'] = True
if instance.tmp_approver.company or instance.tmp_approver.delegation.name.lower() == 'requestor':
if instance.tmp_approver.company:
ret['editable_comp'] = False
else:
ret['editable_comp'] = True
if instance.tmp_approver.department or instance.tmp_approver.delegation.name.lower() == 'requestor':
if instance.tmp_approver.department:
ret['editable_dept'] = False
else:
ret['editable_dept'] = True
......@@ -58,13 +58,12 @@ class ChangeRequestFormApproversSerializer(
else:
ret['editable_deleg'] = True
# print(instance.tmp_approver.delegation.name)
# comment
# if instance.tmp_approver.delegation.name.lower() == 'requestor':
# ret['editable_user'] = False
# ret['editable_comp'] = False
# ret['editable_dept'] = False
# ret['editable_deleg'] = False
if instance.tmp_approver.delegation:
if instance.tmp_approver.delegation.name.lower() == 'requestor':
ret['editable_user'] = False
ret['editable_comp'] = False
ret['editable_dept'] = False
ret['editable_deleg'] = False
else:
ret['editable_user'] = True
......@@ -84,13 +83,13 @@ class ChangeRequestFormApproversSerializer(
if instance.form_code.status == 'Draft':
if instance.tmp_approver:
if instance.tmp_approver.user or instance.tmp_approver.delegation.name.lower() == 'requestor':
if instance.tmp_approver.user:
ret['editable_user'] = False
else:
ret['user'] = None
ret['editable_user'] = True
if instance.tmp_approver.company or instance.tmp_approver.delegation.name.lower() == 'requestor':
if instance.tmp_approver.company:
ret['company'] = {
"id": instance.tmp_approver.company.id,
"code": instance.tmp_approver.company.code,
......@@ -102,7 +101,7 @@ class ChangeRequestFormApproversSerializer(
ret['company'] = None
ret['editable_comp'] = True
if instance.tmp_approver.department or instance.tmp_approver.delegation.name.lower() == 'requestor':
if instance.tmp_approver.department:
ret['department'] = {
"id": instance.tmp_approver.department.id,
"code": instance.tmp_approver.department.code,
......@@ -125,12 +124,12 @@ class ChangeRequestFormApproversSerializer(
ret['delegation'] = None
ret['editable_deleg'] = True
# print(instance.tmp_approver.delegation.name)
# if instance.tmp_approver.delegation.name.lower() == 'requestor':
# ret['editable_user'] = False
# ret['editable_comp'] = False
# ret['editable_dept'] = False
# ret['editable_deleg'] = False
if instance.tmp_approver.delegation:
if instance.tmp_approver.delegation.name.lower() == 'requestor':
ret['editable_user'] = False
ret['editable_comp'] = False
ret['editable_dept'] = False
ret['editable_deleg'] = False
else:
ret['editable_user'] = True
......
......@@ -17,18 +17,18 @@ class ChangeRequestFormAttachmentsSerializer(
"contact_no": instance.uploaded_by.contact_no
}
ret['uploaded_by'] = user_object
ret['file_upload'] = self.context['request'].build_absolute_uri(
instance.file_upload.url.url)
ret['file_upload_id'] = instance.file_upload.id
return ret
class Meta:
model = models.ChangeRequestFormAttachments
fields = '__all__'
read_only_fields = ['created', 'code']
class ChangeRequestFormAttachmentsFileUploadSerializer(
serializers.ModelSerializer
):
......
......@@ -98,7 +98,7 @@ class ChangeRequestFormHeaderSerializer(
ret['template_object'] = "None"
return ret
# 'company_desc', 'department_desc', 'requested_desc',
class Meta:
model = models.ChangeRequestFormHeader
# fields = '__all__'
......
......@@ -22,7 +22,8 @@ from django.db import transaction, IntegrityError, connection
from app.applicationlayer.utils import (QuerySetHelper,
status_message_response,
send_broadcast_message)
from app.businesslayer.changerequest import change_request
from app.businesslayer.changerequest import (change_request,
change_request_template)
from app.applicationlayer.cms.utils_cr import (number_generator,
send_mail_requestor,
......@@ -35,7 +36,8 @@ from app.applicationlayer.cms.utils_cr import (number_generator,
entity_log_bulk,
reminder_trigger_save,
overdue_trigger_save,
reset_autoemail_tables)
reset_autoemail_tables,
delete_master_attachment_file)
from app.entities import enums
from app.applicationlayer.utils import model_to_dict
......@@ -72,6 +74,9 @@ from django.conf import settings
from io import BytesIO
from django.http import HttpResponse
from xhtml2pdf import pisa
from app.helper.decorators import *
from app.applicationlayer.utils import error_message
config = configparser.ConfigParser()
......@@ -547,10 +552,7 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
form_code=str(form_code)
).values('file_upload__url')
attch_list = [data['file_upload__url'].split('/')[1] for data in attch]
# print(attch.query)
# print(attch)
# print(attch_list)
if os.path.isdir(my_folder):
shutil.rmtree(my_folder)
......@@ -575,7 +577,6 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
# full_file_name = os.path.join(my_folder, file_name)
# if os.path.isfile(full_file_name):
# shutil.copy(full_file_name, dest)
print(attch)
for file_name in attch:
print(file_name['file_upload__url'])
......@@ -583,7 +584,6 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
# full_file_name = os.path.join(my_folder, file_name['file_upload__url'])
# print(full_file_name)
if os.path.isfile(a):
print('ddd')
print(a)
# print(type(a))
b = open(a, 'r')
......@@ -749,6 +749,7 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
return Response(message, status=status.HTTP_200_OK)
@FormValidation
@transaction.atomic
@action(
methods=['PATCH'], detail=True,
......@@ -861,7 +862,8 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
)
return Response(message, status=status.HTTP_200_OK)
@FormValidation
@transaction.atomic
@action(
methods=['PATCH'], detail=True,
......@@ -874,6 +876,13 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
form_code = kwargs['form_code']
form_data = request.data
# Restrict a requestor to submit a CR without atleast 1 approver
counter = change_request_template.validation_existing_approver(
form_data['frm_approvers'])
if counter == 0:
return error_message('400', 'Please select at least 1 approver before submitting this request.',
'failed', status.HTTP_400_BAD_REQUEST)
# generate batchno history
batchno = get_max_batchno("batch")
......@@ -1177,16 +1186,17 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
class ChangeRequestFormPost(APIView):
@FormValidation
@transaction.atomic()
def post(self, request):
form_header = request.data
try:
data_list_approver = []
data_list_stake = []
data_list_attach = []
data_list_detail = []
form_header_data = {
'requested_to_template_name': form_header['requested_to_template_name'],
'requested_to_template_id': form_header['requested_to_template_id'],
......@@ -1195,9 +1205,6 @@ class ChangeRequestFormPost(APIView):
'requested_to_priority': form_header['requested_to_priority'],
'description': form_header['description'],
'status': form_header['status'],
'company_desc': form_header['company_desc'],
'department_desc': form_header['department_desc'],
'requested_desc': form_header['requested_desc'],
'requested_by_department': form_header['requested_by_department'],
'requested_by_user': form_header['requested_by_user'],
'requested_to_company': form_header['requested_to_company'],
......@@ -1206,7 +1213,11 @@ class ChangeRequestFormPost(APIView):
'template_no': form_header['template_no']
}
# sp1 = transaction.savepoint() # nothing will save to db
# 'company_desc': None,
# 'department_desc': None,
# 'requested_desc': None,
sp1 = transaction.savepoint() # nothing will save to db
serializer = ChangeRequestFormHeaderSerializer(
data=form_header_data)
......@@ -1225,15 +1236,13 @@ class ChangeRequestFormPost(APIView):
serializer.save()
frm_id = serializer.data['form_code']
# create form approvers
frm_approvers = form_header['frm_approvers']
counter = 0
for frm_approver in frm_approvers:
frm_approver['form_code'] = frm_id
counter = counter + 1
data_list_approver.append(frm_approver)
serializerApprover = ChangeRequestFormApproversSerializer(
data=data_list_approver, many=True)
......@@ -1364,7 +1373,8 @@ class ChangeRequestFormPost(APIView):
return Response(message, status=status.HTTP_201_CREATED)
except ValidationError as e:
# transaction.savepoint_rollback(sp1)
transaction.savepoint_rollback(sp1)
message = {
'code': 400,
'status': 'failed',
......@@ -1373,7 +1383,8 @@ class ChangeRequestFormPost(APIView):
return Response(message, status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
# transaction.savepoint_rollback(sp1)
transaction.savepoint_rollback(sp1)
message = {
'code': 500,
'status': 'failed',
......
......@@ -118,7 +118,6 @@ class ChangeRequestFormHeaderSerializer(
fields = ('form_code', 'requested_to_template_name', 'requested_to_objective',
'requested_to_target_date', 'requested_to_priority',
'description', 'created', 'cancel_date', 'status',
'company_desc', 'department_desc', 'requested_desc',
'requested_to_template_id', 'requested_to_company',
'requested_to_department', 'requested_to_user',
'requested_by_user', 'requested_by_department',
......@@ -127,7 +126,7 @@ class ChangeRequestFormHeaderSerializer(
read_only_fields = ['created', 'form_code']
# 'company_desc', 'department_desc', 'requested_desc',
class ChangeRequestFormHeaderSerializerList(
serializers.ModelSerializer
):
......
......@@ -941,9 +941,6 @@ class ChangeRequestFormPost(APIView):
'requested_to_priority': form_header['requested_to_priority'],
'description': form_header['description'],
'status': form_header['status'],
'company_desc': form_header['company_desc'],
'department_desc': form_header['department_desc'],
'requested_desc': form_header['requested_desc'],
'requested_by_department': form_header['requested_by_department'],
'requested_by_user': form_header['requested_by_user'],
'requested_to_company': form_header['requested_to_company'],
......@@ -952,6 +949,10 @@ class ChangeRequestFormPost(APIView):
'template_no': form_header['template_no']
}
# 'company_desc': form_header['company_desc'],
# 'department_desc': form_header['department_desc'],
# 'requested_desc': form_header['requested_desc'],
sp1 = transaction.savepoint() # nothing will save to db
serializer = serializers.ChangeRequestFormHeaderSerializer(
......
......@@ -26,8 +26,6 @@ class UserListTemplate(APIView):
user_list = models.User.objects.filter(
code__in=verified_users
)
print(user_list)
page = self.paginate_queryset(user_list)
if page is not None:
......
......@@ -22,7 +22,7 @@ class ChangeRequestTemplateApproversSerializer(
ret['editable_comp'] = True
if instance.department:
ret['department'] = {
"id": instance.department.id,
"code": instance.department.code,
......@@ -33,7 +33,7 @@ class ChangeRequestTemplateApproversSerializer(
ret['editable_dept'] = True
if instance.user:
user_object = {
"id": instance.user.id,
"name": instance.user.name,
......@@ -59,12 +59,13 @@ class ChangeRequestTemplateApproversSerializer(
else:
ret['editable_deleg'] = True
if instance.delegation.name.lower() == 'requestor':
ret['editable_user'] = False
ret['editable_comp'] = False
ret['editable_dept'] = False
ret['editable_deleg'] = False
if instance.delegation:
if instance.delegation.name.lower() == 'requestor' or instance.delegation.name.lower() == 'vendor/implementor':
ret['editable_user'] = False
ret['editable_comp'] = False
ret['editable_dept'] = False
ret['editable_deleg'] = False
return ret
except Exception as e:
......
......@@ -33,7 +33,7 @@ class ChangeRequestTemplatesSerializer(
many=True, read_only=True)
tmp_details = ChangeRequestTemplateDetailsSerializer(
many=True, read_only=True)
def to_representation(self, instance):
ret = super().to_representation(instance)
try:
......
......@@ -14,7 +14,8 @@ from app.applicationlayer.utils import (CustomPagination,
status_message_response)
from app.applicationlayer.cms.utils_cr import (
entity_log_bulk
entity_log_bulk,
delete_master_attachment_file
)
from app.applicationlayer.utils import model_to_dict
from app.entities import enums, models
......@@ -23,7 +24,9 @@ from django.db.models import Q
from app.applicationlayer.utils import log_save, CustomPagination
from rest_framework.exceptions import ParseError
from app.businesslayer.changerequest.change_request_template import (
tmp_add_edit_delete
tmp_add_edit_delete,
validation_approver_same_level,
validation_existing_vendor_requestor
)
from app.applicationlayer.management.account.serializer import ChangeRequestList
from app.applicationlayer.cms.template.approver.serializers import ChangeRequestTemplateApproversSerializer
......@@ -33,6 +36,7 @@ from app.applicationlayer.cms.template.attachment.serializers import ChangeReque
from app.applicationlayer.cms.template.header.serializers import ChangeRequestTemplatesSerializer
from app.applicationlayer.cms.template.header.serializers import ChangeRequestTemplatesSerializerList
from app.applicationlayer.cms.template.header.table_filters import HeaderFilterSet
from app.helper.decorators import *
# from django_filters import rest_framework as filters
......@@ -184,9 +188,10 @@ class ChangeRequestTemplatesViewset(viewsets.ModelViewSet):
return Response(e,
status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@TemplateValidation
@transaction.atomic
def partial_update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', True)
instance = self.get_object()
......@@ -339,16 +344,24 @@ class ChangeRequestTemplatesViewset(viewsets.ModelViewSet):
class ChangeRequestTemplatePost(APIView):
@TemplateValidation
@transaction.atomic()
def post(self, request):
template_header = request.data
try:
# Check if prefix already exists
prefix = models.ChangeRequestTemplateHeader.objects.filter(
requested_to_template_id=template_header['requested_to_template_id'])
if prefix:
return error_message('400', 'CR Number prefix already exists.',
'failed', status.HTTP_400_BAD_REQUEST)
data_list_approver = []
data_list_stake = []
data_list_attach = []
data_list_detail = []
template_header_data = {
'requested_to_template_name': template_header['requested_to_template_name'],
'requested_to_template_id': template_header['requested_to_template_id'],
......@@ -365,12 +378,6 @@ class ChangeRequestTemplatePost(APIView):
sp1 = transaction.savepoint() # nothing will save to db
# cr_prefix = request.data['requested_to_template_id'])
# models.ChangeRequestTemplateHeader.objects.filter(
# requested_to_template_id=cr_prefix
# )
serializer = ChangeRequestTemplatesSerializer(
data=template_header_data)
......@@ -385,7 +392,7 @@ class ChangeRequestTemplatePost(APIView):
for tmp_approver in tmp_approvers:
tmp_approver['template_no'] = tmp_id
data_list_approver.append(tmp_approver)
serializerApprover = ChangeRequestTemplateApproversSerializer(
data=data_list_approver, many=True)
......@@ -445,15 +452,25 @@ class ChangeRequestTemplatePost(APIView):
except ValidationError as e:
transaction.savepoint_rollback(sp1)
if template_header['tmp_attachments']:
delete_master_attachment_file(
template_header['tmp_attachments'])
message = {
'code': 400,
'status': 'failed',
'message': str(e),
}
return Response(message, status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
transaction.savepoint_rollback(sp1)
if template_header['tmp_attachments']:
delete_master_attachment_file(
template_header['tmp_attachments'])
message = {
'code': 500,
'status': 'failed',
......
......@@ -396,11 +396,9 @@ def next_approver_email(form_code, next_level):
level=str(next_level),
form_code=form_code
)
# print(next_approver.values())
# LOOP on next approver for sending email
for n_approver in next_approver:
# print(n_approver.delegation)
# NOTIF MSG FOR NEXT APPROVER
msg = APPROVER_MESSAGE.split(';')[0]
......@@ -564,7 +562,6 @@ def crhistory_log_bulk_delete_masterattach(queryset, entity, tbl, form_code,
try:
for data in queryset:
test = model_to_dict(data)
# print(test)
crhistory_save(batch_no,
main_action,
enums.CREnum.DELETED.value,
......@@ -822,4 +819,13 @@ def cancelled_user_trigger(form_code,
# create notification
notification_create(form_code, message, receiver_code,
sender_code, 'cms')
\ No newline at end of file
sender_code, 'cms')
def delete_master_attachment_file(attachments):
# delete master attachment data and media file attachments
for attachment in attachments:
attach = models.MasterAttachment.objects.filter(
id=attachment['file_upload'])
if attach:
attach.first().delete()
......@@ -25,10 +25,9 @@ class UserDownloadRequest(XLSXFileMixin, ReadOnlyModelViewSet):
# id_number = request.user.code
data = User.objects.all()
data = User.objects.all().exclude(id=1)
serializer = headers(data=data, many=True)
serializer.is_valid(raise_exception=False)
print(serializer.data)
return Response(serializer.data)
column_header = {
......
......@@ -10,6 +10,13 @@ from app.applicationlayer.management.module.serializer import ModuleSerializer
from app.entities.models import (
User, Department, UserImage, AllowedCompany, Application, Module
)
import os
import configparser
config = configparser.ConfigParser()
config_file = os.path.join('./', 'env.ini')
config.read(config_file)
class UserManagementRetreiveSerializer(serializers.ModelSerializer):
......@@ -79,9 +86,13 @@ class UserManagementRetreiveSerializer(serializers.ModelSerializer):
request = self.context.get('request')
primayPic = user.user_images.filter(is_primary=True).first()
ssl = config['SETTINGS']['SSL']
if primayPic:
path = request.build_absolute_uri(primayPic.image.url)
path = path.replace('http', 'https')
if ssl == "1" or ssl == 1:
path = path.replace('http', 'https')
else:
path = path.replace('https', 'http')
return path
else:
return request.build_absolute_uri('/media/no-user.png')
......
......@@ -55,6 +55,7 @@ class UserViewSet(viewsets.ModelViewSet):
'email', 'contact_no'
)
@rms.AccountValidation
@rms.user_create
@transaction.atomic
def create(self, request, *args, **kwargs):
......@@ -146,22 +147,35 @@ class UserViewSet(viewsets.ModelViewSet):
@transaction.atomic
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
new_instance = model_to_dict(instance)
UserHistory.objects.filter(username=instance.username).update(deleted=True)
AllowedCompany.objects.filter(id_number=instance.code).delete()
self.perform_destroy(instance)
try:
log_save(
enums.LogEnum.DELETED.value,
enums.LogEntitiesEnum.USER.value,
new_instance['id'],
new_instance,
''
)
instance = self.get_object()
new_instance = model_to_dict(instance)
UserHistory.objects.filter(username=instance.username).update(deleted=True)
AllowedCompany.objects.filter(id_number=instance.code).delete()
self.perform_destroy(instance)
log_save(
enums.LogEnum.DELETED.value,
enums.LogEntitiesEnum.USER.value,
new_instance['id'],
new_instance,
''
)
return Response(status=status.HTTP_204_NO_CONTENT)
return Response(status=status.HTTP_204_NO_CONTENT)
except IntegrityError as e:
error = f'Cant delete {instance.name} it has an existing transactions on either change request or change request template'
message = {
'code': 400,
'status': 'failed',
'message': error,
}
return Response(message,
status=status.HTTP_400_BAD_REQUEST)
@rms.AccountValidation
@rms.user_create
@transaction.atomic
def update(self, request, *args, **kwargs):
......@@ -185,9 +199,18 @@ class UserViewSet(viewsets.ModelViewSet):
if cms_form.count() > 0 or cms_template.count() > 0:
raise ParseError(
'Cannot update this record the user has a record on change request it might cause a data error'
)
# raise ParseError(
# 'Cannot update this record the user has a record on change request it might cause a data error'
# )
error = 'Cannot update this record the user has a record on change request it might cause a data error'
message = {
'code': 400,
'status': 'failed',
'message': error,
}
return Response(message,
status=status.HTTP_400_BAD_REQUEST)
serializer = self.get_serializer(
instance, data=request.data, partial=partial
......@@ -272,7 +295,15 @@ class UserViewSet(viewsets.ModelViewSet):
else:
raise Exception('User not found')
# raise Exception('User not found')
error = 'User not found'
message = {
'code': 400,
'status': 'failed',
'message': error,
}
return Response(message,
status=status.HTTP_400_BAD_REQUEST)
return Response(
{"detail": "Success"},
......@@ -296,7 +327,16 @@ class UserViewSet(viewsets.ModelViewSet):
form = request.data
if form['new_password'] != form['new_password_confirm']:
raise Exception('Passwords must match')
# raise Exception('Passwords must match')
error = 'Passwords must match'
message = {
'code': 400,
'status': 'failed',
'message': error,
}
return Response(message,
status=status.HTTP_400_BAD_REQUEST)
existingUser = User.objects.filter(code=code)
pk = existingUser.values().first()['id']
......@@ -322,7 +362,15 @@ class UserViewSet(viewsets.ModelViewSet):
status=status.HTTP_200_OK
)
else:
raise Exception('User not found')
# raise Exception('User not found')
error = 'User not found'
message = {
'code': 400,
'status': 'failed',
'message': error,
}
return Response(message,
status=status.HTTP_400_BAD_REQUEST)
else:
serialized.is_valid(raise_exception=True)
......@@ -373,7 +421,15 @@ class UserViewSet(viewsets.ModelViewSet):
status=status.HTTP_200_OK
)
else:
raise Exception('User not found')
# raise Exception('User not found')
error = 'User not found'
message = {
'code': 400,
'status': 'failed',
'message': error,
}
return Response(message,
status=status.HTTP_400_BAD_REQUEST)
else:
serialized.is_valid(raise_exception=True)
......@@ -412,5 +468,13 @@ class UserViewSet(viewsets.ModelViewSet):
status=status.HTTP_201_CREATED,
headers=headers)
else:
raise ParseError('User not found')
# raise ParseError('User not found')
error = 'User not found'
message = {
'code': 400,
'status': 'failed',
'message': error,
}
return Response(message,
status=status.HTTP_400_BAD_REQUEST)
return Response(data={"detail": "Success"})
......@@ -13,6 +13,7 @@ from app.applicationlayer.utils import (
from django_filters.rest_framework import DjangoFilterBackend
from app.applicationlayer.management.application import serializer
from app.applicationlayer.management.application.table_filters import ApplicationFilterSet
from django.db import IntegrityError
class ApplicationViewSet(viewsets.ModelViewSet):
......@@ -26,6 +27,7 @@ class ApplicationViewSet(viewsets.ModelViewSet):
search_fields = ('name', 'code')
@decorators.rms.ApplicationValidation
@decorators.rms.application_crate
@transaction.atomic
def create(self, request, *args, **kwargs):
......@@ -81,25 +83,32 @@ class ApplicationViewSet(viewsets.ModelViewSet):
return Response(status=status.HTTP_204_NO_CONTENT)
@decorators.rms.ApplicationValidation
@decorators.rms.application_crate
@transaction.atomic
def update(self, request, *args, **kwargs):
try:
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,
old_instance['id'],
old_instance,
new_instance
)
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,
old_instance['id'],
old_instance,
new_instance
)
return Response(serializer.data)
return Response(serializer.data)
except IntegrityError as e:
return Response(
{"message": "Cannot delete or update this reocrd it has foreign key constraint to other tables"},
status=status.HTTP_400_BAD_REQUEST
)
......@@ -292,18 +292,20 @@ class BatchUploadViewSet(viewsets.ModelViewSet):
return self.get_paginated_response(message)
@transaction.atomic
# @transaction.atomic
def create(self, request, **kwargs):
# sp1 = transaction.savepoint() # nothing will save to db
csv_file = request.FILES['file']
extension_file = str(csv_file).split('.')[1]
if extension_file.lower() != 'csv':
return Response(
{"message": "Only csv extension file is allowed"},
status=status.HTTP_400_BAD_REQUEST
)
df = pd.read_csv(csv_file, sep=',', skip_blank_lines=True).dropna()
# df.dropna()
df = pd.read_csv(csv_file, sep=',', skip_blank_lines=True)
df.dropna()
logged_user_type = request.user.user_type
logged_user_company = request.user.department.company.name
logged_user_department = request.user.department.name
......@@ -340,7 +342,8 @@ class BatchUploadViewSet(viewsets.ModelViewSet):
Q(company=user_company)
)
if not request_department:
# raise ParseError(company_error)
etl2.delete()
# transaction.savepoint_rollback(sp1)
return Response(
{"message": company_error},
# {"message": str(e)},
......@@ -349,6 +352,8 @@ class BatchUploadViewSet(viewsets.ModelViewSet):
elif request.user.user_type == enums_department:
if keys['Department_Code'] != request.user.department.code:
etl2.delete()
# transaction.savepoint_rollback(sp1)
return Response(
{"message": department_error},
# {"message": str(e)},
......@@ -429,10 +434,11 @@ class BatchUploadViewSet(viewsets.ModelViewSet):
code=privilege_department_code
)
ccr = True if keys['Create_CR'].lower() == 'yes' else False
crt = True if keys['Create_Template'].lower() == 'yes' else False
view_all = True if keys['View_All_CR'].lower() == 'yes' else False
approve_cr = True if keys['Approve_CR'].lower() == 'yes' else False
ccr = True if str(keys['Create_CR']).lower() == 'yes' else False
crt = True if str(keys['Create_Template']).lower() == 'yes' else False
view_all = True if str(keys['View_All_CR']).lower() == 'yes' else False
approve_cr = True if str(keys['Approve_CR']).lower() == 'yes' else False
privilege_object = {
"id_number": current_user,
......@@ -447,6 +453,8 @@ class BatchUploadViewSet(viewsets.ModelViewSet):
AllowedCompany.objects.create(**privilege_object)
except IntegrityError as e:
etl2.delete()
# transaction.savepoint_rollback(sp1)
return Response(
{"message": f"Duplicate user privilege at row {data + 2}"},
# {"message": str(e)},
......@@ -454,26 +462,32 @@ class BatchUploadViewSet(viewsets.ModelViewSet):
)
except ObjectDoesNotExist as e:
etl2.delete()
# transaction.savepoint_rollback(sp1)
return Response(
{"message": f"Department Does not Exist at Privilege row {data + 2}"},
status=status.HTTP_400_BAD_REQUEST
)
except IntegrityError as e:
# etl2.delete()
# transaction.set_rollback(True)
etl2.delete()
# transaction.savepoint_rollback(sp1)
return Response(
{"message": f"Record already exist at row {data + 2}"},
status=status.HTTP_400_BAD_REQUEST
)
except KeyError as e:
etl2.delete()
# transaction.savepoint_rollback(sp1)
return Response(
{"message": f"Missing column {e.args[0]}"},
status=status.HTTP_400_BAD_REQUEST
)
except ObjectDoesNotExist as e:
etl2.delete()
# transaction.savepoint_rollback(sp1)
return Response(
{"message": f"Department Does not Exist at row {data + 2}"},
status=status.HTTP_400_BAD_REQUEST
......
......@@ -17,6 +17,17 @@ import json
REALTIMESERVER_IP = settings.REALTIMESERVER_IP
def error_message(code, message, status, status_code):
return Response(
{
"code": code,
"message": message,
"status": status
},
status=status_code
)
def model_to_dict(instance):
try:
mySerializer = copy.deepcopy(DynamicSerializer)
......@@ -37,7 +48,7 @@ class DynamicSerializer(serializers.ModelSerializer):
class CustomPagination(PageNumberPagination):
page_size = 10
max_page_size = 50
max_page_size = 1000
page_query_param = 'page'
page_size_query_param = 'page_size'
......
......@@ -765,22 +765,4 @@ def cr_routing_actions(approver_instance, current_user, move_to_level):
reset_autoemail_tables(form_code)
return True
return True
\ No newline at end of file
......@@ -20,6 +20,9 @@ from app.entities import enums, models
from app.applicationlayer.utils import log_save, CustomPagination
from app.applicationlayer.cms.template import serializers
import itertools
from operator import itemgetter
def tmp_add_edit_delete(tmp_request_body,
queryset,
......@@ -101,3 +104,90 @@ def tmp_add_edit_delete(tmp_request_body,
)
return True
# Check if routing table has Vendor and Requestor
def validation_existing_vendor_requestor(approvers):
approvers_data = sorted(approvers,
key=itemgetter('level'))[-2:]
if (approvers_data[0]['delegation'] == 'DELEGATION-20191119-0000002' and
approvers_data[1]['delegation'] == 'DELEGATION-20191119-0000001'):
return True
else:
return False
# Check if routing table has atleast 1 approver
def validation_existing_approver(approvers):
counter = 0
for approver in approvers:
# count all delegation not equal to Requestor and Vendor
if approver['delegation'] not in ['DELEGATION-20191119-0000002',
'DELEGATION-20191119-0000001']:
counter = counter + 1
return counter
return counter
# Check if a user has multiple same level in routing table
def validation_approver_same_level(approvers):
data_list_appr = []
for approver in approvers:
if 'user' in approver and 'level' in approver:
if not approver['user'] is None:
data_list_appr.append(approver)
# add checking
approvers_data = sorted(data_list_appr,
key=itemgetter('level', 'user'))
for key, value in itertools.groupby(approvers_data,
key=itemgetter('level', 'user')):
count_user_same_level = 0
for i in value:
count_user_same_level = count_user_same_level + 1
user_code = i.get('user')
if count_user_same_level > 1:
user = models.User.objects.get(code=user_code)
user_name = user.name
return user_name
return None
# Check if poc is assigned to another delegation other than Vendor
def validation_poc_vendor_only(poc, approvers):
validate = False
for approver in approvers:
if 'user' in approver and 'delegation' in approver:
if poc == approver['user']:
if not approver['delegation'] == 'DELEGATION-20191119-0000002':
validate = True
return validate
# Check if level if Vendor delegation has same level with other delegation
def validation_vendor_unique_level(approvers):
validate = 0
data_level = []
for approver in approvers:
if 'delegation' in approver:
if approver['delegation'] == 'DELEGATION-20191119-0000002':
data_level.append(approver['level'])
for approver in approvers:
if 'delegation' in approver:
if not approver['delegation'] is None:
if approver['level'] in data_level:
if not approver['delegation'] == 'DELEGATION-20191119-0000002':
validate = approver['level']
return validate
......@@ -13,11 +13,9 @@ def custom_exception_handler(exc, context):
# Update the structure of the response data.
if response is not None:
print('dd')
error_message = {}
for key, value in response.data.items():
print(value)
if type(value) == list and value[0].code == 'blank':
value = value[0].replace('This field', key)
# elif type(value) == dict:
......
# Generated by Django 2.2 on 2020-02-05 17:07
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('entities', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='changerequestformattachments',
name='file_upload',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.PROTECT, related_name='form_attachments', to='entities.MasterAttachment'),
preserve_default=False,
),
migrations.AlterField(
model_name='changerequesttemplateattachments',
name='file_upload',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.PROTECT, related_name='template_attachments', to='entities.MasterAttachment'),
preserve_default=False,
),
]
# Generated by Django 2.2 on 2020-02-06 14:22
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('entities', '0002_auto_20200205_1707'),
]
operations = [
migrations.RemoveField(
model_name='changerequestformheader',
name='company_desc',
),
migrations.RemoveField(
model_name='changerequestformheader',
name='department_desc',
),
migrations.RemoveField(
model_name='changerequestformheader',
name='requested_desc',
),
]
......@@ -266,9 +266,7 @@ class ExtractTransformLoad(AuditClass):
def save(self, *args, **kwargs):
super(ExtractTransformLoad, self).save(*args, **kwargs)
code = number_generator(enums.GenerateCode.ETL.value, self.id)
print(type(self.code))
if self.code == '' or self.code == None:
self.code = code
self.save()
......@@ -527,7 +525,6 @@ class MasterAttachment(models.Model):
attch_ref = models.TextField()
def delete(self,*args,**kwargs):
# print(self.url.name)
if os.path.isfile(self.url.path):
os.remove(self.url.path)
......@@ -707,9 +704,7 @@ class ChangeRequestTemplateAttachments(BaseAttachment):
file_upload = models.ForeignKey(
MasterAttachment,
on_delete=models.PROTECT,
related_name='template_attachments',
blank=True,
null=True
related_name='template_attachments'
)
template_no = models.ForeignKey(
ChangeRequestTemplateHeader,
......@@ -786,18 +781,6 @@ class ChangeRequestFormHeader(BaseHeader):
on_delete=models.PROTECT,
to_field='template_no')
status = models.CharField(max_length=50)
company_desc = models.CharField(
max_length=255,
null=True,
blank=True)
department_desc = models.CharField(
max_length=255,
null=True,
blank=True)
requested_desc = models.CharField(
max_length=255,
null=True,
blank=True)
requested_to_template_id = models.CharField(
max_length=255)
requested_to_target_date = models.DateTimeField(
......@@ -819,6 +802,18 @@ class ChangeRequestFormHeader(BaseHeader):
self.form_code = code
self.save()
# company_desc = models.CharField(
# max_length=255,
# null=True,
# blank=True)
# department_desc = models.CharField(
# max_length=255,
# null=True,
# blank=True)
# requested_desc = models.CharField(
# max_length=255,
# null=True,
# blank=True)
class ChangeRequestFormApprovers(BaseApprover):
code = models.CharField(
......@@ -936,9 +931,7 @@ class ChangeRequestFormAttachments(BaseAttachment):
file_upload = models.ForeignKey(
MasterAttachment,
on_delete=models.PROTECT,
related_name='form_attachments',
blank=True,
null=True
related_name='form_attachments'
)
class Meta:
......@@ -1192,7 +1185,7 @@ class OverdueTrigger(models.Model):
class Meta:
db_table = 'trigger_overdue'
# comment
"""
**********************
*** AMS TABLES ***
......
This diff is collapsed.
......@@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
import configparser
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(
......@@ -25,10 +26,10 @@ BASE_DIR = os.path.dirname(
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 = []
DEBUG = False
ALLOWED_HOSTS = ['*']
CORS_ORIGIN_ALLOW_ALL = True
# Application definition
......@@ -46,7 +47,6 @@ INSTALLED_APPS = [
'app.accesslayer',
'app.entities',
'channels',
]
MIDDLEWARE = [
......@@ -128,7 +128,7 @@ 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
......@@ -159,19 +159,6 @@ REST_FRAMEWORK = {
'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 = 'rms.noreply@oneberrysystem.com'
# EMAIL_TEMPLATES_ROOT = os.path.join(BASE_DIR, "app/helper/email_service/templates")
EMAIL_TEMPLATES_ROOT = os.path.join(BASE_DIR, "app/helper/email_service/templates")
EMAIL_HOST = 'email-smtp.us-west-2.amazonaws.com'
......@@ -182,3 +169,62 @@ EMAIL_USE_SSL = False
EMAIL_USE_TLS = True
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_DEFAULT_SENDER = 'noreply@rms-hub.com'
###########################################################################
# config
#########################################################################
config = configparser.ConfigParser()
config_file = os.path.join('./', 'env.ini')
config.read(config_file)
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('172.17.0.1', 6379)],
# "hosts": [('127.0.0.1', 6379)],
},
},
}
DATABASES = {
'default': {
'ENGINE': config['SETTINGS']['DATABASE_ENGINE'],
'NAME': config['SETTINGS']['DATABASE_NAME'],
'USER': config['SETTINGS']['DATABASE_USER'],
'PASSWORD': config['SETTINGS']['DATABASE_PASSWORD'],
'HOST': config['SETTINGS']['DATABASE_HOST'],
'PORT': config['SETTINGS']['DATABASE_PORT'],
}
}
# ****************
# PROGRAM SETTINGS
# ****************
SESSION_TIMEOUT = config['SETTINGS']['SESSION_TIMEOUT']
FRONT_END_URL = config['SETTINGS']['FRONT_END_URL']
AUTH_ACCESSS_TOKEN_TIMEOUT = config['SETTINGS']['AUTH_ACCESSS_TOKEN_TIMEOUT']
USER_DEFAULT_PASSWORD = config['SETTINGS']['USER_DEFAULT_PASSWORD']
REALTIMESERVER_IP = config['SETTINGS']['REALTIMESERVER_IP']
# Notification Messages
APPROVER_MESSAGE = config['NOTIFICATION_EMAIL']['APPROVER_MESSAGE']
REQUESTOR_MESSAGE = config['NOTIFICATION_EMAIL']['REQUESTOR_MESSAGE']
REQUESTOR_REJECT_MESSAGE = config['NOTIFICATION_EMAIL']['REQUESTOR_REJECT_MESSAGE']
VENDOR_ACKNOWLEDGE_MESSAGE = config['NOTIFICATION_EMAIL']['VENDOR_ACKNOWLEDGE_MESSAGE']
REQUESTOR_ACKNOWLEDGE_MESSAGE = config['NOTIFICATION_EMAIL']['REQUESTOR_ACKNOWLEDGE_MESSAGE']
REQUESTOR_COMPLETION_MESSAGE = config['NOTIFICATION_EMAIL']['REQUESTOR_COMPLETION_MESSAGE']
VENDOR_ACCEPTANCE_MESSAGE = config['NOTIFICATION_EMAIL']['VENDOR_ACCEPTANCE_MESSAGE']
VENDOR_REJECT_MESSAGE = config['NOTIFICATION_EMAIL']['VENDOR_REJECT_MESSAGE']
REVISED_MESSAGE = config['NOTIFICATION_EMAIL']['REVISED_MESSAGE']
CANCEL_MESSAGE = config['NOTIFICATION_EMAIL']['CANCEL_MESSAGE']
APPROVER_REJECT_MESSAGE = config['NOTIFICATION_EMAIL']['APPROVER_REJECT_MESSAGE']
#ADMIN PROFILE
CATCH_EMAIL = config['SETTINGS']['CATCH_EMAIL']
CR_FRONT_LINK = config['SETTINGS']['CR_LINK']
......@@ -14,8 +14,8 @@ CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
# "hosts": [('172.17.0.1', 6379)],
"hosts": [('127.0.0.1', 6379)],
"hosts": [('172.17.0.1', 6379)],
# "hosts": [('127.0.0.1', 6379)],
},
},
}
......
......@@ -14,8 +14,8 @@ CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
# "hosts": [('172.17.0.1', 6379)],
"hosts": [('127.0.0.1', 6379)],
"hosts": [('172.17.0.1', 6379)],
# "hosts": [('127.0.0.1', 6379)],
},
},
}
......
......@@ -13,8 +13,8 @@ CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
# "hosts": [('172.17.0.1', 6379)],
"hosts": [('127.0.0.1', 6379)],
"hosts": [('172.17.0.1', 6379)],
# "hosts": [('127.0.0.1', 6379)],
},
},
}
......
......@@ -13,8 +13,8 @@ CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
# "hosts": [('172.17.0.1', 6379)],
"hosts": [('127.0.0.1', 6379)],
"hosts": [('172.17.0.1', 6379)],
# "hosts": [('127.0.0.1', 6379)],
},
},
}
......
version: '3'
services:
web:
image: dev-rmsv2:latest
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "7020:8000"
container_name: dev_rmsv2_api_container
restart: always
[SETTINGS]
BATCH_UPLOAD_FORMAT_FILENAME = instruction.pdf
SSL = 1
DATABASE_ENGINE = django.db.backends.mysql
DATABASE_NAME = rms_db
DATABASE_USER = red_database
DATABASE_PASSWORD = password123
DATABASE_HOST = 10.0.75.1
DATABASE_PORT = 3306
SESSION_TIMEOUT = 30
FRONT_END_URL = http://devweb.rmsv2.oneberrysystem.com
AUTH_ACCESSS_TOKEN_TIMEOUT = 3600
USER_DEFAULT_PASSWORD = password
CATCH_EMAIL = gladys@tirsolutions.com
CR_LINK = http://localhost:8000/cms/change-request/form/view
REALTIMESERVER_IP = 127.0.0.1:8000
[NOTIFICATION_EMAIL]
APPROVER_MESSAGE = has sent you an APPROVAL REQUEST for change request;RMS-ACTIONREQUIRED
REQUESTOR_MESSAGE = has APPROVED the change request;RMS-CRAPPROVED
REQUESTOR_REJECT_MESSAGE = has REJECTED the change request;RMS-CRREJECTED
VENDOR_ACKNOWLEDGE_MESSAGE = has sent you an ACKNOWLEDGEMENT REQUEST for change request;RMS-ACTIONREQUIRED-VENDOR
REQUESTOR_ACKNOWLEDGE_MESSAGE = has ACKNOWLEDGED the change request;RMS-CRACKNOWLEDGE
REQUESTOR_COMPLETION_MESSAGE = has COMPLETED the change request;RMS-CRCOMPLETED
VENDOR_ACCEPTANCE_MESSAGE = has ACCEPTED the change request;RMS-CRACCEPTED
VENDOR_REJECT_MESSAGE = has REJECTED the change request;RMS-CRREJECTED-VENDOR
REVISED_MESSAGE = has REJECTED the change request for your revision;RMS-CRREVISED
CANCEL_MESSAGE = has CANCELLED the change request;RMS-CRCANCELLED-USERTRIGGER
APPROVER_REJECT_MESSAGE = has REJECTED the change request for your approval;RMS-CRREJECTED-APPROVER
......@@ -10,7 +10,7 @@ config.read(config_file)
if __name__ == "__main__":
os.environ.setdefault('DJANGO_SETTINGS_MODULE',
config['SETTINGS']['CONFIG'])
'config.settings.base')
# os.system('start chrome.exe --kiosk --kiosk-printing
# http://localhost:8000/')
try:
......
......@@ -18,4 +18,5 @@ docker run -d --restart=always -p 3001:3000 sit_rms_webv2 npm start
Clear Cache REDIS
docker exec -it container-name redis-cli FLUSHALL
config set stop-writes-on-bgsave-error no
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