Commit 82e58763 authored by John Red Medrano's avatar John Red Medrano

Merge pull request #539 in RMS/api-main-service from RMSv2 to staging

* commit '015f53ef': (127 commits)
  add order by on etl endpoint descending order
  email to admin upon bulk create user
  body
  sender body batch email admin
  batch email admin
  requested to user comp and dept details
  batch upload exception
  select_related
  select_related
  try select_related
  vendor email
  approver reject message
  approver msg
  update reject template approver
  replace error at CUA upload user
  replace error key from detail to message to fix the bug on upload users
  updating my copy
  fix route back
  bug fix 2
  bug fix
  ...
parents f56a247c 015f53ef
......@@ -20,7 +20,10 @@ from django.db import IntegrityError
class AllowedCompanyViewSet(viewsets.ModelViewSet):
queryset = AllowedCompany.objects.all()
# queryset = AllowedCompany.objects.all()
queryset = AllowedCompany.objects.select_related(
'id_number', 'company_pivot', 'group_pivots'
).all()
serializer_class = AllowedCompanySerializer
pagination_class = CustomPagination
lookup_field = 'code'
......@@ -85,7 +88,6 @@ class AllowedCompanyViewSet(viewsets.ModelViewSet):
return Response(message, status=status.HTTP_400_BAD_REQUEST)
except IntegrityError as e:
print(str(e))
error = 'Adding the same Department under the same Company is not allowed'
message = {
'code': 400,
......@@ -96,8 +98,6 @@ class AllowedCompanyViewSet(viewsets.ModelViewSet):
status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
# print(str(e))
# error = 'adding the same departments under same Company is not allowed'
message = {
'code': 500,
'status': 'failed',
......
......@@ -10,11 +10,14 @@ from django.conf import settings
from datetime import timedelta
from app.helper.email_service import sender
from app.applicationlayer.utils import main_threading
from rest_framework.permissions import AllowAny
CR_FRONT_LINK = settings.CR_FRONT_LINK
class CancelTriggerAPIView(views.APIView):
permission_classes = (AllowAny,)
def get(self, request):
date_now = datetime.now()
today_mail = models.CancelTrigger.objects.filter(
......
......@@ -10,28 +10,32 @@ from django.conf import settings
from datetime import timedelta
from app.helper.email_service import sender
from app.applicationlayer.utils import main_threading
from rest_framework.permissions import AllowAny
CR_FRONT_LINK = settings.CR_FRONT_LINK
class OverdueTriggerAPIView(views.APIView):
permission_classes = (AllowAny,)
def get(self, request):
date_now = datetime.now()
today_mail = models.CancelTrigger.objects.filter(
Q(auto_cancel_date=date_now.strftime('%Y-%m-%d 00:00:00.000'))
today_mail = models.OverdueTrigger.objects.filter(
Q(overdue_date=date_now.strftime('%Y-%m-%d 00:00:00.000')) &
Q(is_sent=False)
)
list_of_emails = []
for data in today_mail:
if data.is_sent == False and data.form_code.status == 'Pending' and data.frm_approver.is_action == True:
if data.is_sent == False and (data.form_code.status == 'Pending' or
data.form_code.status == 'Approved' or
data.form_code.status == 'Rejected'):
cr_link = f'{CR_FRONT_LINK}/{data.form_code}'
requestor_name = data.form_code.requested_by_user.name
auto_cancel_date = data.auto_cancel_date.strftime('%B %d, %Y')
date_submitted_last_approver = data.date_submitted_last_approver.strftime('%B %d, %Y')
approver_pending_action = data.frm_approver.user.name
target_date = data.form_code.requested_to_target_date.strftime('%B %d, %Y')
cr_number = data.form_code.requested_to_template_id
cr_name = data.form_code.requested_to_template_name
company_requestedto = data.form_code.requested_to_company.name
......@@ -42,17 +46,12 @@ class OverdueTriggerAPIView(views.APIView):
requestor_recipient = data.form_code.requested_by_user.email
admin = 'Test'
args_requestor = [requestor_name, auto_cancel_date,
date_submitted_last_approver, approver_pending_action,
args_requestor = [requestor_name, target_date,
cr_number, cr_name, company_requestedto,
department_requestedto, priority_level, form_status, url,
requestor_recipient, admin]
main_threading(args_requestor, sender.routing_table_cancelled)
cancel = models.ChangeRequestFormHeader.objects.filter(
form_code=data.form_code
).update(status='Cancelled')
main_threading(args_requestor, sender.routing_table_overdue)
list_of_emails.append(data.form_code.form_code)
......
......@@ -10,11 +10,14 @@ from django.conf import settings
from datetime import timedelta
from app.helper.email_service import sender
from app.applicationlayer.utils import main_threading
from rest_framework.permissions import AllowAny
CR_FRONT_LINK = settings.CR_FRONT_LINK
class ReminderTriggerAPIView(views.APIView):
permission_classes = (AllowAny,)
def get(self, request):
date_now = datetime.now()
next_day = date_now + timedelta(days=1)
......@@ -23,10 +26,10 @@ class ReminderTriggerAPIView(views.APIView):
Q(date_to__lte=date_now.strftime('%Y-%m-%d 00:00:00.000')) &
Q(date_to_send=date_now.strftime('%Y-%m-%d 00:00:00.000'))
)
# print(today_mail)
list_of_emails = []
for data in today_mail:
if data.frm_approver.is_action == True:
if data.frm_approver.is_action == True and data.form_code.status == 'Pending':
# common details
cr_link = f'{CR_FRONT_LINK}/{data.frm_approver.form_code}'
......
......@@ -8,6 +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,
......@@ -28,32 +29,53 @@ class ChangeRequestFormApproversSerializer(
"contact_no": instance.user.contact_no
}
ret['user'] = user_object
ret['delegation'] = {
"id": instance.delegation.id,
"code": instance.delegation.code,
"name": instance.delegation.name
}
if instance.form_code.status == 'Draft':
if instance.tmp_approver:
if instance.tmp_approver.user or instance.tmp_approver.delegation.lower() == 'requestor':
if instance.tmp_approver.user or instance.tmp_approver.delegation.name.lower() == 'requestor':
ret['editable_user'] = False
else:
ret['editable_user'] = True
if instance.tmp_approver.company or instance.tmp_approver.delegation.lower() == 'requestor':
if instance.tmp_approver.company or instance.tmp_approver.delegation.name.lower() == 'requestor':
ret['editable_comp'] = False
else:
ret['editable_comp'] = True
if instance.tmp_approver.department or instance.tmp_approver.delegation.lower() == 'requestor':
if instance.tmp_approver.department or instance.tmp_approver.delegation.name.lower() == 'requestor':
ret['editable_dept'] = False
else:
ret['editable_dept'] = True
# not instance.tmp_approver.delegation.code or
if instance.tmp_approver.delegation:
ret['editable_deleg'] = False
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
else:
ret['editable_user'] = True
ret['editable_comp'] = True
ret['editable_dept'] = True
ret['editable_deleg'] = True
else:
ret['editable_user'] = False
ret['editable_comp'] = False
ret['editable_dept'] = False
ret['editable_deleg'] = False
return ret
......@@ -61,13 +83,14 @@ class ChangeRequestFormApproversSerializer(
if instance.form_code.status == 'Draft':
if instance.tmp_approver:
if instance.tmp_approver.user or instance.tmp_approver.delegation.lower() == 'requestor':
if instance.tmp_approver.user or instance.tmp_approver.delegation.name.lower() == 'requestor':
ret['editable_user'] = False
else:
ret['user'] = None
ret['editable_user'] = True
if instance.tmp_approver.company or instance.tmp_approver.delegation.lower() == 'requestor':
if instance.tmp_approver.company or instance.tmp_approver.delegation.name.lower() == 'requestor':
ret['company'] = {
"id": instance.tmp_approver.company.id,
"code": instance.tmp_approver.company.code,
......@@ -79,7 +102,7 @@ class ChangeRequestFormApproversSerializer(
ret['company'] = None
ret['editable_comp'] = True
if instance.tmp_approver.department or instance.tmp_approver.delegation.lower() == 'requestor':
if instance.tmp_approver.department or instance.tmp_approver.delegation.name.lower() == 'requestor':
ret['department'] = {
"id": instance.tmp_approver.department.id,
"code": instance.tmp_approver.department.code,
......@@ -90,14 +113,35 @@ class ChangeRequestFormApproversSerializer(
ret['department'] = None
ret['editable_dept'] = True
if instance.tmp_approver.delegation:
ret['delegation'] = {
"id": instance.tmp_approver.delegation.id,
"code": instance.tmp_approver.delegation.code,
"name": instance.tmp_approver.delegation.name
}
ret['editable_deleg'] = False
else:
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
else:
ret['editable_user'] = True
ret['editable_comp'] = True
ret['editable_dept'] = True
ret['editable_deleg'] = True
else:
ret['editable_user'] = False
ret['editable_comp'] = False
ret['editable_dept'] = False
ret['editable_deleg'] = False
return ret
......
......@@ -13,7 +13,10 @@ from app.applicationlayer.utils import (
class ChangeRequestFormApproversViewset(viewsets.ModelViewSet):
queryset = models.ChangeRequestFormApprovers.objects.all().order_by('level')
# queryset = models.ChangeRequestFormApprovers.objects.all().order_by('level')
queryset = models.ChangeRequestFormApprovers.objects.select_related(
'form_code', 'tmp_approver'
).all().order_by('level')
serializer_class = serializers.ChangeRequestFormApproversSerializer
pagination_class = CustomPagination
lookup_field = 'code'
......
......@@ -12,7 +12,10 @@ from app.applicationlayer.utils import (
class ChangeRequestFormAttachmentsViewset(viewsets.ModelViewSet):
queryset = models.ChangeRequestFormAttachments.objects.all()
# queryset = models.ChangeRequestFormAttachments.objects.all()
queryset = models.ChangeRequestFormAttachments.objects.select_related(
'form_code', 'file_upload'
).all()
serializer_class = serializers.ChangeRequestFormAttachmentsSerializer
pagination_class = CustomPagination
lookup_field = "code"
......
......@@ -13,7 +13,10 @@ from app.applicationlayer.utils import (
class ChangeRequestFormDetailsViewset(viewsets.ModelViewSet):
queryset = models.ChangeRequestFormDetails.objects.all()
# queryset = models.ChangeRequestFormDetails.objects.all()
queryset = models.ChangeRequestFormDetails.objects.select_related(
'form_code'
).all()
serializer_class = serializers.ChangeRequestFormDetailsSerializer
pagination_class = CustomPagination
lookup_field = "code"
......
......@@ -38,7 +38,6 @@ class headers(serializers.ModelSerializer):
ret['created'] = instance.created.strftime('%Y-%m-%d-%H:%M:%S')
ret['action'] = approver
# ret['requested_to_target_date'] = instance.requested_to_target_date.strftime('%Y-%m-%d-%H:%M:%S')
print(ret)
return ret
# except Exception as e:
# ret['action_required'] = "No"
......
......@@ -93,19 +93,18 @@ class ChangeRequestFormHeaderSerializer(
ret['requested_to_company'] = "None"
ret['requested_to_department'] = "None"
ret['requested_to_user'] = "None"
ret['requested_by_user'] ="None"
ret['requested_by_user'] = "None"
ret['requested_by_department'] = "None"
ret['template_object'] = "None"
return ret
# 'company_desc', 'department_desc', 'requested_desc',
class Meta:
model = models.ChangeRequestFormHeader
# fields = '__all__'
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',
......
......@@ -5,13 +5,14 @@ from app.entities.models import ChangeRequestFormHeader
class HeaderFilterSet(filters.FilterSet):
# action_required = filters.CharFilter(method='action_required_bar')
class Meta:
model = ChangeRequestFormHeader
fields = '__all__'
# def action_required_bar(self, queryset, name, value):
# return queryset.filter(
# Q(title__icontains=value) |
# Q(name__icontains=value) |
# Q(description__icontains=value)
# )
class Meta:
model = ChangeRequestFormHeader
fields = '__all__'
import configparser
import shutil
import os
from django.shortcuts import render
from rest_framework import viewsets
from rest_framework.views import APIView
......@@ -30,7 +33,9 @@ from app.applicationlayer.cms.utils_cr import (number_generator,
generate_template_id,
crhistory_create_save,
entity_log_bulk,
reminder_trigger_save)
reminder_trigger_save,
overdue_trigger_save,
reset_autoemail_tables)
from app.entities import enums
from app.applicationlayer.utils import model_to_dict
......@@ -62,6 +67,17 @@ from django_filters.rest_framework import DjangoFilterBackend
import json
from app.applicationlayer.utils import main_threading
from django.core.files.base import ContentFile
from django.conf import settings
from io import BytesIO
from django.http import HttpResponse
from xhtml2pdf import pisa
config = configparser.ConfigParser()
config_file = os.path.join('./', 'env.ini')
config.read(config_file)
APPROVER_MESSAGE = settings.APPROVER_MESSAGE
REQUESTOR_MESSAGE = settings.REQUESTOR_MESSAGE
REQUESTOR_REJECT_MESSAGE = settings.REQUESTOR_REJECT_MESSAGE
......@@ -74,7 +90,10 @@ VENDOR_REJECT_MESSAGE = settings.VENDOR_REJECT_MESSAGE
class ChangeRequestFormsViewset(viewsets.ModelViewSet):
queryset = models.ChangeRequestFormHeader.objects.all()
queryset = models.ChangeRequestFormHeader.objects.select_related(
'requested_by_user', 'requested_by_department', 'template_no'
).all()
# queryset = models.ChangeRequestFormHeader.objects.all()
serializer_class = ChangeRequestFormHeaderSerializer
pagination_class = CustomPagination
lookup_field = 'form_code'
......@@ -200,6 +219,22 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
overdue = overdue_filtered.count()
# server side computations
# status_total = pending + approved + rejected + cancelled + completed
# close = rejected + cancelled + completed
# opened = pending + approved
# open_percent = round((opened/status_total) * 100)
# close_percent = round((close/status_total) * 100)
# priority_total = high + normal
# high_percent = round((high/priority_total) * 100)
# normal_percent = round((normal/priority_total) * 100)
message = {
'account_no': id_number,
'pending': pending,
......@@ -211,6 +246,10 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
'normal': normal,
'awaiting': awaiting,
'overdue': overdue,
# 'open_percent': open_percent,
# 'close_percent': close_percent,
# 'high_percent': high_percent,
# 'normal_percent': normal_percent,
'code': 200,
'status': 'success',
'message': 'Dashboard Summary'
......@@ -374,21 +413,21 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
# queryset = self.get_serializer_class().setup_eager_loading(self.queryset)
models.Notification.objects.filter(
account_no=id_number,
form_code=form_code,
is_read=False).update(is_read=True)
# models.Notification.objects.filter(
# account_no=id_number,
# form_code=form_code,
# is_read=False).update(is_read=True)
ROOM = id_number
SENDER = id_number
# ROOM = id_number
# SENDER = id_number
notif = send_broadcast_message(
ROOM,
SENDER,
'UPDATE NOTIFICATIONS'
)
# notif = send_broadcast_message(
# ROOM,
# SENDER,
# 'UPDATE NOTIFICATIONS'
# )
main_threading(1, notif)
# main_threading(1, notif)
return Response(serializer.data)
......@@ -494,99 +533,70 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
return Response(e,
status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@transaction.atomic()
@action(
methods=['PATCH'], detail=True,
url_path='re_route', url_name='re_route'
)
def re_route(self, request, *args, **kwargs):
# generate batchno history
batchno = get_max_batchno("batch")
# partial update
partial = kwargs.pop('partial', True)
instance = self.get_object()
form_code = kwargs['form_code']
status_update = {"status": 'Pending'}
serializer = self.get_serializer(instance,
data=status_update,
partial=partial)
serializer.is_valid(raise_exception=True)
old_instance = model_to_dict(instance)
self.perform_update(serializer)
form_header = get_object_or_404(models.ChangeRequestFormHeader,
pk=instance.id)
new_instance = model_to_dict(form_header)
# save history in form header
crhistory_save(
batchno,
enums.CREnum.REROUTE.value,
enums.CREnum.UPDATE.value,
enums.CREntitiesEnum.CR_FRM_HEADER.value,
form_code,
old_instance,
new_instance
)
approver_data = []
# get all approvers of form
approvers = models.ChangeRequestFormApprovers.objects.filter(
form_code=form_code)
for approver in approvers:
approver_add = {
'id': approver.id,
'action': None,
'remarks': None,
'date_sent': None,
'action_date': None,
'is_action': False
}
approver_data.append(approver_add)
change_request.form_add_edit_delete(
approver_data,
models.ChangeRequestFormApprovers,
enums.CREntitiesEnum.CR_FRM_APPROVER.value,
ChangeRequestFormApproversSerializer,
partial,
self,
form_code,
batchno,
enums.CREnum.REROUTE.value
)
min_level = models.ChangeRequestFormApprovers.objects.filter(
form_code=form_code
).aggregate(Min('level'))
min_level = min_level.get('level__min')
next_approver_email(form_code, min_level)
@action(
methods=['GET'], detail=True,
url_path='form-download', url_name='form-download'
)
def FormDownload(self, request, form_code=None):
args = ['CHANGE_REQUEST_TEMPLATE.html']
my_folder = os.path.join(settings.MEDIA_ROOT, f'cr/{request.user.code}')
attch = models.ChangeRequestFormAttachments.objects.filter(
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)
user_folder = os.mkdir(my_folder)
for data in args:
F = open(os.path.join(settings.EMAIL_TEMPLATES_ROOT, data), 'r')
result = BytesIO()
pdf = pisa.pisaDocument(F, result)
updated_file = ContentFile(result.getvalue())
updated_file.name = f"{data}.pdf"
completeName = os.path.join(
os.path.join(settings.MEDIA_ROOT, f'cr/{request.user.code}'),
updated_file.name
)
file1 = open(completeName, "w")
file1.close()
# for file_name in attch_list:
# 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'])
a = os.path.join(settings.MEDIA_ROOT, file_name['file_upload__url'])
# 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')
shutil.copy(b, my_folder)
else:
print('xxx')
# update next approver details
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) & Q(level=int(min_level))
).update(
date_sent=datetime.now()
)
test = shutil.make_archive(my_folder + 'archive', 'zip', my_folder, ".")
message = status_message_response(
200, 'success',
'Change request form successfully re routed',
serializer.data
)
return Response(message, status=status.HTTP_200_OK)
response = HttpResponse(open(test, 'rb'), content_type='application/zip')
response['Content-Disposition'] = 'attachment; filename=change request.zip'
return response
@transaction.atomic()
@action(
......@@ -688,16 +698,12 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
def actions(self, request, *args, **kwargs):
current_user = self.request.user.code
action_body = request.data
id = action_body.get('id', False)
form_code = action_body.get('form_code', False)
delegation = action_body.get('delegation', False)
action = action_body.get('action', False)
level = action_body.get('level', False)
next_level = int(level) + 1
remarks = action_body.get('remarks', False)
move_to_level = action_body.get('move_to_level', False)
# generate batchno history
batchno = get_max_batchno("batch")
......@@ -724,8 +730,6 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
self.perform_update(serializer)
new_instance = serializer.data
print(new_instance['action'])
crhistory_save(
batchno,
enums.CREnum.ACTION.value,
......@@ -736,248 +740,8 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
new_instance
)
if action.lower() == 'approved':
the_next_vendor = models.ChangeRequestFormApprovers.objects.filter(
form_code=form_code, level=int(next_level),
delegation='Vendor/Implementor'
).first()
if the_next_vendor:
the_last_vendor = models.ChangeRequestFormApprovers.objects.filter(
form_code=form_code, delegation='Vendor/Implementor'
).order_by('level').last()
if the_next_vendor == the_last_vendor:
models.ChangeRequestFormHeader.objects.filter(
form_code=form_code
).update(status='Approved')
# NOTIF MSG FOR REQUESTOR
requestor_notification_msg = REQUESTOR_MESSAGE.split(';')[0]
# NOTIF MSG FOR NEXT APPROVER
notification_msg = APPROVER_MESSAGE.split(';')[0]
# SEND EMAIL AND NOTIF TO REQUESTOR
send_mail_requestor(
current_user, form_code, delegation,
requestor_notification_msg, action,
remarks, level
)
next_approver_email(form_code, next_level)
date_now = datetime.now()
# update next approver details
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) & Q(level=int(next_level))
).update(
date_sent=date_now,
is_action=True
)
# update current approver details
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) & Q(level=int(level))
).update(
is_action=False
)
reminder_trigger_save(form_code, date_now,
approver_instance.date_sent)
elif action.lower() == 'rejected':
# send email to vendor
if delegation.lower() == 'requestor':
notification_msg = VENDOR_REJECT_MESSAGE.split(';')[0]
send_mail_vendor(
current_user, form_code, delegation,
notification_msg, action,
remarks, level
)
prev_level = int(level) - 1
# reset last vendor details
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) &
Q(level=int(prev_level))
).update(
is_action=True,
action='Acknowledged',
action_date=datetime.now(),
date_sent=datetime.now()
)
else:
prev_vendor = models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) &
Q(action='Completed') &
Q(delegation='Vendor/Implementor') &
Q(level__lte=int(level))
)
if not prev_vendor.count() > 0:
models.ChangeRequestFormHeader.objects.filter(
form_code=form_code
).update(status='Rejected')
# EMAIL CODE FOR REQUESTOR
requestor_notification_msg = REQUESTOR_REJECT_MESSAGE.split(';')[0]
# SEND EMAIL AND NOTIF TO REQUESTOR
send_mail_requestor(
current_user, form_code, delegation,
requestor_notification_msg, action,
remarks, level
)
else:
# EMAIL CODE FOR REQUESTOR
requestor_notification_msg = REQUESTOR_REJECT_MESSAGE.split(';')[0]
# SEND EMAIL AND NOTIF TO REQUESTOR
send_mail_requestor(
current_user, form_code, delegation,
requestor_notification_msg, action,
remarks, level
)
notification_msg = VENDOR_REJECT_MESSAGE.split(';')[0]
send_mail_vendor(
current_user, form_code, 'others',
notification_msg, action,
remarks, level
)
last_action_vendor = prev_vendor.last()
models.ChangeRequestFormApprovers.objects.filter(
code=last_action_vendor
).update(
is_action=True,
action='Acknowledged',
action_date=datetime.now(),
date_sent=datetime.now()
)
level = last_action_vendor.level + 1
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) & Q(level__gte=int(level))
).update(
is_action=False,
action=None,
remarks=None,
action_date=None,
date_sent=None
)
elif action.lower() == 'completed':
the_last_vendor = models.ChangeRequestFormApprovers.objects.filter(
form_code=form_code, delegation='Vendor/Implementor'
).order_by('level').last()
if (current_user == the_last_vendor.user.code and
level == the_last_vendor.level):
models.ChangeRequestFormHeader.objects.filter(
form_code=form_code
).update(status='Approved')
else:
the_next_vendor = models.ChangeRequestFormApprovers.objects.filter(
form_code=form_code, level=int(next_level),
delegation='Vendor/Implementor'
).first()
if the_next_vendor:
if the_next_vendor.user.code == the_last_vendor.user.code:
models.ChangeRequestFormHeader.objects.filter(
form_code=form_code
).update(status='Approved')
else:
models.ChangeRequestFormHeader.objects.filter(
form_code=form_code
).update(status='Pending')
next_approver_email(form_code, next_level)
models.ChangeRequestFormApprovers.objects.filter(
Q(level=int(next_level))
).update(
date_sent=datetime.now(),
is_action=True
)
# update current approver details
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) & Q(level=int(level))
).update(
is_action=False
)
# EMAIL CODE FOR REQUESTOR
requestor_notification_msg = REQUESTOR_COMPLETION_MESSAGE.split(';')[0]
send_mail_requestor(
current_user, form_code, delegation,
requestor_notification_msg, action,
remarks, level
)
elif action.lower() == 'acknowledged':
# EMAIL CODE FOR REQUESTOR
requestor_notification_msg = REQUESTOR_ACKNOWLEDGE_MESSAGE.split(';')[0]
send_mail_requestor(
current_user, form_code, delegation,
requestor_notification_msg, action,
remarks, level
)
elif action.lower() == 'accepted':
models.ChangeRequestFormHeader.objects.filter(
form_code=form_code
).update(status='Completed & Accepted')
# EMAIL CODE FOR VENDOR
requestor_notification_msg = VENDOR_ACCEPTANCE_MESSAGE.split(';')[0]
send_mail_vendor(
current_user, form_code, delegation,
requestor_notification_msg, action,
remarks, level
)
# update is_action for current level
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) & Q(level=int(level))
).update(
is_action=False
)
elif action.lower() == 'cancelled':
# changed form status to cancelled
models.ChangeRequestFormHeader.objects.filter(
form_code=form_code).update(status='Cancelled')
# update is_action for current level
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) & Q(level=int(level))
).update(
is_action=False
)
change_request.cr_routing_actions(new_instance, current_user, move_to_level)
# ---------------- removed code
message = status_message_response(
200, 'success',
'Action performed',
......@@ -1029,7 +793,6 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
self.perform_update(serializer)
new_instance = serializer.data
print(serializer.errors)
# save history in form header
crhistory_save(
......@@ -1155,8 +918,6 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
new_instance = model_to_dict(form_header)
print(serializer.errors)
# save history in form header
crhistory_create_save(
batchno,
......@@ -1225,6 +986,8 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
next_approver_email(form_code, min_level)
date_now = datetime.now()
# update next approver details
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) & Q(level=int(min_level))
......@@ -1233,6 +996,13 @@ class ChangeRequestFormsViewset(viewsets.ModelViewSet):
is_action=True
)
# save details for overdue and auto cancellation
overdue_trigger_save(form_code)
# save details for reminder for first approver
reminder_trigger_save(form_code, date_now,
date_now)
serializer = self.get_serializer(instance)
message = status_message_response(
......@@ -1544,14 +1314,47 @@ class ChangeRequestFormPost(APIView):
next_approver_email(frm_id, min_level)
date_now = datetime.now()
# update next approver details
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=frm_id) & Q(level=int(min_level))
).update(
date_sent=datetime.now(),
date_sent=date_now,
is_action=True
)
# save details for overdue and auto cancellation
overdue_trigger_save(frm_id)
# save details for reminder for first approver
reminder_trigger_save(frm_id, date_now,
date_now)
else:
template_no = serializer.data['template_no']
CR_Prefix = models.ChangeRequestTemplateHeader.objects.filter(
template_no=template_no
).values('requested_to_template_id')
CR_Prefix = CR_Prefix.values_list('requested_to_template_id', flat=True)[0]
models.ChangeRequestFormHeader.objects.filter(
form_code=frm_id
).update(requested_to_template_id=CR_Prefix)
models.ChangeRequestFormApprovers.objects.filter(
form_code=frm_id
).update(
is_action=False,
action=None,
remarks=None,
action_date=None,
date_sent=None
)
message = {
'code': 201,
'status': 'success',
......
......@@ -12,7 +12,10 @@ from app.applicationlayer.utils import (
class ChangeRequestFormStakeHoldersViewset(viewsets.ModelViewSet):
queryset = models.ChangeRequestFormStakeHolders.objects.all()
# queryset = models.ChangeRequestFormStakeHolders.objects.all()
queryset = models.ChangeRequestFormStakeHolders.objects.select_related(
'form_code'
).all()
serializer_class = serializers.ChangeRequestFormStakeHoldersSerializer
pagination_class = CustomPagination
lookup_field = "code"
......
......@@ -556,12 +556,12 @@ class ChangeRequestFormsViewset(meviewsets.ModelViewSet):
the_next_vendor = models.ChangeRequestFormApprovers.objects.filter(
form_code=form_code, level=str(next_level),
delegation='Vendor/Implementor'
delegation__name='Vendor/Implementor'
).first()
if the_next_vendor:
the_last_vendor = models.ChangeRequestFormApprovers.objects.filter(
form_code=form_code, delegation='Vendor/Implementor'
form_code=form_code, delegation__name='Vendor/Implementor'
).order_by('level').last()
if the_next_vendor == the_last_vendor:
......@@ -688,7 +688,6 @@ class ChangeRequestFormsViewset(meviewsets.ModelViewSet):
old_instance = model_to_dict(instance)
self.perform_update(serializer)
new_instance = serializer.data
print(serializer.errors)
# save history in form header
crhistory_save(
......@@ -803,8 +802,6 @@ class ChangeRequestFormsViewset(meviewsets.ModelViewSet):
new_instance = model_to_dict(form_header)
print(serializer.errors)
# save history in form header
crhistory_create_save(
batchno,
......
......@@ -17,16 +17,10 @@ class UserListForm(APIView):
try:
serializer = ChangeRequestList
dept = self.request.query_params['department_code']
# company = self.request.query_params['company_code']
# allowed = models.AllowedCompany.objects.filter(
# Q(group_pivots=dept) &
# Q()
# )
user_list = models.User.objects.filter(
department=dept
).exclude(id=1)
# user_list = user_list.exclude(id=request.user.id)
print(user_list.query)
page = self.paginate_queryset(user_list)
if page is not None:
......
......@@ -72,8 +72,6 @@ class ChangeRequestCompanyFormViewSet(viewsets.ModelViewSet):
Q(requested_by_user=id_number) |
Q(frm_stakes__user__code=id_number)
).values()
# print(id_number)
# print(forms)
allowed = AllowedCompany.objects.filter(
id_number=id_number
......
......@@ -3,7 +3,7 @@ from rest_framework.response import Response
from app.applicationlayer.utils import model_to_dict
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters import rest_framework as filters
from app.entities.models import Department, AllowedCompany
from app.entities.models import Department, AllowedCompany, Delegation
from app.applicationlayer.utils import (
CustomPagination, status_message_response
)
......@@ -53,3 +53,8 @@ class ChangeRequestDepartmentFormViewSet(viewsets.ModelViewSet):
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
......@@ -4,8 +4,9 @@ from app.applicationlayer.utils import (CustomPagination,
from app.applicationlayer.management.account.serializer import ChangeRequestList
from app.entities import models
from rest_framework.response import Response
from django.db.models import Q
from django.db.models import Q, F
from rest_framework import status
# from django.db.models import F
class UserListTemplate(APIView):
......@@ -25,6 +26,7 @@ class UserListTemplate(APIView):
user_list = models.User.objects.filter(
code__in=verified_users
)
print(user_list)
page = self.paginate_queryset(user_list)
......
from rest_framework import serializers
from app.entities.models import User
from app.applicationlayer.utils import model_to_dict
class DefaultApproverSerializer(serializers.ModelSerializer):
def to_representation(self, instance):
ret = super().to_representation(instance)
ret['department'] = model_to_dict(instance.department)
ret['company'] = model_to_dict(instance.department.company)
return ret
class Meta:
model = User
fields = ('id', 'code', 'name', 'contact_no', 'email', 'department')
# fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
\ No newline at end of file
from django_filters import rest_framework as filters
from django.db.models import Count
from app.entities.models import User
from django.db.models import Q
class DefaultApproverFilterSet(filters.FilterSet):
class Meta:
model = User
fields = '__all__'
from rest_framework import viewsets, status
from rest_framework.response import Response
from app.applicationlayer.utils import model_to_dict
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters import rest_framework as filters
from app.entities.models import User, AllowedCompany
from app.applicationlayer.utils import (
CustomPagination, status_message_response
)
from django_filters.rest_framework import DjangoFilterBackend
from app.applicationlayer.cms.master.template.default_approver import serializer
from app.applicationlayer.cms.master.template.default_approver.table_filter import (
DefaultApproverFilterSet
)
from app.helper.decorators import rms
from django.db.models import Q
from rest_framework.exceptions import ParseError
class DefaultApproverViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = serializer.DefaultApproverSerializer
pagination_class = CustomPagination
lookup_field = 'code'
filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter)
filterset_class = DefaultApproverFilterSet
ordering_fields = '__all__'
search_fields = ('name', 'department__name', 'code')
def list(self, request, *args, **kwargs):
department = self.request.query_params['department_code']
queryset = self.filter_queryset(self.get_queryset())
default_user = AllowedCompany.objects.filter(
Q(group_pivots=department) &
Q(approve_cr=True)
).values('id_number')
queryset = queryset.filter(code__in=default_user)
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 Default Approvers found',
serializer.data
)
return self.get_paginated_response(message)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
......@@ -48,11 +48,23 @@ class ChangeRequestTemplateApproversSerializer(
else:
ret['editable_user'] = True
if instance.delegation.lower() == 'requestor':
if instance.delegation:
ret['delegation'] = {
"id": instance.delegation.id,
"code": instance.delegation.code,
"name": instance.delegation.name
}
ret['editable_deleg'] = False
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
return ret
except Exception as e:
......@@ -60,6 +72,7 @@ class ChangeRequestTemplateApproversSerializer(
ret['editable_user'] = True
ret['editable_comp'] = True
ret['editable_dept'] = True
ret['editable_deleg'] = True
return ret
......
......@@ -13,7 +13,10 @@ from app.applicationlayer.utils import (
class ChangeRequestTemplateApproversViewset(viewsets.ModelViewSet):
queryset = models.ChangeRequestTemplateApprovers.objects.all()
# queryset = models.ChangeRequestTemplateApprovers.objects.all()
queryset = models.ChangeRequestTemplateApprovers.objects.select_related(
'template_no', 'company', 'department'
).all()
serializer_class = serializers.ChangeRequestTemplateApproversSerializer
pagination_class = CustomPagination
lookup_field = "code"
......
......@@ -13,7 +13,10 @@ from app.applicationlayer.utils import (
class ChangeRequestTemplateAttachmentsViewset(viewsets.ModelViewSet):
queryset = models.ChangeRequestTemplateAttachments.objects.all()
# queryset = models.ChangeRequestTemplateAttachments.objects.all()
queryset = models.ChangeRequestTemplateAttachments.objects.select_related(
'file_upload', 'template_no'
).all()
serializer_class = serializers.ChangeRequestTemplateAttachmentsSerializer
pagination_class = CustomPagination
lookup_field = "code"
......
......@@ -13,7 +13,10 @@ from app.applicationlayer.utils import (
class ChangeRequestTemplateDetailsViewset(viewsets.ModelViewSet):
queryset = models.ChangeRequestTemplateDetails.objects.all()
# queryset = models.ChangeRequestTemplateDetails.objects.all()
queryset = models.ChangeRequestTemplateDetails.objects.select_related(
'template_no'
).all()
serializer_class = serializers.ChangeRequestTemplateDetailsSerializer
pagination_class = CustomPagination
lookup_field = "code"
......
......@@ -43,7 +43,11 @@ class ChangeRequestTemplatesSerializer(
"username": instance.requested_to_user.username,
"code": instance.requested_to_user.code,
"email": instance.requested_to_user.email,
"contact_no": instance.requested_to_user.contact_no
"contact_no": instance.requested_to_user.contact_no,
"company_code": instance.requested_to_user.department.company.code,
"company_name": instance.requested_to_user.department.company.name,
"department_code": instance.requested_to_user.department.code,
"department_name": instance.requested_to_user.department.name
}
ret['requested_to_company'] = {
......
......@@ -46,7 +46,10 @@ from django_filters.rest_framework import DjangoFilterBackend
class ChangeRequestTemplatesViewset(viewsets.ModelViewSet):
queryset = models.ChangeRequestTemplateHeader.objects.all()
# queryset = models.ChangeRequestTemplateHeader.objects.all()
queryset = models.ChangeRequestTemplateHeader.objects.select_related(
'created_by_user', 'created_by_department'
).all()
serializer_class = ChangeRequestTemplatesSerializer
pagination_class = CustomPagination
lookup_field = 'template_no'
......@@ -362,6 +365,12 @@ 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)
......
......@@ -13,7 +13,10 @@ from app.applicationlayer.utils import (
class ChangeRequestTemplateStakeholdersViewset(viewsets.ModelViewSet):
queryset = models.ChangeRequestTemplateStakeHolders.objects.all()
# queryset = models.ChangeRequestTemplateStakeHolders.objects.all()
queryset = models.ChangeRequestTemplateStakeHolders.objects.select_related(
'template_no'
).all()
serializer_class = serializers.ChangeRequestTemplateStakeHoldersSerializer
pagination_class = CustomPagination
lookup_field = "code"
......
......@@ -12,6 +12,7 @@ from app.applicationlayer.cms.master.template.company.views import ChangeRequest
from app.applicationlayer.cms.master.template.department.views import ChangeRequestDepartmentTemplateViewSet
from app.applicationlayer.cms.master.template.account.views import UserListTemplate
from app.applicationlayer.cms.master.template_list.views import ChangeRequestTemplateHeaderMaster
from app.applicationlayer.cms.master.template.default_approver.views import DefaultApproverViewSet
# MASTERS Form
......@@ -69,6 +70,7 @@ router.register(r'allowed-companies', allowed.AllowedCompanyViewSet)
router.register(r'template-companies', ChangeRequestCompanyTemplateViewSet)
router.register(r'template-departments', ChangeRequestDepartmentTemplateViewSet)
router.register(r'allowed-templates', ChangeRequestTemplateHeaderMaster)
router.register(r'default-approvers', DefaultApproverViewSet)
# filter endpoints under Allowed Companies table
# filter endpoints under Allowed Companies table
......@@ -86,7 +88,8 @@ urlpatterns = [
path('template-user-list/', UserListTemplate.as_view(), name="User List"),
# filter endpoints under Allowed Companies table
path('reminder/', reminder.ReminderTriggerAPIView.as_view()),
# path('cancelled/', cancel.CancelTriggerAPIView.as_view()),
path('cancelled/', cancel.CancelTriggerAPIView.as_view()),
path('overdue/', overdue.OverdueTriggerAPIView.as_view()),
]
# urlpatterns += format_suffix_patterns(urlpatterns)
......
......@@ -15,6 +15,7 @@ from rest_framework.exceptions import ParseError
from django.db import IntegrityError
from rest_framework.exceptions import APIException
from django.db.models import Max
import os
CR_FRONT_LINK = settings.CR_FRONT_LINK
......@@ -26,11 +27,12 @@ REQUESTOR_ACKNOWLEDGE_MESSAGE = settings.REQUESTOR_ACKNOWLEDGE_MESSAGE
REQUESTOR_COMPLETION_MESSAGE = settings.REQUESTOR_COMPLETION_MESSAGE
VENDOR_ACCEPTANCE_MESSAGE = settings.VENDOR_ACCEPTANCE_MESSAGE
VENDOR_REJECT_MESSAGE = settings.VENDOR_REJECT_MESSAGE
REVISED_MESSAGE = settings.REVISED_MESSAGE
CANCEL_MESSAGE = settings.CANCEL_MESSAGE
def entity_log_bulk(queryset, entity, tbl):
try:
# print(entity)
for data in queryset:
test = model_to_dict(data)
log_save(
......@@ -206,11 +208,13 @@ def send_mail_vendor(requestor,
recipient = vendor_email
action_type = action
delegation_type = delegation
delegation_recipient = 'vendor'
admin = sender_email
args = [name, action_by, routing_level, status, cr_number, cr_name,
company_requestedto, department_requestedto, priority_level,
url, remarks, recipient, action_type, delegation_type, admin]
url, remarks, recipient, action_type, delegation_type,
delegation_recipient, admin]
main_threading(args, sender.routing_table_actions)
......@@ -219,7 +223,7 @@ def send_mail_vendor(requestor,
# create notification
notification_create(form_code, message, vendor_code,
sender_code)
sender_code, 'cms')
def send_mail_requestor(current_user,
......@@ -274,11 +278,13 @@ def send_mail_requestor(current_user,
recipient = requestor_email
action_type = action
delegation_type = delegation
delegation_recipient = 'requestor'
admin = sender_email
args = [name, action_by, routing_level, status, cr_number, cr_name,
company_requestedto, department_requestedto, priority_level,
url, remarks, recipient, action_type, delegation_type, admin]
url, remarks, recipient, action_type, delegation_type,
delegation_recipient, admin]
main_threading(args, sender.routing_table_actions)
......@@ -287,7 +293,78 @@ def send_mail_requestor(current_user,
# create notification
notification_create(form_code, message, requestor_code,
current_user)
current_user, 'cms')
def send_mail_approver(current_user,
form_code,
delegation,
msg,
action,
remarks,
routing_level,
approver_code):
cr_link = f'{CR_FRONT_LINK}/{form_code}'
template_instance = get_template_instance(form_code)
cr_number = template_instance.requested_to_template_id
template_name = template_instance.requested_to_template_name
requested_to_company = template_instance.requested_to_company.code
requested_to_department = template_instance.requested_to_department.code
requested_by_user = template_instance.requested_by_user.code
requested_to_priority = template_instance.requested_to_priority
cr_status = template_instance.status
# receiver details --------------------------------------------------
approver_instance = get_account_details(approver_code)
approver_name = approver_instance.values_list('name', flat=True)[0]
approver_email = approver_instance.values_list('email', flat=True)[0]
approver_code = approver_instance.values_list('code', flat=True)[0]
# sender details --------------------------------------------------
sender_instance = get_account_details(current_user)
sender_email = sender_instance.values_list('email', flat=True)[0]
sender_name = sender_instance.values_list('name', flat=True)[0]
department = get_dept_details(requested_to_department)
dept_name = department.values_list('name', flat=True)[0]
company = get_companies_details(requested_to_company)
company_name = company.values_list('name', flat=True)[0]
# call sender email
name = approver_name
action_by = sender_name
routing_level = routing_level
status = cr_status
cr_number = cr_number
cr_name = template_name
company_requestedto = company_name
department_requestedto = dept_name
priority_level = requested_to_priority
url = cr_link
recipient = approver_email
action_type = action
delegation_type = delegation
delegation_recipient = 'approver'
admin = sender_email
args = [name, action_by, routing_level, status, cr_number, cr_name,
company_requestedto, department_requestedto, priority_level,
url, remarks, recipient, action_type, delegation_type,
delegation_recipient, admin]
main_threading(args, sender.routing_table_actions)
message = f"{sender_name} {msg} ({template_name})"
# create notification
notification_create(form_code, message, approver_code,
current_user, 'cms')
def next_approver_email(form_code, next_level):
......@@ -319,14 +396,16 @@ 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]
if n_approver.delegation.lower() == 'vendor/implementor':
if n_approver.delegation.name.lower() == 'vendor/implementor':
msg = VENDOR_ACKNOWLEDGE_MESSAGE.split(';')[0]
# next approver details --------------------------------------------------
......@@ -347,12 +426,14 @@ def next_approver_email(form_code, next_level):
url = cr_link
recipient = receiver_email
delegation_type = n_approver.delegation.lower()
delegation_type = n_approver.delegation.name.lower()
delegation_recipient = 'None'
admin = sender_email
args = [name, cr_number, cr_name,
company_requestedto, department_requestedto, priority_level,
status, url, recipient, delegation_type, admin]
status, url, recipient, delegation_type,
delegation_recipient, admin]
main_threading(args, sender.routing_table_actions_required)
......@@ -361,7 +442,7 @@ def next_approver_email(form_code, next_level):
# create notification
notification_create(form_code, message, receiver_code,
sender_code)
sender_code, 'cms')
def cancel_overdue(request):
......@@ -461,7 +542,6 @@ def crhistory_save(batch_no, main_action,
def crhistory_log_bulk_delete(queryset, entity, tbl, form_code,
batch_no, main_action):
try:
# print(entity)
for data in queryset:
test = model_to_dict(data)
crhistory_save(batch_no,
......@@ -473,6 +553,44 @@ def crhistory_log_bulk_delete(queryset, entity, tbl, form_code,
'')
tbl.objects.filter(id=test['id']).delete()
return True
except IntegrityError as exc:
raise APIException(detail=exc)
def crhistory_log_bulk_delete_masterattach(queryset, entity, tbl, form_code,
batch_no, main_action):
try:
for data in queryset:
test = model_to_dict(data)
# print(test)
crhistory_save(batch_no,
main_action,
enums.CREnum.DELETED.value,
entity,
form_code,
test,
'')
tbl.objects.filter(id=test['id']).delete()
# url = models.MasterAttachment.objects.get(id=test['file_upload'])
# models.MasterAttachment.objects.filter(
# id=test['file_upload']).delete()
# r = model_to_dict(url)
# print(r['url'])
# print(settings.MEDIA_ROOT)
# # os.remove(r['url'])
# x = os.path.join(settings.MEDIA_ROOT, r['url'])
# print(x)
# if os.path.exists(os.path.join(settings.MEDIA_ROOT, r['url'])):
# print("file exists")
# # os.remove(r['url'])
# else:
# print("The file does not exist")
return True
except IntegrityError as exc:
raise APIException(detail=exc)
......@@ -551,7 +669,8 @@ def reminder_trigger_save(form_code,
date_to_send=date_from.strftime('%Y-%m-%d 00:00:00.000'),
auto_cancel_date=auto_cancel_date.strftime('%Y-%m-%d 00:00:00.000'),
date_submitted_last_approver=date_submitted_last_approver,
is_sent=False
is_sent=False,
form_code=form_instance
)
if counter == 0:
......@@ -560,8 +679,147 @@ def reminder_trigger_save(form_code,
auto_cancel_date=auto_cancel_date.strftime('%Y-%m-%d 00:00:00.000'),
date_submitted_last_approver=date_submitted_last_approver,
is_sent=False,
frm_approver=approver
frm_approver=approver,
cancel_type='from_approval'
)
counter = counter + 1
return True
def overdue_trigger_save(form_code):
form_instance = models.ChangeRequestFormHeader.objects.get(
form_code=form_code)
requested_to_target_date = form_instance.requested_to_target_date
overdue_date = requested_to_target_date + timedelta(days=1)
auto_cancel_date = overdue_date + timedelta(days=30)
models.OverdueTrigger.objects.create(
form_code=form_instance,
overdue_date=overdue_date.strftime('%Y-%m-%d 00:00:00.000'),
is_sent=False
)
models.CancelTrigger.objects.create(
form_code=form_instance,
auto_cancel_date=auto_cancel_date.strftime('%Y-%m-%d 00:00:00.000'),
date_submitted_last_approver=None,
is_sent=False,
frm_approver=None,
cancel_type='from_target_date'
)
return True
def reset_autoemail_tables(form_code):
models.ReminderTrigger.objects.filter(
form_code=form_code
).delete()
models.CancelTrigger.objects.filter(
form_code=form_code
).delete()
models.OverdueTrigger.objects.filter(
form_code=form_code
).delete()
return True
def cancelled_user_trigger(form_code,
action,
routing_level):
cr_link = f'{CR_FRONT_LINK}/{form_code}'
template_instance = get_template_instance(form_code)
cr_number = template_instance.requested_to_template_id
template_name = template_instance.requested_to_template_name
requested_to_company = template_instance.requested_to_company.code
requested_to_department = template_instance.requested_to_department.code
requested_by_user = template_instance.requested_by_user.code
requested_by_username = template_instance.requested_by_user.username
requested_to_priority = template_instance.requested_to_priority
cr_status = template_instance.status
# requestor details --------------------------------------------------
sender_instance = get_account_details(requested_by_user)
sender_email = sender_instance.values_list('email', flat=True)[0]
sender_name = sender_instance.values_list('name', flat=True)[0]
sender_code = sender_instance.values_list('code', flat=True)[0]
department = get_dept_details(requested_to_department)
dept_name = department.values_list('name', flat=True)[0]
company = get_companies_details(requested_to_company)
company_name = company.values_list('name', flat=True)[0]
# get details of approvers received an email about the CR
received_form_approvers = models.ChangeRequestFormApprovers.objects.filter(
~Q(date_sent=None) &
Q(form_code=form_code)
)
received_form_approvers = received_form_approvers.values_list('user_id')
received_history_approvers = models.ChangeRequestHistory.objects.filter(
Q(form_code=form_code) &
Q(entity='CR_FRM_APPROVER') &
Q(main_action='ACTION')
).values_list('modifiedby', flat=True).distinct()
received_history_approvers = models.User.objects.filter(
Q(username__in=received_history_approvers) |
Q(code__in=received_form_approvers)
).exclude(username=requested_by_username)
# comment
# LOOP on next approver for sending email
for n_approver in received_history_approvers:
# NOTIF MSG FOR NEXT APPROVER
msg = CANCEL_MESSAGE.split(';')[0]
# next approver details --------------------------------------------------
receiver_instance = get_account_details(n_approver.code)
receiver_name = receiver_instance.values_list('name', flat=True)[0]
receiver_email = receiver_instance.values_list('email', flat=True)[0]
receiver_code = receiver_instance.values_list('code', flat=True)[0]
# call sender email
name = receiver_name
action_by = sender_name
routing_level = routing_level
status = cr_status
cr_number = cr_number
cr_name = template_name
company_requestedto = company_name
department_requestedto = dept_name
priority_level = requested_to_priority
url = cr_link
remarks = 'None'
recipient = receiver_email
action_type = action
delegation_type = 'others'
delegation_recipient = 'None'
admin = sender_email
args = [name, action_by, routing_level, status, cr_number, cr_name,
company_requestedto, department_requestedto, priority_level,
url, remarks, recipient, action_type, delegation_type,
delegation_recipient, admin]
main_threading(args, sender.routing_table_actions)
message = f"{sender_name} {msg} ({template_name})"
# create notification
notification_create(form_code, message, receiver_code,
sender_code, 'cms')
\ No newline at end of file
......@@ -5,7 +5,6 @@ from django.db.models import Q
class headers(serializers.ModelSerializer):
def to_representation(self, instance):
ret = super().to_representation(instance)
ret['deparment'] = instance.department.name
......@@ -13,8 +12,6 @@ class headers(serializers.ModelSerializer):
return ret
class Meta:
model = models.User
fields = (
......
......@@ -11,7 +11,6 @@ class headers(serializers.ModelSerializer):
return ret
class Meta:
model = models.Company
fields = (
......
......@@ -50,6 +50,15 @@ class UserEditSerializer(serializers.ModelSerializer):
class ChangeRequestList(serializers.ModelSerializer):
def to_representation(self, instance):
ret = super().to_representation(instance)
ret['company_name'] = instance.department.company.name
ret['company_code'] = instance.department.company.code
ret['department_code'] = instance.department.code
ret['department_name'] = instance.department.name
return ret
class Meta:
model = User
fields = (
......
import copy
import threading
import pandas as pd
import csv
import io, os
from app.entities import enums
from django.db import transaction
from app.helper import decorators
......@@ -13,7 +16,8 @@ from rest_framework.response import Response
from app.applicationlayer.utils import model_to_dict
from app.entities.models import (
User, EntityLog, PasswordReset, Application, UserImage,
ChangeRequestFormHeader, ChangeRequestTemplateHeader
ChangeRequestFormHeader, ChangeRequestTemplateHeader,
AllowedCompany, Company, Department, UserHistory
)
from app.helper.decorators import rms, error_safe
from django.contrib.auth.hashers import make_password
......@@ -23,6 +27,7 @@ from rest_framework.filters import SearchFilter, OrderingFilter
from app.applicationlayer.management.account.table_filters import AccountFilterset
from app.applicationlayer.management.account import serializer
from app.helper.file_manager import FileHelper
from django.db import IntegrityError
from app.applicationlayer.utils import (
CustomPagination, status_message_response, log_save,
main_threading
......@@ -66,8 +71,6 @@ class UserViewSet(viewsets.ModelViewSet):
if request.data['user_type'] != 'USR':
rms = Application.objects.filter(id=1).values('code').first()
app.append(rms['code'])
# else:
# app = request.data['application']
......@@ -145,6 +148,8 @@ class UserViewSet(viewsets.ModelViewSet):
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(
......@@ -228,6 +233,193 @@ class UserViewSet(viewsets.ModelViewSet):
)
# @rms.user_create
# @action(detail=False,
# methods=['put'],
# url_path='batch-upload',
# name="upload User")
# @decorators.error_safe
# @transaction.atomic
# def BatchUpload(self, request):
# csv_file = request.FILES['file']
# df = pd.read_csv(csv_file, sep=',', skiprows=0)
# logged_user_type = request.user.user_type
# logged_user_company = request.user.department.company.name
# logged_user_department = request.user.department.name
# logged_user_email = request.user.email
# email_users = []
# for data, keys in df.iterrows():
# try:
# user_department = Department.objects.filter(
# Q(name__icontains=keys['department']) &
# Q(company__name__icontains=logged_user_company)
# ).first()
# if logged_user_type == 'CUA':
# user_department = Department.objects.filter(
# Q(name__icontains=keys['department']) &
# Q(company__name__icontains=logged_user_company)
# ).first()
# if user_department == None:
# msg = f"company is not the same with the logged user at row {data + 2}"
# return Response(
# {"message": msg},
# status=status.HTTP_400_BAD_REQUEST
# )
# elif logged_user_type == 'DUA':
# user_department = Department.objects.get(
# name__icontains=logged_user_department
# )
# elif logged_user_type == 'USR':
# return Response(
# {"message": "Logged User is not allowed"},
# status=status.HTTP_400_BAD_REQUEST
# )
# else:
# user_department = Department.objects.get(
# name__icontains=keys['department']
# )
# default_app = Application.objects.filter(
# excel_code=keys['default_app']
# ).first()
# enums_super = enums.UserTypeEnum.SUPER_USER.value
# enums_OUA = enums.UserTypeEnum.OVERALL_USER_ADMIN.value
# enums_company = enums.UserTypeEnum.COMPANY_USER_ADMIN.value
# enums_department = enums.UserTypeEnum.DEPARTMENT_USER_ADMIN.value
# enums_user = enums.UserTypeEnum.USER.value
# if keys['user_type'].lower() == 'super user' and logged_user_type == enums_super:
# user_type = enums.UserTypeEnum.SUPER_USER.value
# elif keys['user_type'].lower() == 'super user' and logged_user_type != enums_super:
# return Response(
# {"message": f"This user is not allowed to create super user. data error at row {data + 2}"},
# status=status.HTTP_201_CREATED
# )
# elif keys['user_type'].lower() == 'overall user admin':
# user_type = enums.UserTypeEnum.OVERALL_USER_ADMIN.value
# elif keys['user_type'].lower() == 'company user admin':
# user_type = enums.UserTypeEnum.COMPANY_USER_ADMIN.value
# elif keys['user_type'].lower() == 'department user admin':
# user_type = enums.UserTypeEnum.DEPARTMENT_USER_ADMIN.value
# else:
# user_type = enums.UserTypeEnum.USER.value
# users = {
# "username": keys['username'],
# "name": keys['name'],
# "department": user_department,
# "email": keys['email'],
# "contact_no": keys['contact_no'],
# "default_app": default_app,
# "user_type": user_type
# }
# current_user = User.objects.create(
# **users
# )
# password = User.objects.make_random_password(length=10)
# password_hash = make_password(password)
# current_user.password = password_hash
# current_user.save()
# app = Application.objects.filter(
# excel_code__in=keys['application'].split(',')
# )
# update_user = current_user.application.set(app)
# for instance in keys['privilege'].split(';'):
# privilege_list = instance.split(',')
# this_company = Company.objects.filter(
# name__icontains=privilege_list[0]
# ).first()
# this_department = Department.objects.filter(
# name__icontains=privilege_list[1]
# ).first()
# if privilege_list[2] == 0:
# privilege_list[2] = False
# else:
# privilege_list[2] = True
# if privilege_list[3] == 0:
# privilege_list[3] = False
# else:
# privilege_list[3] = True
# if privilege_list[4] == 0:
# privilege_list[4] = False
# else:
# privilege_list[4] = True
# current_user = User.objects.get(id=current_user.id)
# try:
# privilege_object = {
# "id_number": current_user,
# "company_pivot": this_company,
# "group_pivots": this_department,
# "create_change_request": privilege_list[2],
# "create_change_request_template": privilege_list[3],
# "view_all_change_request": privilege_list[4],
# "approve_cr": privilege_list[5]
# }
# AllowedCompany.objects.create(**privilege_object)
# except IntegrityError as e:
# return Response(
# {"message": f"Duplicate user privilege at row {data + 2}"},
# status=status.HTTP_400_BAD_REQUEST
# )
# except IntegrityError as e:
# return Response(
# {"message": f"Record already exist at row {data + 2}"},
# status=status.HTTP_400_BAD_REQUEST
# )
# except KeyError as e:
# return Response(
# {"message": "Missing column user_type"},
# status=status.HTTP_400_BAD_REQUEST
# )
# del users['department']
# del users['contact_no']
# del users['default_app']
# del users['user_type']
# users['password'] = password
# UserHistory.objects.create(
# **users
# )
# users['admin'] = logged_user_email
# send_mail = UserHistory.objects.filter(sent=False)[0:100].values(
# 'name', 'username', 'email', 'password'
# )
# df = pd.DataFrame(send_mail)
# df.to_csv("users.csv", index=False)
# args = ["users.csv", logged_user_email]
# main_threading(args, sender.batch_email_admin)
# args = [send_mail, logged_user_email]
# main_threading(args, sender.batch_email_users)
# return Response(
# {"message": "File already uploaded"},
# status=status.HTTP_201_CREATED
# )
@action(detail=True,
methods=['put'],
url_path='reset-password',
......
from rest_framework import serializers
from app.entities.models import (
ExtractTransformLoad, UserHistory, MasterAttachment
)
class ExtractTransformLoadSerializer(serializers.ModelSerializer):
class Meta:
model = ExtractTransformLoad
fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
class UserHistorySerializer(serializers.ModelSerializer):
class Meta:
model = UserHistory
fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'code'
)
class BatchUploadSerializer(serializers.ModelSerializer):
class Meta:
model = MasterAttachment
fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
class BatchUploadSerializer(serializers.ModelSerializer):
class Meta:
model = MasterAttachment
fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
from django_filters import rest_framework as filters
from app.entities.models import UserHistory, ExtractTransformLoad
class ExtractTransformLoadFilter(filters.FilterSet):
class Meta:
model = ExtractTransformLoad
fields = '__all__'
import os
import datetime
import threading
import configparser
import pandas as pd
from datetime import datetime
from app.entities import enums
from django.db import transaction
from app.helper import decorators
from django.db import IntegrityError
from app.helper.email_service import sender
from rest_framework import status, viewsets
from rest_framework.response import Response
from app.applicationlayer.management.batchupload.serializer import (
ExtractTransformLoadSerializer,
UserHistorySerializer,
BatchUploadSerializer
)
from app.entities.models import (
User, Application, ExtractTransformLoad,
AllowedCompany, Company, Department, UserHistory, MasterAttachment
)
from app.applicationlayer.utils import (
status_message_response,
main_threading, PaginationForETL
)
from django.db.models import Q
from rest_framework.exceptions import ParseError
from rest_framework.decorators import action
from django.contrib.auth.hashers import make_password
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter, OrderingFilter
from app.applicationlayer.management.batchupload.table_filters import ExtractTransformLoadFilter
from django.db.models import F, Value
from django.core.files.base import ContentFile
config = configparser.ConfigParser()
config_file = os.path.join('./', 'env.ini')
config.read(config_file)
from django.conf import settings
from io import BytesIO
from django.http import HttpResponse
from django.template.loader import get_template
from xhtml2pdf import pisa
from django.core.files.storage import FileSystemStorage
from django.core.exceptions import ObjectDoesNotExist
import sys
import os
import zipfile
import shutil
class BatchUploadViewSet(viewsets.ModelViewSet):
queryset = ExtractTransformLoad.objects.all().order_by('-created')
serializer_class = ExtractTransformLoadSerializer
pagination_class = PaginationForETL
lookup_field = 'code'
filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter)
filterset_class = ExtractTransformLoadFilter
ordering_fields = (
'file_name', 'model_type', 'code'
)
search_fields = (
'file_name', 'model_type', 'code'
)
def list(self, request, *args, **kwargs):
logged_user = request.user.username
queryset = self.filter_queryset(self.get_queryset().filter(createdby=logged_user))
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
message = status_message_response(
200,
'success',
'',
serializer.data
)
return self.get_paginated_response(message)
serializer = self.get_serializer(queryset, many=True)
return Response(
serializer.data,
status=status.HTTP_200_OK
)
@action(
detail=True, methods=['get'],
url_path='users', name='list of batch upload users'
)
def Users(self, request, code=None):
self.serializer_class = UserHistorySerializer
queryset = UserHistory.objects.filter(file_name=code)
page = self.paginate_queryset(queryset)
serializer = self.get_serializer(page, many=True)
message = status_message_response(
200,
'success',
'List of User found',
serializer.data
)
return self.get_paginated_response(message)
@action(
detail=False, methods=['get'],
url_path='pdf-instruction', name='how to upload bulk users'
)
def testpdf(self, request, code=None):
F = open(os.path.join(settings.EMAIL_TEMPLATES_ROOT, 'RMS-NEWUSER.html'), 'r')
result = BytesIO()
pdf = pisa.pisaDocument(F, result)
updated_file = ContentFile(result.getvalue())
updated_file.name = "cr_download.pdf"
my_folder = os.path.join(settings.MEDIA_ROOT, f'cr/{request.user.code}')
if os.path.isdir(my_folder):
shutil.rmtree(my_folder)
user_folder = os.mkdir(my_folder)
completeName = os.path.join(os.path.join(settings.MEDIA_ROOT, f'cr/{request.user.code}'), updated_file.name)
file1 = open(completeName, "w+")
# response = HttpResponse(open(my_folder, 'rb'), content_type='application/zip')
# response['Content-Disposition'] = 'attachment; filename=any_name_you_like.zip'
# return response
message = status_message_response(
200,
'success',
'test',
"sss"
)
return Response(message)
# return sender.to_pdf()
@action(
detail=False, methods=['get'],
url_path='user-instruction', name='how to upload bulk users'
)
def UserInstruction(self, request, code=None):
self.serializer_class = BatchUploadSerializer
queryset = MasterAttachment.objects.filter(
url__contains=config['SETTINGS']['BATCH_UPLOAD_FORMAT_FILENAME']
)
page = self.paginate_queryset(queryset)
serializer = self.get_serializer(page, many=True)
message = status_message_response(
200,
'success',
'',
serializer.data
)
return self.get_paginated_response(message)
@action(
detail=False, methods=['get'],
url_path='user-format-download', name='Users file format'
)
def UserFormat(self, request, code=None):
attach_user = MasterAttachment.objects.filter(attch_ref='etl_gen')
if attach_user:
attach_user.first().delete()
departments = Department.objects.exclude(id=1).annotate(
Privilege_Company=F('company__name'),
Privilege_Department=F('name'),
Privilege_Department_Code=F('code')
).values(
'Privilege_Company',
'Privilege_Department',
'Privilege_Department_Code'
)
data = {
'Username': ["ob-john"],
'Name': ["John Doe"],
'Company': [departments[0]['Privilege_Company']],
'Department': [departments[0]['Privilege_Department']],
'Department_Code': [departments[0]['Privilege_Department_Code']],
'Email': ["johndoe@gmail.com"],
'Contact_No': ["123456"],
'Application': ["cms,ams"],
'Default_app': ["cms"],
'Privilege_Company': [departments[0]['Privilege_Company']],
'Privilege_Department': [departments[0]['Privilege_Department']],
'Privilege_Department_Code': [departments[0]['Privilege_Department_Code']],
'Create_CR': ["Yes"],
'Create_Template': ["No"],
'View_All_CR': ["Yes"],
'Approve_CR': ["Yes"]
}
cols = ['Username', 'Name', 'Company', 'Department', 'Department_Code']
cols += ['Email', 'Contact_No', 'Application', 'Default_app']
cols += ['Privilege_Company', 'Privilege_Department', 'Privilege_Department_Code']
cols += ['Create_CR', 'Create_Template', 'View_All_CR', 'Approve_CR']
df = pd.DataFrame(data)
header = {"Privilege_Company": ['Please use this department code as reference']}
df3 = pd.DataFrame(
header
)
df2 = pd.DataFrame(
departments
)
df_row_reindex = pd.concat([df, df3, df2])
df_row_reindex = df_row_reindex.reindex(columns=cols)
df_row_reindex = df_row_reindex.to_csv(index=False)
updated_file = ContentFile(df_row_reindex)
updated_file.name = "user_format.csv"
uploaded = MasterAttachment.objects.create(
url=updated_file,
attch_ref='etl_gen'
)
self.serializer_class = BatchUploadSerializer
queryset = MasterAttachment.objects.filter(id=uploaded.id)
page = self.paginate_queryset(queryset)
serializer = self.get_serializer(page, many=True)
message = status_message_response(
200,
'success',
'User File format is found',
serializer.data
)
return self.get_paginated_response(message)
@transaction.atomic
def create(self, request, **kwargs):
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()
logged_user_type = request.user.user_type
logged_user_company = request.user.department.company.name
logged_user_department = request.user.department.name
logged_user_email = request.user.email
email_users = []
department_error = 'Department should be same with the logged user'
company_error = 'Company should be same with the logged user'
etl = ExtractTransformLoad.objects.create(
file_name=str(csv_file),
model_type=enums.GenerateCode.USER.value
)
etl2 = ExtractTransformLoad.objects.get(id=etl.id)
enums_super = enums.UserTypeEnum.SUPER_USER.value
enums_OUA = enums.UserTypeEnum.OVERALL_USER_ADMIN.value
enums_company = enums.UserTypeEnum.COMPANY_USER_ADMIN.value
enums_department = enums.UserTypeEnum.DEPARTMENT_USER_ADMIN.value
enums_user = enums.UserTypeEnum.USER.value
for data, keys in df.iterrows():
try:
default_app = Application.objects.filter(
excel_code=keys['Default_app']
).first()
# user type authorization and user type per user
if request.user.user_type == enums_company:
user_company = request.user.department.company.code
request_department = Department.objects.filter(
Q(code=keys['Department_Code']) &
Q(company=user_company)
)
if not request_department:
# raise ParseError(company_error)
return Response(
{"message": company_error},
# {"message": str(e)},
status=status.HTTP_400_BAD_REQUEST
)
elif request.user.user_type == enums_department:
if keys['Department_Code'] != request.user.department.code:
return Response(
{"message": department_error},
# {"message": str(e)},
status=status.HTTP_400_BAD_REQUEST
)
# raise ParseError(
# department_error
# )
# user type authorization and user type per user
else:
user_department = Department.objects.filter(
name__icontains=keys['Department_Code']
)
default_app = Application.objects.filter(
excel_code=keys['Default_app']
).first()
dept_code = Department.objects.get(
code=keys['Department_Code']
)
users = {
"username": keys['Username'],
"name": keys['Name'],
"department": dept_code,
"email": keys['Email'],
"contact_no": keys['Contact_No'],
"default_app": default_app,
"user_type": enums_user
}
check_user = User.objects.filter(username=keys['Username'])
if not check_user:
current_user = User.objects.create(
**users
)
password = User.objects.make_random_password(length=10)
password_hash = make_password(password)
current_user.password = password_hash
current_user.save()
app = Application.objects.filter(
excel_code__in=keys['Application'].split(',')
)
current_user.application.set(app)
current_user = User.objects.get(id=current_user.id)
del users['department']
del users['contact_no']
del users['default_app']
del users['user_type']
users['file_name'] = etl2
users['password'] = password
# users['admin'] = logged_user_email
UserHistory.objects.create(
**users
)
elif check_user.count() > 0 and not check_user[0].date_joined.strftime('%Y-%m-%d') == datetime.now().strftime('%Y-%m-%d'):
# i insert it on database to make an integrity error it means this row is already exist
current_user = User.objects.create(
**users
)
else:
current_user = check_user[0]
try:
privilege_department_code = keys['Privilege_Department_Code']
privilege_department_code = Department.objects.get(
code=privilege_department_code
)
ccr = True if keys['Create_CR'] == 'Yes' else False
crt = True if keys['Create_Template'] == 'Yes' else False
view_all = True if keys['View_All_CR'] == 'Yes' else False
approve_cr = True if keys['Approve_CR'] == 'Yes' else False
privilege_object = {
"id_number": current_user,
"company_pivot": privilege_department_code.company,
"group_pivots": privilege_department_code,
"create_change_request": ccr,
"create_change_request_template": crt,
"view_all_change_request": view_all,
"approve_cr": approve_cr
}
AllowedCompany.objects.create(**privilege_object)
except IntegrityError as e:
return Response(
{"message": f"Duplicate user privilege at row {data + 2}"},
# {"message": str(e)},
status=status.HTTP_400_BAD_REQUEST
)
except ObjectDoesNotExist as e:
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)
return Response(
{"message": f"Record already exist at row {data + 2}"},
status=status.HTTP_400_BAD_REQUEST
)
except KeyError as e:
return Response(
{"message": f"Missing column {e.args[0]}"},
status=status.HTTP_400_BAD_REQUEST
)
except ObjectDoesNotExist as e:
return Response(
{"message": f"Department Does not Exist at row {data + 2}"},
status=status.HTTP_400_BAD_REQUEST
)
# except ValueError as e:
# return Response(
# {"message": f"Invalid department code. Please check at line {data + 2}"},
# status=status.HTTP_400_BAD_REQUEST
# )
send_mail = UserHistory.objects.filter(sent=False).values(
'name', 'username', 'email', 'password'
)
df = pd.DataFrame(send_mail)
df.to_csv("users.csv", index=False)
args = ["users.csv", logged_user_email]
main_threading(args, sender.batch_email_admin)
args = [send_mail, logged_user_email, etl.code]
main_threading(args, sender.batch_email_users)
return Response(
{"message": "File already uploaded"},
status=status.HTTP_201_CREATED
)
......@@ -88,7 +88,6 @@ class CompanyViewSet(viewsets.ModelViewSet):
partial = kwargs.pop('partial', False)
instance = self.get_object()
print(request.data)
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
......
from rest_framework import serializers
from app.entities.models import Delegation
class DelegationSerializer(serializers.ModelSerializer):
class Meta:
model = Delegation
fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
from django_filters import rest_framework as filters
from app.entities.models import Delegation
class DelegationFilterSet(filters.FilterSet):
class Meta:
model = Delegation
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 app.applicationlayer.utils import model_to_dict
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters import rest_framework as filters
from app.entities.models import Delegation, Department
from app.applicationlayer.utils import (
CustomPagination, status_message_response, log_save
)
from django_filters.rest_framework import DjangoFilterBackend
from app.applicationlayer.management.delegation import serializer
from app.applicationlayer.management.delegation.table_filters import DelegationFilterSet
from app.helper import decorators
class DelegationViewSet(viewsets.ModelViewSet):
queryset = Delegation.objects.all().order_by('-created')
serializer_class = serializer.DelegationSerializer
pagination_class = CustomPagination
lookup_field = 'code'
filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter)
filterset_class = DelegationFilterSet
ordering_fields = '__all__'
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 Delegation 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 Delegation 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):
message = {
'code': 400,
'status': 'failed',
'message': 'Delegation/s cannot delete, Please update instead'
}
return Response(message, status=status.HTTP_400_BAD_REQUEST)
@transaction.atomic
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', True)
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)
if not (old_instance['name'].lower() == 'vendor/implementor' or
old_instance['name'].lower() == 'requestor'):
self.perform_update(serializer)
new_instance = serializer.data
log_save(
enums.LogEnum.UPDATE.value,
enums.LogEntitiesEnum.DELEGATION.value,
old_instance['id'],
old_instance,
new_instance
)
return Response(serializer.data)
else:
message = {
'code': 400,
'status': 'failed',
'message': 'Default delegation cannot edit'
}
return Response(message, status=status.HTTP_400_BAD_REQUEST)
......@@ -89,7 +89,6 @@ class NotificationsViewset(meviewsets.ModelViewSet):
def seen(self, request, account_no=None, **kwargs):
try:
account_no = self.kwargs['account_no']
print(account_no)
models.Notification.objects.filter(account_no=account_no,
id__in=request.data['ids']).update(
......@@ -117,7 +116,6 @@ class NotificationsViewset(meviewsets.ModelViewSet):
def seenall(self, request, account_no=None, **kwargs):
try:
account_no = self.kwargs['account_no']
print(account_no)
models.Notification.objects.filter(account_no=account_no).update(
is_read=True,
......
......@@ -19,7 +19,6 @@ class UserManagementSerializer(serializers.ModelSerializer):
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')
......@@ -106,7 +105,6 @@ class UserManagementRetreiveSerializer(serializers.ModelSerializer):
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')
......
......@@ -68,9 +68,7 @@ class UsersManagementViewSet(viewsets.ModelViewSet):
@decorators.error_safe
def list(self, request, *args, **kwargs):
print(request.data['department__name'])
self.serializer_class = serializers.UserManagementRetreiveSerializer
# self.queryset = QuerySetHelper.Sort(self)
return super(UsersManagementViewSet, self).list(request)
@decorators.error_safe
......
......@@ -16,7 +16,8 @@ class AdminAccountSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
# fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
exclude = ('password',)
from rest_framework import serializers
from app.entities.models import Department
from app.entities.models import Department, Delegation
from app.applicationlayer.utils import model_to_dict
......@@ -16,3 +16,12 @@ class AdminDepartmentSerializer(serializers.ModelSerializer):
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
class DelegationSerializer(serializers.ModelSerializer):
class Meta:
model = Delegation
fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
\ No newline at end of file
......@@ -3,20 +3,23 @@ from rest_framework.response import Response
from app.applicationlayer.utils import model_to_dict
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters import rest_framework as filters
from app.entities.models import Department
from app.entities.models import Department, Delegation
from app.applicationlayer.utils import (
CustomPagination, status_message_response
)
from django_filters.rest_framework import DjangoFilterBackend
from app.applicationlayer.master.department import serializer
from app.applicationlayer.master.department.serializer import (
AdminDepartmentSerializer,
DelegationSerializer)
from app.applicationlayer.management.department.table_filters import DepartmentFilterSet
from app.helper.decorators import rms
from rest_framework.decorators import action
class AdminDepartmentViewSet(viewsets.ModelViewSet):
queryset = Department.objects.all().order_by('-created')
serializer_class = serializer.AdminDepartmentSerializer
serializer_class = AdminDepartmentSerializer
pagination_class = CustomPagination
lookup_field = 'code'
filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter)
......@@ -44,7 +47,6 @@ class AdminDepartmentViewSet(viewsets.ModelViewSet):
)
return self.get_paginated_response(message)
except Exception as e:
# serializer = self.get_serializer(queryset, many=True)
message = status_message_response(
400,
'failed',
......@@ -52,3 +54,34 @@ class AdminDepartmentViewSet(viewsets.ModelViewSet):
''
)
return Response(message)
@action(detail=True,
methods=['get'],
url_path='delegations',
name="Delegation Filtered List")
def delegations(self, request, *args, **kwargs):
try:
dept_code = kwargs['code']
queryset = Delegation.objects.filter(departments__code=dept_code)
page = self.paginate_queryset(queryset)
if page is not None:
self.serializer_class = DelegationSerializer
serializer = self.get_serializer(page, many=True)
message = status_message_response(
200,
'success',
'list of filtered delegations found',
serializer.data
)
return self.get_paginated_response(message)
except Exception as e:
message = status_message_response(
400,
'failed',
str(e),
''
)
return Response(message)
\ No newline at end of file
......@@ -7,8 +7,10 @@ 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.account.views import UserViewSet
from app.applicationlayer.management.batchupload.views import BatchUploadViewSet
from app.businesslayer.company.views import AdminCompanyViewSet
from app.applicationlayer.management.notification.views import NotificationsViewset
from app.applicationlayer.management.delegation.views import DelegationViewSet
from app.applicationlayer.download.accounts.views import UserDownloadRequest
from app.applicationlayer.download.department.views import DepartmentDownloadRequest
......@@ -26,6 +28,8 @@ router.register(r'notifications', NotificationsViewset)
router.register(r'user-download', UserDownloadRequest)
router.register(r'department-download', DepartmentDownloadRequest)
router.register(r'company-download', CompanyDownloadRequest)
router.register(r'delegations', DelegationViewSet)
router.register(r'extract-transform-load', BatchUploadViewSet)
urlpatterns = (
path('', include(router.urls)),
......
......@@ -54,6 +54,25 @@ class CustomPagination(PageNumberPagination):
})
class PaginationForETL(PageNumberPagination):
page_size = 100
max_page_size = 3000
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):
......@@ -161,7 +180,8 @@ def send_broadcast_message(room_name, sender, message):
ws.close()
def notification_create(form_code, message, account_no, sender_account_no):
def notification_create(form_code, message, account_no,
sender_account_no, app):
try:
......@@ -170,7 +190,7 @@ def notification_create(form_code, message, account_no, sender_account_no):
notif_type='TASK',
message=message,
is_read=False,
app='APP-20190909-0000002',
app=app,
account_no=account_no,
sender_account_no=sender_account_no
)
......@@ -184,12 +204,6 @@ def notification_create(form_code, message, account_no, sender_account_no):
'NEW NOTIFICATIONS'
)
# message = {
# 'code': 200,
# 'status': 'success',
# 'message': 'Notification successfully created!',
# }
# return Response(message, status=status.HTTP_200_OK)
return True
except Exception as e:
......
......@@ -13,14 +13,39 @@ from django.http import Http404
from django.db.models import Q
from app.applicationlayer.cms.utils_cr import (
number_generator, crhistory_save, entity_log_bulk,
crhistory_log_bulk_delete
number_generator,
crhistory_save,
entity_log_bulk,
crhistory_log_bulk_delete,
crhistory_log_bulk_delete_masterattach,
send_mail_requestor,
next_approver_email,
send_mail_vendor,
crhistory_create_save,
reminder_trigger_save,
overdue_trigger_save,
reset_autoemail_tables,
cancelled_user_trigger,
send_mail_approver
)
from app.applicationlayer.utils import model_to_dict
from app.entities import enums, models
from app.applicationlayer.utils import log_save, CustomPagination
from app.applicationlayer.cms.template import serializers
from django.db.models import Min
from django.conf import settings
APPROVER_MESSAGE = settings.APPROVER_MESSAGE
REQUESTOR_MESSAGE = settings.REQUESTOR_MESSAGE
REQUESTOR_REJECT_MESSAGE = settings.REQUESTOR_REJECT_MESSAGE
VENDOR_ACKNOWLEDGE_MESSAGE = settings.VENDOR_ACKNOWLEDGE_MESSAGE
REQUESTOR_ACKNOWLEDGE_MESSAGE = settings.REQUESTOR_ACKNOWLEDGE_MESSAGE
REQUESTOR_COMPLETION_MESSAGE = settings.REQUESTOR_COMPLETION_MESSAGE
VENDOR_ACCEPTANCE_MESSAGE = settings.VENDOR_ACCEPTANCE_MESSAGE
VENDOR_REJECT_MESSAGE = settings.VENDOR_REJECT_MESSAGE
REVISED_MESSAGE = settings.REVISED_MESSAGE
CANCEL_MESSAGE = settings.CANCEL_MESSAGE
APPROVER_REJECT_MESSAGE = settings.APPROVER_REJECT_MESSAGE
def list_by_user(user_id_number):
......@@ -343,7 +368,7 @@ def attachment_add_edit_delete(form_request_body,
)
if delete_query.count() > 0:
crhistory_log_bulk_delete(delete_query,
crhistory_log_bulk_delete_masterattach(delete_query,
entity,
queryset,
form_code,
......@@ -388,15 +413,13 @@ def attachment_add_edit_delete(form_request_body,
serializer = serializer_data(frm_instance,
data=data,
partial=partial,
context={"request":self.request})
context={"request": self.request})
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
new_instance = serializer.data
#
# print(new_instance)
crhistory_save(
batch_no,
main_action,
......@@ -442,25 +465,322 @@ def check_vendor_level(position, routing_level, form_code):
query = models.ChangeRequestFormApprovers.objects.filter(
form_code=form_code,
level=int(routing_level),
delegation='Vendor/Implementor'
)
delegation__name='Vendor/Implementor'
).first()
return query
elif position == 'last':
query = models.ChangeRequestFormApprovers.objects.filter(
form_code=form_code,
delegation='Vendor/Implementor'
delegation__name='Vendor/Implementor'
).order_by('level').last()
return query
elif position == 'prev':
query = models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) &
Q(action='Completed') &
Q(delegation='Vendor/Implementor') &
Q(level__lte=int(level))
Q(delegation__name='Vendor/Implementor') &
Q(level__lte=int(routing_level))
)
return query
def update_form_approver(form_code, level, apprv_type, date_now):
if apprv_type == 'next':
# update next approver details
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) & Q(level=int(level))
).update(
date_sent=date_now,
is_action=True
)
elif apprv_type == 'current':
# update current approver details
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) & Q(level=int(level))
).update(
is_action=False
)
# def cr_routing_actions(approver_instance):
def update_form_header_status(form_code, status):
models.ChangeRequestFormHeader.objects.filter(
form_code=form_code
).update(status=status)
return True
def cr_routing_actions(approver_instance, current_user, move_to_level):
form_code = approver_instance['form_code']
delegation = approver_instance['delegation']['name']
action = approver_instance['action'].lower()
level = approver_instance['level']
next_level = int(approver_instance['level']) + 1
remarks = approver_instance['remarks']
if approver_instance['action'].lower() == 'approved':
the_next_vendor = check_vendor_level(
'next', next_level, form_code)
if the_next_vendor:
the_last_vendor = check_vendor_level(
'last', level, form_code)
# changed form status to Approved
if the_next_vendor == the_last_vendor:
update_form_header_status(form_code, 'Approved')
# NOTIF MSG FOR REQUESTOR
requestor_notification_msg = REQUESTOR_MESSAGE.split(';')[0]
# SEND EMAIL AND NOTIF TO REQUESTOR
send_mail_requestor(
current_user, form_code, delegation,
requestor_notification_msg, action,
remarks, level
)
next_approver_email(form_code, next_level)
date_now = datetime.now()
# update next approver details
update_form_approver(form_code, next_level, 'next', date_now)
# update current approver details
update_form_approver(form_code, level, 'current', date_now)
#save details for reminder trigger
reminder_trigger_save(form_code, date_now, date_now)
elif approver_instance['action'].lower() == 'rejected':
# reject from requestor action
if delegation.lower() == 'requestor':
notification_msg = REVISED_MESSAGE.split(';')[0]
# send reject email to vendor
send_mail_vendor(
current_user, form_code, delegation,
notification_msg, action,
remarks, level
)
prev_level = int(level) - 1
# reset last vendor details
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) &
Q(level=int(prev_level))
).update(
is_action=True,
action='Acknowledged',
action_date=datetime.now(),
date_sent=datetime.now()
)
else:
back_to_approver = models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) &
Q(level=move_to_level) &
(~Q(action=None) | Q(delegation__name='Requestor'))
).first()
if back_to_approver.delegation.name.lower() == 'requestor':
requestor_notification_msg = REQUESTOR_REJECT_MESSAGE.split(';')[0]
# SEND EMAIL AND NOTIF TO REQUESTOR
send_mail_requestor(
current_user, form_code, delegation,
requestor_notification_msg, action,
remarks, level
)
update_form_header_status(form_code, 'Rejected')
elif back_to_approver.delegation.name.lower() == 'vendor/implementor':
vendor_notification_msg = REVISED_MESSAGE.split(';')[0]
# send reject email to vendor
send_mail_vendor(
current_user, form_code, delegation,
vendor_notification_msg, action,
remarks, level
)
requestor_notification_msg = REQUESTOR_REJECT_MESSAGE.split(';')[0]
# SEND EMAIL AND NOTIF TO REQUESTOR
send_mail_requestor(
current_user, form_code, delegation,
requestor_notification_msg, action,
remarks, level
)
# reset selected vendor details
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) &
Q(level=int(move_to_level))
).update(
is_action=True,
action='Acknowledged',
action_date=datetime.now(),
date_sent=datetime.now()
)
else:
approver_code = back_to_approver.user.code
approver_notification_msg = APPROVER_REJECT_MESSAGE.split(';')[0]
send_mail_approver(
current_user, form_code, delegation,
approver_notification_msg, action, remarks,
level, approver_code
)
requestor_notification_msg = REQUESTOR_REJECT_MESSAGE.split(';')[0]
# SEND EMAIL AND NOTIF TO REQUESTOR
send_mail_requestor(
current_user, form_code, delegation,
requestor_notification_msg, action,
remarks, level
)
# reset selected vendor details
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) &
Q(level=int(move_to_level))
).update(
is_action=True,
action=None,
action_date=None,
date_sent=datetime.now()
)
models.ChangeRequestFormApprovers.objects.filter(
Q(form_code=form_code) & Q(level__gt=int(move_to_level))
).update(
is_action=False,
action=None,
remarks=None,
action_date=None,
date_sent=None
)
elif approver_instance['action'].lower() == 'completed':
the_last_vendor = check_vendor_level(
'last', level, form_code)
if (the_last_vendor and current_user == the_last_vendor.user.code and
level == the_last_vendor.level):
update_form_header_status(form_code, 'Approved')
else:
the_next_vendor = check_vendor_level(
'next', next_level, form_code)
if the_next_vendor:
if the_next_vendor.user.code == the_last_vendor.user.code:
update_form_header_status(form_code, 'Approved')
else:
update_form_header_status(form_code, 'Pending')
next_approver_email(form_code, next_level)
date_now = datetime.now()
# update next approver details
update_form_approver(form_code, next_level, 'next', date_now)
# update current approver details
update_form_approver(form_code, level, 'current', date_now)
# EMAIL CODE FOR REQUESTOR
requestor_notification_msg = REQUESTOR_COMPLETION_MESSAGE.split(';')[0]
send_mail_requestor(
current_user, form_code, delegation,
requestor_notification_msg, action,
remarks, level
)
elif action.lower() == 'acknowledged':
# EMAIL CODE FOR REQUESTOR
requestor_notification_msg = REQUESTOR_ACKNOWLEDGE_MESSAGE.split(';')[0]
send_mail_requestor(
current_user, form_code, delegation,
requestor_notification_msg, action,
remarks, level
)
elif action.lower() == 'accepted':
update_form_header_status(form_code, 'Completed & Accepted')
# EMAIL CODE FOR VENDOR
requestor_notification_msg = VENDOR_ACCEPTANCE_MESSAGE.split(';')[0]
send_mail_vendor(
current_user, form_code, delegation,
requestor_notification_msg, action,
remarks, level
)
date_now = datetime.now()
# update current approver details
update_form_approver(form_code, level, 'current', date_now)
elif action.lower() == 'cancelled':
# send email and notif to anyone who received an email about the change request
cancelled_user_trigger(form_code, action, level)
# changed form status to cancelled
update_form_header_status(form_code, 'Cancelled')
date_now = datetime.now()
# update is_action for current level
update_form_approver(form_code, level, 'current', date_now)
reset_autoemail_tables(form_code)
return True
......@@ -29,6 +29,7 @@ class GenerateCode(Enum):
COMPANY = 'COMPANY'
DEPARTMENT = 'DEPARTMENT'
USER = 'USER'
DELEGATION = 'DELEGATION'
NOTIFICATION = 'NOTIF'
TEMPLATE = 'TMP'
TMP_APPROVER = 'TMPAPR'
......@@ -40,6 +41,7 @@ class GenerateCode(Enum):
FORM_STAKE = 'FRMSTK'
FORM_ATTACH = 'FRMATCH'
FORM_DETAIL = 'FRMDETAIL'
ETL = 'ETL'
ASSET_GROUP = 'AMSGRP'
......@@ -62,6 +64,7 @@ class LogEntitiesEnum(Enum):
COMPANY = "COMPANY"
DEPARTMENT = "DEPARTMENT"
MODULE = "MODULE"
DELEGATION = "DELEGATION"
ChangeRequestTemplateHeader = "ChangeRequestTemplateHeader"
ChangeRequestTemplateApprovers = "ChangeRequestTemplateApprovers"
ChangeRequestTemplateStakeHolders = "ChangeRequestTemplateStakeHolders"
......
# Generated by Django 2.2 on 2019-11-08 14:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('entities', '0027_assetgroup'),
]
operations = [
migrations.AddField(
model_name='application',
name='excel_code',
field=models.CharField(default='rms', max_length=255),
preserve_default=False,
),
]
# Generated by Django 2.2 on 2019-10-29 15:13
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('entities', '0027_assetgroup'),
]
operations = [
migrations.AddField(
model_name='canceltrigger',
name='cancel_type',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='remindertrigger',
name='form_code',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='entities.ChangeRequestFormHeader', to_field='form_code'),
),
migrations.AlterField(
model_name='canceltrigger',
name='frm_approver',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='entities.ChangeRequestFormApprovers', to_field='code'),
),
]
# Generated by Django 2.2 on 2019-11-04 12:28
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('entities', '0028_auto_20191029_1513'),
]
operations = [
migrations.AlterModelTable(
name='canceltrigger',
table='trigger_cancel',
),
migrations.AlterModelTable(
name='overduetrigger',
table='trigger_overdue',
),
migrations.AlterModelTable(
name='remindertrigger',
table='trigger_reminder',
),
]
# Generated by Django 2.2 on 2019-11-08 15:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('entities', '0028_application_excel_code'),
]
operations = [
migrations.CreateModel(
name='UserHistory',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('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)),
('name', models.CharField(max_length=255)),
('username', models.CharField(max_length=255, unique=True)),
('email', models.EmailField(max_length=255)),
('password', models.CharField(max_length=255)),
('sent', models.BooleanField(default=False)),
],
options={
'db_table': 'user_history',
},
),
]
# Generated by Django 2.2 on 2019-11-04 15:07
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('entities', '0029_auto_20191104_1228'),
]
operations = [
migrations.AlterModelOptions(
name='assetgroup',
options={'ordering': ['-created']},
),
]
# Generated by Django 2.2 on 2019-11-07 12:39
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('entities', '0030_auto_20191104_1507'),
]
operations = [
migrations.CreateModel(
name='Delegation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('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)),
('code', models.CharField(max_length=255, unique=True)),
('name', models.CharField(max_length=255, unique=True)),
],
options={
'db_table': 'delegations',
},
),
migrations.AlterField(
model_name='changerequestformapprovers',
name='delegation',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='entities.Delegation', to_field='code'),
),
migrations.AlterField(
model_name='changerequesttemplateapprovers',
name='delegation',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='entities.Delegation', to_field='code'),
),
migrations.AddField(
model_name='department',
name='delegation',
field=models.ManyToManyField(to='entities.Delegation'),
),
]
# Generated by Django 2.2 on 2019-11-08 11:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('entities', '0031_auto_20191107_1239'),
]
operations = [
migrations.AddField(
model_name='allowedcompany',
name='approve_cr',
field=models.BooleanField(default=True),
),
migrations.AlterField(
model_name='entitylog',
name='entity',
field=models.CharField(choices=[('USER', 'USER'), ('APPLICATION', 'APPLICATION'), ('COMPANY', 'COMPANY'), ('DEPARTMENT', 'DEPARTMENT'), ('MODULE', 'MODULE'), ('DELEGATION', 'DELEGATION'), ('ChangeRequestTemplateHeader', 'ChangeRequestTemplateHeader'), ('ChangeRequestTemplateApprovers', 'ChangeRequestTemplateApprovers'), ('ChangeRequestTemplateStakeHolders', 'ChangeRequestTemplateStakeHolders'), ('ChangeRequestTemplateAttachments', 'ChangeRequestTemplateAttachments'), ('ChangeRequestTemplateDetails', 'ChangeRequestTemplateDetails'), ('ChangeRequestFormHeader', 'ChangeRequestFormHeader'), ('ChangeRequestFormApprovers', 'ChangeRequestFormApprovers'), ('ChangeRequestFormStakeHolders', 'ChangeRequestFormStakeHolders'), ('ChangeRequestFormAttachments', 'ChangeRequestFormAttachments'), ('ChangeRequestFormDetails', 'ChangeRequestFormDetails')], default='Add', max_length=50),
),
]
# Generated by Django 2.2 on 2019-11-08 17:25
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('entities', '0032_auto_20191108_1109'),
('entities', '0029_userhistory'),
]
operations = [
]
# Generated by Django 2.2 on 2019-11-08 19:24
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('entities', '0033_merge_20191108_1725'),
]
operations = [
migrations.AlterField(
model_name='allowedcompany',
name='approve_cr',
field=models.BooleanField(default=False),
),
]
# Generated by Django 2.2 on 2019-11-11 10:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('entities', '0034_auto_20191108_1924'),
]
operations = [
migrations.AddField(
model_name='changerequesttemplateapprovers',
name='is_default',
field=models.BooleanField(default=False),
),
]
# Generated by Django 2.2 on 2019-11-11 15:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('entities', '0035_changerequesttemplateapprovers_is_default'),
]
operations = [
migrations.AlterField(
model_name='department',
name='delegation',
field=models.ManyToManyField(related_name='departments', to='entities.Delegation'),
),
]
# Generated by Django 2.2 on 2019-11-12 14:03
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('entities', '0036_auto_20191111_1549'),
]
operations = [
migrations.AlterField(
model_name='changerequestformapprovers',
name='delegation',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='entities.Delegation', to_field='code'),
),
migrations.AlterField(
model_name='changerequesttemplateapprovers',
name='delegation',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='entities.Delegation', to_field='code'),
),
]
# Generated by Django 2.2 on 2019-11-12 14:57
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('entities', '0037_auto_20191112_1403'),
]
operations = [
migrations.AlterField(
model_name='changerequestformapprovers',
name='delegation',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='entities.Delegation', to_field='code'),
),
migrations.AlterField(
model_name='changerequesttemplateapprovers',
name='delegation',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='entities.Delegation', to_field='code'),
),
]
# Generated by Django 2.2 on 2019-11-13 10:16
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('entities', '0038_auto_20191112_1457'),
]
operations = [
migrations.CreateModel(
name='ExtractTransformLoad',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('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)),
('file_name', models.CharField(max_length=255)),
('model_type', models.CharField(choices=[('APP', 'APP'), ('MODULE', 'MODULE'), ('COMPANY', 'COMPANY'), ('DEPARTMENT', 'DEPARTMENT'), ('USER', 'USER'), ('DELEGATION', 'DELEGATION'), ('NOTIF', 'NOTIF'), ('TMP', 'TMP'), ('TMPAPR', 'TMPAPR'), ('TMPSTK', 'TMPSTK'), ('TMPATCH', 'TMPATCH'), ('TMPDETAIL', 'TMPDETAIL'), ('FRM', 'FRM'), ('FRMAPR', 'FRMAPR'), ('FRMSTK', 'FRMSTK'), ('FRMATCH', 'FRMATCH'), ('FRMDETAIL', 'FRMDETAIL'), ('ETL', 'ETL'), ('AMSGRP', 'AMSGRP')], default='USER', max_length=100)),
('code', models.CharField(blank=True, max_length=255, null=True, unique=True)),
],
options={
'db_table': 'csv_filenames',
},
),
migrations.AddField(
model_name='userhistory',
name='file_name',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='extract_transform_load', to='entities.ExtractTransformLoad', to_field='code'),
),
]
# Generated by Django 2.2 on 2019-11-13 15:05
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('entities', '0039_auto_20191113_1016'),
]
operations = [
migrations.AddField(
model_name='userhistory',
name='deleted',
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name='userhistory',
name='username',
field=models.CharField(max_length=255),
),
]
# Generated by Django 2.2 on 2019-11-13 19:23
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('entities', '0040_auto_20191113_1505'),
]
operations = [
migrations.AlterModelTable(
name='extracttransformload',
table='extract_transform_load',
),
migrations.AlterModelTable(
name='userhistory',
table='extract_transform_load_user_history',
),
]
......@@ -32,7 +32,6 @@ class BaseAuditClass(models.Model):
modifiedby = models.CharField(max_length=255)
def save(self, *args, **kwargs):
# print('333')
if self.createdby and self.modifiedby:
# username = 'Anonymous User'
# self.createdby = username
......
......@@ -8,6 +8,9 @@ from datetime import datetime
from . import enums
from django.utils.text import slugify
from datetime import timedelta
import os
from django.conf import settings
# ********************* AUTH TABLES *********************
......@@ -27,6 +30,7 @@ class Application(AuditClass):
max_length=255
)
name = models.CharField(unique=True, max_length=255)
excel_code = models.CharField(max_length=255)
class Meta:
db_table = 'applications'
......@@ -85,6 +89,29 @@ class Module(AuditClass):
Module.objects.filter(id=self.id).update(code=code)
class Delegation(AuditClass):
code = models.CharField(
unique=True,
max_length=255
)
name = models.CharField(unique=True, max_length=255)
class Meta:
db_table = 'delegations'
def __str__(self):
return f'{self.name}'
def save(self, *args, **kwargs):
super(Delegation, self).save(*args, **kwargs)
code = number_generator(enums.GenerateCode.DELEGATION.value, self.id)
if self.code == '':
self.code = code
self.created = datetime.now()
self.save()
class Company(AuditClass):
code = models.CharField(
unique=True,
......@@ -103,7 +130,6 @@ class Company(AuditClass):
def save(self, *args, **kwargs):
super(Company, self).save(*args, **kwargs)
if self.code == 'com':
print(self.code)
code = enums.GenerateCode.APP.value
code = number_generator(enums.GenerateCode.COMPANY.value, self.id)
Company.objects.filter(id=self.id).update(code=code)
......@@ -128,6 +154,10 @@ class Department(AuditClass):
default='dept'
)
name = models.CharField(max_length=255)
delegation = models.ManyToManyField(
Delegation,
related_name='departments'
)
class Meta:
db_table = 'departments'
......@@ -213,6 +243,57 @@ class RolePermission(AuditClass):
db_table = 'role_permissions'
class ExtractTransformLoad(AuditClass):
file_name = models.CharField(max_length=255)
model_type = models.CharField(
choices=[(tag.value, tag.value) for tag in enums.GenerateCode],
default=enums.GenerateCode.USER.value,
max_length=100
)
code = models.CharField(
unique=True,
max_length=255,
blank=True,
null=True
)
class Meta:
db_table = 'extract_transform_load'
def __str__(self):
return f'{self.file_name}'
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()
class UserHistory(AuditClass):
file_name = models.ForeignKey(
ExtractTransformLoad,
to_field='code',
related_name='extract_transform_load',
on_delete=models.DO_NOTHING,
blank=True,
null=True
)
name = models.CharField(max_length=255)
username = models.CharField(max_length=255)
email = models.EmailField(max_length=255, unique=False)
password = models.CharField(max_length=255)
sent = models.BooleanField(default=False)
deleted = models.BooleanField(default=False)
class Meta:
db_table = 'extract_transform_load_user_history'
class User(AbstractUser):
application = models.ManyToManyField(
Application
......@@ -372,33 +453,25 @@ class BaseHeader(models.Model):
Company,
on_delete=models.PROTECT,
to_field='code')
requested_to_department = models.ForeignKey(
Department,
on_delete=models.PROTECT,
to_field='code')
requested_to_user = models.ForeignKey(
User,
on_delete=models.PROTECT,
to_field='code')
requested_to_template_name = models.CharField(max_length=255)
requested_to_objective = models.CharField(
max_length=255,
blank=True,
null=True)
requested_to_priority = models.CharField(max_length=255)
description = models.CharField(
max_length=255,
blank=True,
null=True)
created = models.DateTimeField(auto_now_add=True)
is_active = models.BooleanField(default=True)
class Meta:
......@@ -407,15 +480,18 @@ class BaseHeader(models.Model):
class BaseApprover(models.Model):
level = models.IntegerField()
user = models.ForeignKey(
User,
blank=True,
null=True,
on_delete=models.PROTECT,
to_field='code')
delegation = models.CharField(max_length=50, blank=True, null=True)
delegation = models.ForeignKey(
Delegation,
blank=True,
null=True,
on_delete=models.CASCADE,
to_field='code')
created = models.DateTimeField(
blank=True,
null=True)
......@@ -450,14 +526,28 @@ class MasterAttachment(models.Model):
null=True)
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)
super(MasterAttachment, self).delete(*args,**kwargs)
class Meta:
db_table = 'master_attachments'
def delete(self, *args, **kwargs):
# self.url.delete()
# super().delete(*args, **kwargs)
os.remove(os.path.join(settings.MEDIA_ROOT, self.url.name))
super(MasterAttachment, self).delete(*args, **kwargs)
class BaseAttachment(models.Model):
attachment_type = models.CharField(max_length=255)
attachment_name = models.CharField(max_length=255)
file_name = models.CharField(
max_length=255,
blank=True,
......@@ -494,7 +584,6 @@ class BaseDetails(models.Model):
blank=True,
null=True
)
created = models.DateTimeField(
blank=True,
null=True)
......@@ -513,23 +602,19 @@ class ChangeRequestTemplateHeader(BaseHeader):
template_no = models.CharField(
unique=True,
max_length=255)
requested_to_template_id = models.CharField(
max_length=255,
unique=True)
created_by_user = models.ForeignKey(
User,
on_delete=models.PROTECT,
to_field='code',
related_name='created_by_user')
created_by_department = models.ForeignKey(
Department,
on_delete=models.PROTECT,
to_field='code',
related_name='created_by_department')
requested_to_target_date = models.IntegerField()
class Meta:
......@@ -569,6 +654,9 @@ class ChangeRequestTemplateApprovers(BaseApprover):
null=True,
on_delete=models.PROTECT,
to_field='code')
is_default = models.BooleanField(
default=False
)
class Meta:
db_table = 'change_request_template_approvers'
......@@ -699,7 +787,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,
......@@ -1022,6 +1109,7 @@ class AllowedCompany(models.Model):
create_change_request = models.BooleanField(default=True)
create_change_request_template = models.BooleanField(default=True)
view_all_change_request = models.BooleanField(default=True)
approve_cr = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
deleted_at = models.DateTimeField(null=True, blank=True)
......@@ -1052,9 +1140,15 @@ class ReminderTrigger(models.Model):
blank=True)
is_sent = models.BooleanField(
default=False)
form_code = models.ForeignKey(
ChangeRequestFormHeader,
on_delete=models.PROTECT,
to_field='form_code',
null=True,
blank=True)
class Meta:
db_table = 'reminder_trigger'
db_table = 'trigger_reminder'
class CancelTrigger(models.Model):
......@@ -1065,7 +1159,9 @@ class CancelTrigger(models.Model):
frm_approver = models.ForeignKey(
ChangeRequestFormApprovers,
on_delete=models.PROTECT,
to_field='code')
to_field='code',
blank=True,
null=True)
auto_cancel_date = models.DateTimeField(
null=True,
blank=True)
......@@ -1074,9 +1170,13 @@ class CancelTrigger(models.Model):
date_submitted_last_approver = models.DateTimeField(
null=True,
blank=True)
cancel_type = models.CharField(
null=True,
blank=True,
max_length=255)
class Meta:
db_table = 'cancel_trigger'
db_table = 'trigger_cancel'
class OverdueTrigger(models.Model):
......@@ -1091,7 +1191,7 @@ class OverdueTrigger(models.Model):
default=False)
class Meta:
db_table = 'overdue_trigger'
db_table = 'trigger_overdue'
"""
......@@ -1116,6 +1216,7 @@ class AssetGroup(models.Model):
class Meta:
db_table = 'asset_groups'
ordering = ['-created']
def __str__(self):
return f'{self.code}'
......
......@@ -145,7 +145,8 @@ class rms:
@wraps(function)
def wrapper(self, request, *args, **kwargs):
if rms.user_type(self) == rms.enums_company:
if rms.user_type(self) == rms.enums_company or rms.user_type(self) == rms.enums_department:
id = rms.user(self).department.company.id
self.queryset = self.queryset.filter(
......
import os
from django.core.mail import send_mail
from django.core.mail import send_mail, EmailMessage
from app.entities import models
from django.conf import settings
from django.core import mail as email_connection
from django.db import transaction
# from weasyprint import HTML
from io import BytesIO
from django.http import HttpResponse
from django.template.loader import get_template
from xhtml2pdf import pisa
from email.mime.text import MIMEText
def to_pdf():
F = open(os.path.join(settings.EMAIL_TEMPLATES_ROOT, 'RMS-NEWUSER.html'), 'r')
result = BytesIO()
pdf = pisa.pisaDocument(F, result)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return None
@transaction.atomic
def batch_email_users(args):
connection = email_connection.get_connection()
messages = []
connection.open()
for data in args[0].iterator():
name = data['name']
username = data['username']
password = data['password']
recipient = data['email']
admin = args[1]
F = open(os.path.join(settings.EMAIL_TEMPLATES_ROOT, 'RMS-NEWUSER.html'), 'r')
FC = F.read()
FC = FC.replace('{name}', name)
FC = FC.replace('{username}', username)
FC = FC.replace('{password}', password)
FC = FC.replace('{url}', settings.FRONT_END_URL + '/cms/profile')
send_mail(
subject='Resource Management System: Welcome!',
message='',
from_email=settings.EMAIL_DEFAULT_SENDER,
recipient_list=(recipient,),
html_message=FC,
fail_silently=False
)
models.UserHistory.objects.filter(username=username).update(sent=True)
connection.close()
return True
def batch_email_admin(args):
filename = args[0]
recipient = args[1]
body = """
Dear Admin,
Please see the attached file as your reference for the recent bulk users you have uploaded as an Administrator in RMS.
This email and any files transmitted with it are confidential and may contain privileged and confidential information,
including personal information protected by privacy laws.
It is intended only for the use of the individual or entity to whom they are addressed.
"""
msg = MIMEText(body)
email = EmailMessage(
'Resource Management System: Bulk Users!',
body,
settings.EMAIL_DEFAULT_SENDER,
[recipient]
)
email.attach_file(filename)
email.send()
os.remove(filename)
# def account_created(args, username, password, receiver) :
def account_created(args):
name = args[0]
username = args[1]
......@@ -51,20 +125,7 @@ def account_created(args):
def cronjob(args):
# name = args[0]
# username = args[1]
# password = args[2]
# recipient = args[3]
# admin = args[4]
# F = open(os.path.join(settings.EMAIL_TEMPLATES_ROOT, 'RMS-NEWUSER.html'), 'r')
# FC = F.read()
# FC = FC.replace('{name}', name)
# FC = FC.replace('{username}', username)
# FC = FC.replace('{password}', password)
# FC = FC.replace('{url}', settings.FRONT_END_URL + '/cms/profile') #changed
try:
send_mail(
subject='Resource Management System: Welcome!',
......@@ -145,24 +206,6 @@ def forgot_password(args):
)
# def password_changed(username, date, receiver) :
# F = open(os.path.join(settings.EMAIL_TEMPLATES_ROOT, 'password-changed.html'), 'r')
# FC = F.read()
# FC = FC.replace('[Username]', username)
# FC = FC.replace('[Datetime]', date)
# FC = FC.replace('[URL]', settings.FRONT_END_URL)
# send_mail(
# subject='OB RMS: Password Changed!',
# message='',
# from_email=settings.EMAIL_DEFAULT_SENDER,
# recipient_list=[receiver,],
# html_message=FC
# )
def admin_changepassword(args):
name = args[0]
username = args[1]
......@@ -188,344 +231,9 @@ def admin_changepassword(args):
)
# def account_created(username, password, receiver) :
# F = open(os.path.join(settings.EMAIL_TEMPLATES_ROOT, 'account-created.html'), 'r')
# FC = F.read()
# FC = FC.replace('[Username]', username)
# FC = FC.replace('[Password]', password)
# FC = FC.replace('[URL]', settings.FRONT_END_URL)
# send_mail(
# subject='OB IMS: Welcome!',
# message='',
# from_email=settings.EMAIL_DEFAULT_SENDER,
# recipient_list=[receiver,],
# html_message=FC
# )
# def stock_requisition_new(sr_id,
# sr_no,
# requestor,
# requested_on,
# project,
# remarks,
# receiver,
# requested_items=[],
# purchase_items=[],
# required_date=None):
# F = open(os.path.join(settings.EMAIL_TEMPLATES_ROOT, 'stock-requisition.html'), 'r')
# FC = F.read()
# FC = FC.replace('[SR No]', sr_no)
# FC = FC.replace('[Requestor]', requestor)
# FC = FC.replace('[Requested On]', requested_on)
# FC = FC.replace('[Project]', project)
# FC = FC.replace('[Remarks]', remarks)
# # PRINT SR ITEMS
# if requested_items and len(requested_items) > 0:
# appendedList = ''
# for item in requested_items :
# prodNo = str(item.product.product_no)
# prodName = str(item.product.name)
# brand = str(item.product.brand.name)
# qty = str(item.quantity)
# unit = str(item.product.unit_material.name)
# appendedList += '\t\t\t\t \
# <tr bgcolor="#FFFFFF"> \
# <td>' + prodNo + '</td> \
# <td>' + prodName + '</td> \
# <td>' + brand + '</td> \
# <td>' + qty + '</td> \
# <td>' + unit + '</td> \
# </tr>'
# FC = FC.replace('<tr bgcolor="#FFFFFF" id="sr">\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n </tr>', appendedList)
# # PRINT PR ITEMS
# if purchase_items and len(purchase_items) > 0 :
# FC = FC.replace('[Required Date]', required_date)
# appendedList = ''
# for item in purchase_items :
# prodNo = str(item.product.product_no)
# prodName = str(item.product.name)
# brand = str(item.product.brand.name)
# qty = str(item.quantity)
# unit = str(item.product.unit_material.name)
# appendedList += '\t\t\t\t \
# <tr bgcolor="#FFFFFF"> \
# <td>' + prodNo + '</td> \
# <td>' + prodName + '</td> \
# <td>' + brand + '</td> \
# <td>' + qty + '</td> \
# <td>' + unit + '</td> \
# </tr>'
# FC = FC.replace('<tr bgcolor="#FFFFFF" id="pr">\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n </tr>', appendedList)
# urlApprove = f"{settings.FRONT_END_URL}/{'transaction/requisition/approve'}/{sr_id}/basic"
# urlReject = f"{settings.FRONT_END_URL}/{'transaction/requisition/reject'}/{sr_id}/basic"
# FC = FC.replace('ApproveToken', urlApprove)
# FC = FC.replace('RejectToken', urlReject)
# send_mail(
# subject='OB IMS: '+ sr_no +' by ' + requestor,
# message='',
# from_email=settings.EMAIL_DEFAULT_SENDER,
# recipient_list=[receiver,],
# html_message=FC
# )
# def stock_requisition_approve(sr_no,
# requestor,
# requestor_email,
# requested_on,
# requestor_contact,
# project,
# remarks,
# approved_by,
# approved_date,
# requested_items=[],
# purchase_items=[],
# required_date=None):
# # requested_items
# # LIST OF "RequisitionApproveItem"
# # purchase_items
# # LIST OF "PurchaseRequestApproveItem"
# F = open(os.path.join(settings.EMAIL_TEMPLATES_ROOT, 'stock-requisition-approved.html'), 'r')
# FC = F.read()
# FC = FC.replace('[SR No]', sr_no)
# FC = FC.replace('[Requestor]', requestor)
# FC = FC.replace('[Requested On]', requested_on)
# FC = FC.replace('[Project]', project)
# FC = FC.replace('[Remarks]', remarks)
# FC = FC.replace('[Approved By]', approved_by)
# FC = FC.replace('[Approved On]', approved_date)
# # PRINT SR ITEMS
# if len(requested_items) > 0 :
# appendedList = ''
# for item in requested_items :
# prodNo = item.requisition_product.product.product_no
# prodName = item.requisition_product.product.name
# brand = item.requisition_product.product.brand.name
# qty = str(item.quantity)
# unit = item.requisition_product.product.unit_material.name
# appendedList += '\t\t\t\t \
# <tr bgcolor="#FFFFFF"> \
# <td>' + prodNo + '</td> \
# <td>' + prodName + '</td> \
# <td>' + brand + '</td> \
# <td>' + qty + '</td> \
# <td>' + unit + '</td> \
# </tr>'
# FC = FC.replace('<tr bgcolor="#FFFFFF" id="sr">\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n </tr>', appendedList)
# # PRINT PR ITEMS
# if len(purchase_items) > 0 :
# FC = FC.replace('[Required Date]', required_date)
# appendedList = ''
# for item in purchase_items :
# prodNo = item.purchase_request_item.product.product_no
# prodName = item.purchase_request_item.product.name
# brand = item.purchase_request_item.product.brand.name
# qty = str(item.quantity)
# unit = item.purchase_request_item.product.unit_material.name
# appendedList += '\t\t\t\t \
# <tr bgcolor="#FFFFFF"> \
# <td>' + prodNo + '</td> \
# <td>' + prodName + '</td> \
# <td>' + brand + '</td> \
# <td>' + qty + '</td> \
# <td>' + unit + '</td> \
# </tr>'
# FC = FC.replace('<tr bgcolor="#FFFFFF" id="pr">\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n </tr>', appendedList)
# approver_emails = []
# # roles_receives = ['Receive Stock Requisition Authorization Email',
# # 'Allow Purchase Requests Authorisation',
# # 'Receive Stock Request Email',
# # 'Receive Purchase Request Email']
# # qry = models.User.objects.filter(user_roles__role__code__in=roles_receives).values('email').distinct()
# # for item in qry:
# # approver_emails.append(item['email'])
# approver_emails.append(requestor_email)
# if len(approver_emails) > 0:
# send_mail(
# subject='OB IMS Stock Request: '+ sr_no,
# message='',
# from_email=settings.EMAIL_DEFAULT_SENDER,
# recipient_list=approver_emails,
# html_message=FC
# )
# def stock_requisition_reject(sr_no,
# requestor,
# requestor_email,
# requested_on,
# project,
# remarks,
# rejected_reason,
# rejected_by,
# rejected_date,
# requested_items=[],
# purchase_items=[],
# required_date=None):
# # requested_items
# # LIST OF "RequisitionRejectItem"
# # purchase_items
# # LIST OF "PurchaseRequestRejectItem"
# F = open(os.path.join(settings.EMAIL_TEMPLATES_ROOT, 'stock-requisition-rejected.html'), 'r')
# FC = F.read()
# FC = FC.replace('[SR No]', sr_no)
# FC = FC.replace('[Requestor]', requestor)
# FC = FC.replace('[Requested On]', requested_on)
# FC = FC.replace('[Project]', project)
# FC = FC.replace('[Remarks]', remarks)
# FC = FC.replace('[Rejected By]', rejected_by)
# FC = FC.replace('[Rejected On]', rejected_date)
# FC = FC.replace('[Rejected Reason]', rejected_reason)
# # PRINT SR ITEMS
# if len(requested_items) > 0 :
# appendedList = ''
# for item in requested_items :
# prodNo = item.requisition_product.product.product_no
# prodName = item.requisition_product.product.name
# brand = item.requisition_product.product.brand.name
# qty = str(item.quantity)
# unit = item.requisition_product.product.unit_material.name
# appendedList += '\t\t\t\t \
# <tr bgcolor="#FFFFFF"> \
# <td>' + prodNo + '</td> \
# <td>' + prodName + '</td> \
# <td>' + brand + '</td> \
# <td>' + qty + '</td> \
# <td>' + unit + '</td> \
# </tr>'
# FC = FC.replace('<tr bgcolor="#FFFFFF" id="sr">\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n </tr>', appendedList)
# # PRINT PR ITEMS
# if len(purchase_items) > 0 :
# FC = FC.replace('[Required Date]', required_date)
# appendedList = ''
# for item in purchase_items :
# prodNo = item.purchase_request_item.product.product_no
# prodName = item.purchase_request_item.product.name
# brand = item.purchase_request_item.product.brand.name
# qty = str(item.quantity)
# unit = item.purchase_request_item.product.unit_material.name
# appendedList += '\t\t\t\t \
# <tr bgcolor="#FFFFFF"> \
# <td>' + prodNo + '</td> \
# <td>' + prodName + '</td> \
# <td>' + brand + '</td> \
# <td>' + qty + '</td> \
# <td>' + unit + '</td> \
# </tr>'
# FC = FC.replace('<tr bgcolor="#FFFFFF" id="pr">\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n <td>&nbsp;</td>\n </tr>', appendedList)
# approver_emails = []
# # roles_receives = ['Receive Stock Requisition Authorization Email', 'Allow Purchase Requests Authorisation', 'Receive Stock Request Email', 'Receive Purchase Request Email']
# # qry = models.User.objects.filter(user_roles__role__code__in=roles_receives).values('email').distinct()
# # for item in qry :
# # approver_emails.append(item['email'])
# approver_emails.append(requestor_email)
# if len(approver_emails) > 0:
# send_mail(
# subject='OB IMS: '+ sr_no +' by ' + requestor,
# message='',
# from_email=settings.EMAIL_DEFAULT_SENDER,
# recipient_list=approver_emails,
# html_message=FC
# )
# # def account_password_reset(username, password, receiver, date_reset) :
# # F = open(os.path.join(EMAIL_TEMPLATES_ROOT, 'reset-password.html'), 'r')
# # FC = F.read()
# # FC = FC.replace('[Username]', username)
# # FC = FC.replace('[Password]', password)
# # FC = FC.replace('[Reset Datetime]', date_reset)
# # send_mail(
# # subject='OB IMS: Password Reset!',
# # message='',
# # from_email=EMAIL_DEFAULT_SENDER,
# # recipient_list=[receiver,],
# # html_message=FC
# # )
# RMS-CRAPPROVED ; RMS-CRACKNOWLEDGE ; RMS-CRCOMPLETED ; RMS-CRACCEPTED ;
# RMS-CRREJECTED ; RMS-CRREJECTED-VENDOR
# RMS-CRREJECTED ; RMS-CRREJECTED-VENDOR ; RMS-CRREVISED ; RMS-CRCANCELLED-USERTRIGGER ;
# RMS-CRREJECTED-APPROVER
def routing_table_actions(args):
......@@ -546,7 +254,8 @@ def routing_table_actions(args):
recipient = args[11]
action_type = args[12]
delegation_type = args[13]
admin = args[14]
delegation_recipient = args[14]
admin = args[15]
if args[12].lower() == 'approved':
email_template = 'RMS-CRAPPROVED.html'
......@@ -561,11 +270,18 @@ def routing_table_actions(args):
email_template = 'RMS-CRACCEPTED.html'
subject = 'Resource Management System - Change Request Accepted'
elif args[12].lower() == 'rejected':
if args[14].lower() == 'requestor':
subject = 'Resource Management System - Change Request Rejected'
if args[13].lower() == 'requestor' or args[13].lower() == 'others':
email_template = 'RMS-CRREJECTED-VENDOR.html'
else:
email_template = 'RMS-CRREJECTED.html'
elif args[14].lower() == 'vendor':
subject = 'Resource Management System - Action Required for Change Request'
email_template = 'RMS-CRREVISED.html'
elif args[14].lower() == 'approver':
subject = 'Resource Management System - Action Required for Change Request'
email_template = 'RMS-CRREJECTED-APPROVER.html'
elif args[12].lower() == 'cancelled':
subject = 'Resource Management System - Change Request Cancelled'
email_template = 'RMS-CRCANCELLED-USERTRIGGER.html'
F = open(os.path.join(settings.EMAIL_TEMPLATES_ROOT, email_template), 'r')
......@@ -584,12 +300,6 @@ def routing_table_actions(args):
if args[12].lower() == 'rejected':
FC = FC.replace('{remarks}', remarks)
if email_template == 'RMS-CRREJECTED-VENDOR.html':
if args[13].lower() == 'requestor':
FC = FC.replace('{delegation}', 'requestor')
else:
FC = FC.replace('{delegation}', 'approver')
try:
send_mail(
......
<!DOCTYPE html>
<html>
<head>
<title>RMS: Change Request Cancelled</title>
</head>
<body style="font-family: arial;">
<h3>Resource Management System &#40;RMS&#41;</h3>
<h3 style="color:#888888;">Change Request Cancelled</h3><br>
<p>Dear {name},</p><br>
<p>A change request has been cancelled. Please see the details of the change request below.</p><br>
<b>Cancelled By</b><br>{action_by}<br><br>
<b>Routing Level</b><br>{routing_level}<br><br>
<b>Status</b><br>{status}<br><br><br>
<b>CR Number</b><br>{cr_number}<br><br>
<b>CR Name</b><br>{cr_name}<br><br>
<b>Company Requested To</b><br>{company_requestedto}<br><br>
<b>Department Requested To</b><br>{department_requestedto}<br><br>
<b>Priority Level</b><br>{priority_level}<br><br>
<p>Please click <u><a href="{url}" style="text-decoration:underline;color:#007bff;" target="_blank">here</a></u> to access your change request.</p><br>
<p>Sincerely,</p>
<p>RMS Team</p><br><br>
<p>Powered by</p>
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" class="img-responsive" style="width:150px;height:auto;" />
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>RMS: Change Request Rejected</title>
</head>
<body style="font-family: arial;">
<h3>Resource Management System &#40;RMS&#41;</h3>
<h3 style="color:#888888;">Change Request Rejected</h3><br>
<p>Dear {name},</p><br>
<p>A change request you have previously approved, has been re-submitted for your approval. Please see the details of the change request below.</p><br>
<b>Rejected By</b><br>{action_by}<br><br>
<b>Routing Level</b><br>{routing_level}<br><br>
<b>Status</b><br>{status}<br><br><br>
<b>CR Number</b><br>{cr_number}<br><br>
<b>CR Name</b><br>{cr_name}<br><br>
<b>Company Requested To</b><br>{company_requestedto}<br><br>
<b>Department Requested To</b><br>{department_requestedto}<br><br>
<b>Priority Level</b><br>{priority_level}<br><br>
<b>Remarks</b><br>{remarks}<br><br>
<p>Please click <u><a href="{url}" style="text-decoration:underline;color:#007bff;" target="_blank">here</a></u> to access your change request.</p><br>
<p>Sincerely,</p>
<p>RMS Team</p><br><br>
<p>Powered by</p>
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" class="img-responsive" style="width:150px;height:auto;" />
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>RMS: Change Request Rejected</title>
</head>
<body style="font-family: arial;">
<h3>Resource Management System &#40;RMS&#41;</h3>
<h3 style="color:#888888;">Change Request Rejected</h3><br>
<p>Dear {name},</p><br>
<p>A change request has been submitted for your acknowledgement to revise. Please see the details of the change request below.</p><br>
<b>Rejected By</b><br>{action_by}<br><br>
<b>Routing Level</b><br>{routing_level}<br><br>
<b>Status</b><br>{status}<br><br><br>
<b>CR Number</b><br>{cr_number}<br><br>
<b>CR Name</b><br>{cr_name}<br><br>
<b>Company Requested To</b><br>{company_requestedto}<br><br>
<b>Department Requested To</b><br>{department_requestedto}<br><br>
<b>Priority Level</b><br>{priority_level}<br><br>
<b>Remarks</b><br>{remarks}<br><br>
<p>Please click <u><a href="{url}" style="text-decoration:underline;color:#007bff;" target="_blank">here</a></u> to access your change request.</p><br>
<p>Sincerely,</p>
<p>RMS Team</p><br><br>
<p>Powered by</p>
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" class="img-responsive" style="width:150px;height:auto;" />
</body>
</html>
\ No newline at end of file
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
body {
font-family: Arial, Helvetica, sans-serif;
margin: 30px 200px 30px 200px;
font-size: 20px;
color: #8B8B8B
}
h1 {
padding-bottom: 80px;
font-size: 24px;
font-weight: 400;
}
h2 {
font-size: 22px;
font-weight: 400;
margin-bottom: 20px;
}
h3 {
font-size: 21px;
font-weight: 400;
margin-bottom: 20px;
margin-top: 20px;
}
.requested-to {
margin-top: 20px;
}
.input {
margin-bottom: 50px;
}
label {
font-size: 19px;
font-weight: 700;
color: #737373;
}
input {
display: block;
width: 500px;
color: #8B8B8B;
font-size: 19px;
border: none;
padding-top: 20px;
margin-bottom: 10px;
border-bottom: 2px #919191 solid;
}
table, th, td {
border-bottom: 1px solid #8B8B8B;
border-collapse: collapse;
}
th {
text-align: left;
}
tr {
border-bottom: 1px solid black;
}
td {
padding: 8px;
}
.table {
margin-top: 100px;
font-size: 16px;
padding: 50px;
background-color: #F2F2F2;
border-radius: 25px;
}
\ No newline at end of file
......@@ -48,6 +48,9 @@ REQUESTOR_ACKNOWLEDGE_MESSAGE = config['NOTIFICATION_EMAIL']['REQUESTOR_ACKNOWLE
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['DEV']['CATCH_EMAIL']
......
......@@ -45,6 +45,9 @@ REQUESTOR_ACKNOWLEDGE_MESSAGE = config['NOTIFICATION_EMAIL']['REQUESTOR_ACKNOWLE
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['LOCAL']['CATCH_EMAIL']
......
......@@ -48,6 +48,9 @@ REQUESTOR_ACKNOWLEDGE_MESSAGE = config['NOTIFICATION_EMAIL']['REQUESTOR_ACKNOWLE
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['PRODUCTION']['CATCH_EMAIL']
......
......@@ -47,6 +47,9 @@ REQUESTOR_ACKNOWLEDGE_MESSAGE = config['NOTIFICATION_EMAIL']['REQUESTOR_ACKNOWLE
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['STAGING']['CATCH_EMAIL']
......
......@@ -48,6 +48,9 @@ REQUESTOR_ACKNOWLEDGE_MESSAGE = config['NOTIFICATION_EMAIL']['REQUESTOR_ACKNOWLE
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['UAT']['CATCH_EMAIL']
......
......@@ -22,8 +22,6 @@ from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# path('admin/', admin.site.urls),
path('api-auth/', include('rest_framework.urls')),
......
......@@ -10,9 +10,8 @@ FRONT_END_URL =
AUTH_ACCESSS_TOKEN_TIMEOUT =
USER_DEFAULT_PASSWORD =
CATCH_EMAIL = gladys@tirsolutions.com
CR_LINK = http://stagingrms.oneberrysystem.com/cms/change-request/form/view
CR_LINK = http://staging.rms.oneberrysystem.com/cms/change-request/form/view
REALTIMESERVER_IP = 127.0.0.1:8000
CORS_ORIGIN_ALLOW_ALL = False
[UAT]
DATABASE_ENGINE = django.db.backends.mysql
......@@ -22,13 +21,12 @@ DATABASE_PASSWORD =
DATABASE_HOST =
DATABASE_PORT =
SESSION_TIMEOUT =
FRONT_END_URL = http://stagingrms.oneberrysystem.com
FRONT_END_URL = http://staging.rms.oneberrysystem.com
AUTH_ACCESSS_TOKEN_TIMEOUT =
USER_DEFAULT_PASSWORD =
CATCH_EMAIL = gladys@tirsolutions.com
CR_LINK = http://stagingrms.oneberrysystem.com/cms/change-request/form/view
CR_LINK = http://staging.rms.oneberrysystem.com/cms/change-request/form/view
REALTIMESERVER_IP = 127.0.0.1:8000
CORS_ORIGIN_ALLOW_ALL = False
[DEV]
DATABASE_ENGINE = django.db.backends.mysql
......@@ -44,7 +42,6 @@ USER_DEFAULT_PASSWORD =
CATCH_EMAIL = gladys@tirsolutions.com
CR_LINK = http://devweb.rmsv2.oneberrysystem.com/cms/change-request/form/view
REALTIMESERVER_IP = 127.0.0.1:8000
CORS_ORIGIN_ALLOW_ALL = True
[STAGING]
......@@ -54,21 +51,20 @@ DATABASE_USER =
DATABASE_PASSWORD =
DATABASE_HOST =
DATABASE_PORT =
SESSION_TIMEOUT = 30
FRONT_END_URL = http://stagingrms.oneberrysystem.com
SESSION_TIMEOUT =
FRONT_END_URL = http://staging.rms.oneberrysystem.com
AUTH_ACCESSS_TOKEN_TIMEOUT = 3600
USER_DEFAULT_PASSWORD = password
CATCH_EMAIL = gladys@tirsolutions.com
CR_LINK = http://stagingrms.oneberrysystem.com/cms/change-request/form/view
CATCH_EMAIL =
CR_LINK = http://staging.rms.oneberrysystem.com/cms/change-request/form/view
REALTIMESERVER_IP = 127.0.0.1:8000
CORS_ORIGIN_ALLOW_ALL = False
[LOCAL]
DATABASE_ENGINE = django.db.backends.mysql
DATABASE_NAME = rms_db
DATABASE_USER = root
DATABASE_PASSWORD = password
DATABASE_PASSWORD = 123
DATABASE_HOST = localhost
DATABASE_PORT = 3306
SESSION_TIMEOUT = 30
......@@ -78,10 +74,10 @@ 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
CORS_ORIGIN_ALLOW_ALL = True
[SETTINGS]
CONFIG = config.settings.staging
CONFIG = config.settings.local
BATCH_UPLOAD_FORMAT_FILENAME = instruction.pdf
[NOTIFICATION_EMAIL]
APPROVER_MESSAGE = has sent you an APPROVAL REQUEST for change request;RMS-ACTIONREQUIRED
......@@ -92,3 +88,6 @@ REQUESTOR_ACKNOWLEDGE_MESSAGE = has ACKNOWLEDGED the change request;RMS-CRACKNOW
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
\ No newline at end of file
{
"info": {
"_postman_id": "6221ba86-d38a-482d-b200-08062062700a",
"_postman_id": "e22e74b6-003f-42b5-a067-7e7cc1674e5e",
"name": "RMSv2",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
......@@ -497,7 +497,7 @@
],
"body": {
"mode": "raw",
"raw": "{\n \"name\": \"Business Develsopment\",\n \"company\": \"COMPANY-20190923-0000001\"\n}"
"raw": "{\n \"name\": \"Product Dept\",\n \"company\": \"COMPANY-20190923-0000001\",\n \"delegation\":[2, 3]\n}"
},
"url": {
"raw": "{{baseurl}}/management/departments/",
......@@ -971,6 +971,56 @@
},
"response": []
},
{
"name": "Upload ETL User",
"request": {
"method": "PUT",
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"type": "text",
"value": "application/json",
"disabled": true
}
],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "file",
"value": "",
"type": "file"
},
{
"key": "name",
"value": "test",
"type": "text",
"disabled": true
},
{
"key": "user",
"value": "USER-20190927-0000012",
"type": "text",
"disabled": true
}
]
},
"url": {
"raw": "{{baseurl}}/management/users/batch-upload/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"users",
"batch-upload",
""
]
}
},
"response": []
},
{
"name": "Change Password",
"request": {
......@@ -1020,15 +1070,338 @@
"raw": ""
},
"url": {
"raw": "{{baseurl}}/management/users/USER-20190920-0000028/reset-password/",
"raw": "{{baseurl}}/management/users/USER-20190920-0000028/reset-password/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"users",
"USER-20190920-0000028",
"reset-password",
""
]
}
},
"response": []
}
],
"protocolProfileBehavior": {},
"_postman_isSubFolder": true
},
{
"name": "download",
"item": [
{
"name": "company",
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [],
"url": {
"raw": "{{baseurl}}/management/company-download/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"company-download",
""
]
}
},
"response": []
},
{
"name": "account",
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [],
"url": {
"raw": "{{baseurl}}/management/user-download/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"user-download",
""
]
}
},
"response": []
},
{
"name": "department",
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [],
"url": {
"raw": "{{baseurl}}/management/user-download/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"user-download",
""
]
}
},
"response": []
}
],
"protocolProfileBehavior": {},
"_postman_isSubFolder": true
},
{
"name": "Delegation Management",
"item": [
{
"name": "List of Delegations",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseurl}}/management/delegations/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"delegations",
""
]
}
},
"response": []
},
{
"name": "View Delegation",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseurl}}/management/delegations/DELEGATION-20191107-0000002/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"delegations",
"DELEGATION-20191107-0000002",
""
]
}
},
"response": []
},
{
"name": "Create Delegation",
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"value": "application/json",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n\t\"name\": \"Head of Department\"\n}"
},
"url": {
"raw": "{{baseurl}}/management/delegations/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"delegations",
""
]
}
},
"response": []
},
{
"name": "Edit Delegation",
"request": {
"method": "PUT",
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"value": "application/json",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{\n\t\"name\": \"SOD/ODs\"\n}"
},
"url": {
"raw": "{{baseurl}}/management/delegations/DELEGATION-20191107-0000002/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"delegations",
"DELEGATION-20191107-0000002",
""
]
}
},
"response": []
},
{
"name": "Delete Delegation",
"request": {
"method": "DELETE",
"header": [],
"body": {
"mode": "raw",
"raw": ""
},
"url": {
"raw": "{{baseurl}}/management/delegations/DELEGATION-20191107-0000001/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"delegations",
"DELEGATION-20191107-0000001",
""
]
}
},
"response": []
}
],
"protocolProfileBehavior": {},
"_postman_isSubFolder": true
},
{
"name": "Extract Transform Load",
"item": [
{
"name": "User",
"item": [
{
"name": "download",
"item": [
{
"name": "User format",
"protocolProfileBehavior": {
"disableBodyPruning": true
},
"request": {
"method": "GET",
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"type": "text",
"value": "application/json",
"disabled": true
}
],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "file",
"value": "",
"type": "file"
},
{
"key": "name",
"value": "test",
"type": "text",
"disabled": true
},
{
"key": "user",
"value": "USER-20190927-0000012",
"type": "text",
"disabled": true
}
]
},
"url": {
"raw": "{{baseurl}}/management/extract-transform-load/user-format-download/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"extract-transform-load",
"user-format-download",
""
]
}
},
"response": []
},
{
"name": "User Instruction",
"protocolProfileBehavior": {
"disableBodyPruning": true
},
"request": {
"method": "GET",
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"type": "text",
"value": "application/json",
"disabled": true
}
],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "file",
"value": "",
"type": "file"
},
{
"key": "name",
"value": "test",
"type": "text",
"disabled": true
},
{
"key": "user",
"value": "USER-20190927-0000012",
"type": "text",
"disabled": true
}
]
},
"url": {
"raw": "{{baseurl}}/management/extract-transform-load/user-instruction/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"users",
"USER-20190920-0000028",
"reset-password",
"extract-transform-load",
"user-instruction",
""
]
}
......@@ -1040,24 +1413,48 @@
"_postman_isSubFolder": true
},
{
"name": "download",
"item": [
{
"name": "company",
"name": "Upload Users",
"request": {
"auth": {
"type": "noauth"
"method": "POST",
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"type": "text",
"value": "application/json",
"disabled": true
}
],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "file",
"value": "",
"type": "file"
},
{
"key": "name",
"value": "test",
"type": "text",
"disabled": true
},
{
"key": "user",
"value": "USER-20190927-0000012",
"type": "text",
"disabled": true
}
]
},
"method": "GET",
"header": [],
"url": {
"raw": "{{baseurl}}/management/company-download/",
"raw": "{{baseurl}}/management/extract-transform-load/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"company-download",
"extract-transform-load",
""
]
}
......@@ -1065,21 +1462,51 @@
"response": []
},
{
"name": "account",
"request": {
"auth": {
"type": "noauth"
"name": "List of filename",
"protocolProfileBehavior": {
"disableBodyPruning": true
},
"request": {
"method": "GET",
"header": [],
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"type": "text",
"value": "application/json",
"disabled": true
}
],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "file",
"value": "",
"type": "file"
},
{
"key": "name",
"value": "test",
"type": "text",
"disabled": true
},
{
"key": "user",
"value": "USER-20190927-0000012",
"type": "text",
"disabled": true
}
]
},
"url": {
"raw": "{{baseurl}}/management/user-download/",
"raw": "{{baseurl}}/management/extract-transform-load/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"user-download",
"extract-transform-load",
""
]
}
......@@ -1087,21 +1514,20 @@
"response": []
},
{
"name": "department",
"name": "list of user on uploaded csv",
"request": {
"auth": {
"type": "noauth"
},
"method": "GET",
"header": [],
"url": {
"raw": "{{baseurl}}/management/user-download/",
"raw": "{{baseurl}}/management/extract-transform-load/ETL-20191113-0000032/users/",
"host": [
"{{baseurl}}"
],
"path": [
"management",
"user-download",
"extract-transform-load",
"ETL-20191113-0000032",
"users",
""
]
}
......@@ -1115,6 +1541,10 @@
],
"protocolProfileBehavior": {},
"_postman_isSubFolder": true
}
],
"protocolProfileBehavior": {},
"_postman_isSubFolder": true
},
{
"name": "Access Token",
......@@ -1158,7 +1588,7 @@
"formdata": [
{
"key": "username",
"value": "ryu",
"value": "ob-rita",
"type": "text"
},
{
......@@ -1323,7 +1753,7 @@
"response": []
},
{
"name": "Form Dashboard Copy",
"name": "Form Dashboard w/ Filter",
"protocolProfileBehavior": {
"disableBodyPruning": true
},
......@@ -1499,66 +1929,6 @@
}
},
"response": []
},
{
"name": "Form History",
"protocolProfileBehavior": {
"disableBodyPruning": true
},
"request": {
"auth": {
"type": "oauth2",
"oauth2": [
{
"key": "accessToken",
"value": "cJeBxXT2KVtu7yPUQ5HlESDqTmss8G6m",
"type": "string"
},
{
"key": "tokenType",
"type": "any"
},
{
"key": "addTokenTo",
"value": "header",
"type": "string"
}
]
},
"method": "GET",
"header": [
{
"key": "Content-Type",
"name": "Content-Type",
"type": "text",
"value": "application/json"
}
],
"body": {
"mode": "raw",
"raw": ""
},
"url": {
"raw": "{{baseurl}}/change-request-service/form/FRM-20190823-0000002/history/?page=2",
"host": [
"{{baseurl}}"
],
"path": [
"change-request-service",
"form",
"FRM-20190823-0000002",
"history",
""
],
"query": [
{
"key": "page",
"value": "2"
}
]
}
},
"response": []
}
],
"protocolProfileBehavior": {},
......@@ -1581,7 +1951,7 @@
],
"body": {
"mode": "raw",
"raw": "{\r\n \"requested_to_template_name\": \"XXXXXXX\",\r\n \"requested_to_objective\": \"tesa\",\r\n \"requested_to_target_date\": \"2020-05-24T04:37:36.611000\",\r\n \"requested_to_priority\": \"Normal\",\r\n \"description\": \"test\",\r\n \"status\": \"Pending\",\r\n \"company_desc\": null,\r\n \"department_desc\": null,\r\n \"requested_desc\": null,\r\n \"requested_to_template_id\": \"test555\",\r\n \"requested_to_company\": \"COMPANY-20190923-0000001\",\r\n \"requested_to_department\": \"DEPARTMENT-20191004-0000026\",\r\n \"requested_to_user\": \"USER-20191004-0000087\",\r\n \"requested_by_user\": \"USER-20191004-0000087\",\r\n \"requested_by_department\": \"DEPARTMENT-20191004-0000026\",\r\n \"template_no\": \"TMP-20191004-0000044\",\r\n \"frm_approvers\": [\r\n \t{\r\n \"level\": 1,\r\n \"delegation\": \"Head of Department\",\r\n \"user\": \"USER-20191004-0000082\"\r\n \t}\r\n ],\r\n \"frm_stakes\": [],\r\n \"frm_attachments\": [],\r\n \"frm_details\": []\r\n}"
"raw": "{\r\n \"requested_to_template_name\": \"XXXXXXX\",\r\n \"requested_to_objective\": \"tesa\",\r\n \"requested_to_target_date\": \"2020-05-24T04:37:36.611000\",\r\n \"requested_to_priority\": \"Normal\",\r\n \"description\": \"test\",\r\n \"status\": \"Pending\",\r\n \"company_desc\": null,\r\n \"department_desc\": null,\r\n \"requested_desc\": null,\r\n \"requested_to_template_id\": \"test555\",\r\n \"requested_to_company\": \"COMPANY-20191025-0000017\",\r\n \"requested_to_department\": \"DEPARTMENT-20191025-0000050\",\r\n \"requested_to_user\": \"USER-20191025-0000150\",\r\n \"requested_by_user\": \"USER-20191025-0000151\",\r\n \"requested_by_department\": \"DEPARTMENT-20191025-0000050\",\r\n \"template_no\": \"TMP-20191025-0000032\",\r\n \"frm_approvers\": [\r\n \t{\r\n \"level\": 1,\r\n \"delegation\": \"Head of Department\",\r\n \"user\": \"USER-20191025-0000149\"\r\n \t}\r\n ],\r\n \"frm_stakes\": [],\r\n \"frm_attachments\": [],\r\n \"frm_details\": []\r\n}"
},
"url": {
"raw": "{{baseurl}}/change-request/form-post/",
......@@ -1603,26 +1973,7 @@
"method": "GET",
"header": [],
"url": {
"raw": "{{baseurl}}/change-request/form/",
"host": [
"{{baseurl}}"
],
"path": [
"change-request",
"form",
""
]
}
},
"response": []
},
{
"name": "List of Forms Copy",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseurl}}/change-request/form/?date_modified_from=2019-10-11&date_modified_to=2019-10-11",
"raw": "{{baseurl}}/change-request/form/?company_requested_to=COMPANY-20191004-0000011&department_requested_to=DEPARTMENT-20191004-0000029&form_type=closed&date_modified_from=2019-10-11&date_modified_to=2019-10-11",
"host": [
"{{baseurl}}"
],
......@@ -1634,18 +1985,15 @@
"query": [
{
"key": "company_requested_to",
"value": "COMPANY-20191004-0000011",
"disabled": true
"value": "COMPANY-20191004-0000011"
},
{
"key": "department_requested_to",
"value": "DEPARTMENT-20191004-0000029",
"disabled": true
"value": "DEPARTMENT-20191004-0000029"
},
{
"key": "form_type",
"value": "closed",
"disabled": true
"value": "closed"
},
{
"key": "date_modified_from",
......@@ -1666,35 +2014,14 @@
"method": "GET",
"header": [],
"url": {
"raw": "{{baseurl}}/change-request/form/FRM-20191021-0000148/",
"host": [
"{{baseurl}}"
],
"path": [
"change-request",
"form",
"FRM-20191021-0000148",
""
]
}
},
"response": []
},
{
"name": "Re Route for Approval",
"request": {
"method": "PATCH",
"header": [],
"url": {
"raw": "{{baseurl}}/change-request/form/FRM-20190930-0000035/re_route/",
"raw": "{{baseurl}}/change-request/form/FRM-20191121-0000211/",
"host": [
"{{baseurl}}"
],
"path": [
"change-request",
"form",
"FRM-20190930-0000035",
"re_route",
"FRM-20191121-0000211",
""
]
}
......@@ -1706,6 +2033,10 @@
"request": {
"method": "PATCH",
"header": [],
"body": {
"mode": "raw",
"raw": ""
},
"url": {
"raw": "{{baseurl}}/change-request/form/FRM-20190930-0000035/re_submit/",
"host": [
......@@ -1736,12 +2067,7 @@
],
"body": {
"mode": "raw",
"raw": "{\r\n \"id\": 530,\r\n \"form_code\": \"FRM-20191017-0000135\",\r\n \"delegation\": \"Head of Department\",\r\n \"action\": \"Rejected\",\r\n \"level\": \"1\",\r\n \"remarks\": \"This is rejected by approver before vendor\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
"raw": "{\r\n \"id\": 1079,\r\n \"form_code\": \"FRM-20191126-0000237\",\r\n \"delegation\": \"DELEGATION-20191119-0000003\",\r\n \"action\": \"Rejected\",\r\n \"level\": \"1\",\r\n \"remarks\": \"try lang\",\r\n \"move_to_level\": \"5\"\r\n}"
},
"url": {
"raw": "{{baseurl}}/change-request/form/actions/",
......@@ -1772,12 +2098,7 @@
],
"body": {
"mode": "raw",
"raw": "{\r\n \"requested_to_template_name\": \"XXXXXXX\",\r\n \"requested_to_objective\": \"tesaasdaswererytyrtyrt\",\r\n \"requested_to_target_date\": \"2020-05-24T04:37:36.611000\",\r\n \"requested_to_priority\": \"Normal\",\r\n \"description\": \"test\",\r\n \"created\": \"2019-10-04T14:06:51.671702\",\r\n \"cancel_date\": null,\r\n \"company_desc\": null,\r\n \"department_desc\": null,\r\n \"requested_desc\": null,\r\n \"requested_to_template_id\": \"test555-20191004-0000014\",\r\n \"requested_to_company\": \"COMPANY-20190923-0000001\",\r\n \"requested_to_department\": \"DEPARTMENT-20191004-0000026\",\r\n \"requested_to_user\": \"USER-20191004-0000086\",\r\n \"requested_by_user\": \"USER-20191004-0000087\",\r\n \"requested_by_department\": \"DEPARTMENT-20191004-0000026\",\r\n \"template_no\": \"TMP-20191004-0000044\",\r\n \"frm_approvers\": [\r\n {\r\n \"id\": 215,\r\n \"level\": 1,\r\n \"delegation\": \"Head of Department\",\r\n \"created\": \"2019-10-04T14:06:51.687700\",\r\n \"code\": \"FRMAPR-20191004-0000215\",\r\n \"remarks\": null,\r\n \"action\": null,\r\n \"action_date\": null,\r\n \"date_sent\": \"2019-10-04T14:06:51.754714\",\r\n \"user\": \"USER-20191004-0000082\",\r\n \"form_code\": \"FRM-20191004-0000078\"\r\n }\r\n ],\r\n \"frm_stakes\": [],\r\n \"frm_attachments\": [],\r\n \"frm_details\": [],\r\n \"action_required\": \"No\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
"raw": "{\r\n \"requested_to_template_name\": \"XXXXXXX\",\r\n \"requested_to_objective\": \"tesaasdaswererytyrtyrt\",\r\n \"requested_to_target_date\": \"2020-05-24T04:37:36.611000\",\r\n \"requested_to_priority\": \"Normal\",\r\n \"description\": \"test\",\r\n \"created\": \"2019-10-04T14:06:51.671702\",\r\n \"cancel_date\": null,\r\n \"company_desc\": null,\r\n \"department_desc\": null,\r\n \"requested_desc\": null,\r\n \"requested_to_template_id\": \"test555-20191004-0000014\",\r\n \"requested_to_company\": \"COMPANY-20190923-0000001\",\r\n \"requested_to_department\": \"DEPARTMENT-20191004-0000026\",\r\n \"requested_to_user\": \"USER-20191004-0000086\",\r\n \"requested_by_user\": \"USER-20191004-0000087\",\r\n \"requested_by_department\": \"DEPARTMENT-20191004-0000026\",\r\n \"template_no\": \"TMP-20191004-0000044\",\r\n \"frm_approvers\": [\r\n {\r\n \"id\": 215,\r\n \"level\": 1,\r\n \"delegation\": \"Head of Department\",\r\n \"created\": \"2019-10-04T14:06:51.687700\",\r\n \"code\": \"FRMAPR-20191004-0000215\",\r\n \"remarks\": null,\r\n \"action\": null,\r\n \"action_date\": null,\r\n \"date_sent\": \"2019-10-04T14:06:51.754714\",\r\n \"user\": \"USER-20191004-0000082\",\r\n \"form_code\": \"FRM-20191004-0000078\"\r\n }\r\n ],\r\n \"frm_stakes\": [],\r\n \"frm_attachments\": [],\r\n \"frm_details\": [],\r\n \"action_required\": \"No\"\r\n}"
},
"url": {
"raw": "{{baseurl}}/change-request/form/FRM-20191004-0000078/submit/",
......@@ -1809,12 +2130,7 @@
],
"body": {
"mode": "raw",
"raw": "{\r\n \"requested_to_template_name\": \"XXXXXXX\",\r\n \"requested_to_objective\": \"tesass\",\r\n \"requested_to_target_date\": \"2020-05-24T04:37:36.611000\",\r\n \"requested_to_priority\": \"Normal\",\r\n \"description\": \"test\",\r\n \"created\": \"2019-10-04T14:06:51.671702\",\r\n \"cancel_date\": null,\r\n \"company_desc\": null,\r\n \"department_desc\": null,\r\n \"requested_desc\": null,\r\n \"requested_to_template_id\": \"test555-20191004-0000014\",\r\n \"requested_to_company\": \"COMPANY-20190923-0000001\",\r\n \"requested_to_department\": \"DEPARTMENT-20191004-0000026\",\r\n \"requested_to_user\": \"USER-20191004-0000086\",\r\n \"requested_by_user\": \"USER-20191004-0000087\",\r\n \"requested_by_department\": \"DEPARTMENT-20191004-0000026\",\r\n \"template_no\": \"TMP-20191004-0000044\",\r\n \"frm_approvers\": [\r\n {\r\n \"id\": 215,\r\n \"level\": 1,\r\n \"delegation\": \"Head of Department\",\r\n \"created\": \"2019-10-04T14:06:51.687700\",\r\n \"code\": \"FRMAPR-20191004-0000215\",\r\n \"remarks\": null,\r\n \"action\": null,\r\n \"action_date\": null,\r\n \"date_sent\": \"2019-10-04T14:06:51.754714\",\r\n \"user\": \"USER-20191004-0000082\",\r\n \"form_code\": \"FRM-20191004-0000078\"\r\n }\r\n ],\r\n \"frm_stakes\": [],\r\n \"frm_attachments\": [],\r\n \"frm_details\": [],\r\n \"action_required\": \"No\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
"raw": "{\r\n \"requested_to_template_name\": \"XXXXXXX\",\r\n \"requested_to_objective\": \"tesass\",\r\n \"requested_to_target_date\": \"2020-05-24T04:37:36.611000\",\r\n \"requested_to_priority\": \"Normal\",\r\n \"description\": \"test\",\r\n \"created\": \"2019-10-04T14:06:51.671702\",\r\n \"cancel_date\": null,\r\n \"company_desc\": null,\r\n \"department_desc\": null,\r\n \"requested_desc\": null,\r\n \"requested_to_template_id\": \"test555-20191004-0000014\",\r\n \"requested_to_company\": \"COMPANY-20190923-0000001\",\r\n \"requested_to_department\": \"DEPARTMENT-20191004-0000026\",\r\n \"requested_to_user\": \"USER-20191004-0000086\",\r\n \"requested_by_user\": \"USER-20191004-0000087\",\r\n \"requested_by_department\": \"DEPARTMENT-20191004-0000026\",\r\n \"template_no\": \"TMP-20191004-0000044\",\r\n \"frm_approvers\": [\r\n {\r\n \"id\": 215,\r\n \"level\": 1,\r\n \"delegation\": \"Head of Department\",\r\n \"created\": \"2019-10-04T14:06:51.687700\",\r\n \"code\": \"FRMAPR-20191004-0000215\",\r\n \"remarks\": null,\r\n \"action\": null,\r\n \"action_date\": null,\r\n \"date_sent\": \"2019-10-04T14:06:51.754714\",\r\n \"user\": \"USER-20191004-0000082\",\r\n \"form_code\": \"FRM-20191004-0000078\"\r\n }\r\n ],\r\n \"frm_stakes\": [],\r\n \"frm_attachments\": [],\r\n \"frm_details\": [],\r\n \"action_required\": \"No\"\r\n}"
},
"url": {
"raw": "{{baseurl}}/change-request/form/FRM-20191004-0000078/save/",
......@@ -1846,12 +2162,7 @@
],
"body": {
"mode": "raw",
"raw": "",
"options": {
"raw": {
"language": "json"
}
}
"raw": ""
},
"url": {
"raw": "{{baseurl}}/change-request/form/FRM-20191008-0000087/",
......@@ -1893,6 +2204,10 @@
"request": {
"method": "PATCH",
"header": [],
"body": {
"mode": "raw",
"raw": ""
},
"url": {
"raw": "{{baseurl}}/change-request/form/FRM-20190930-0000034/",
"host": [
......@@ -1947,14 +2262,14 @@
"raw": ""
},
"url": {
"raw": "{{baseurl}}/change-request/form/FRM-20191007-0000078/history/",
"raw": "{{baseurl}}/change-request/form/FRM-20191025-0000040/history/",
"host": [
"{{baseurl}}"
],
"path": [
"change-request",
"form",
"FRM-20191007-0000078",
"FRM-20191025-0000040",
"history",
""
]
......@@ -1976,22 +2291,17 @@
],
"body": {
"mode": "raw",
"raw": "{\r\n\t\"attachments\": [\r\n\t\t{\r\n\t\t\t\"id\": 2,\r\n\t\t\t\"attachment_type\": \"Before\",\r\n\t\t\t\"attachment_name\": \"we\",\r\n\t\t\t\"file_name\": \"logo_oneberry.png\",\r\n\t\t\t\"description\": \"we\",\r\n\t\t\t\"file_upload\": 140,\r\n\t\t\t\"uploaded_by\": \"USER-20191004-0000098\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"attachment_type\": \"hello\",\r\n\t\t\t\"attachment_name\": \"hello name\",\r\n\t\t\t\"file_name\": \"logo_oneberry.png\",\r\n\t\t\t\"description\": \"hello desc\",\r\n\t\t\t\"file_upload\": 139,\r\n\t\t\t\"attachment_no\": \"\",\r\n\t\t\t\"date_uploaded\": \"\",\r\n\t\t\t\"file\": \"\",\r\n\t\t\t\"template_no\": \"\",\r\n\t\t\t\"upload_no\": \"\"\r\n\t\t}\r\n\t]\r\n}\r\n",
"options": {
"raw": {
"language": "json"
}
}
"raw": "{\r\n\t\"attachments\": [\r\n\t\t{\r\n\t\t\t\"attachment_type\": \"Before\",\r\n\t\t\t\"attachment_name\": \"we\",\r\n\t\t\t\"file_name\": \"logo_oneberry.png\",\r\n\t\t\t\"description\": \"we\",\r\n\t\t\t\"file_upload\": 302,\r\n\t\t\t\"uploaded_by\": \"USER-20191004-0000098\"\r\n\t\t},\r\n\t\t{\r\n\t\t\t\"attachment_type\": \"hello\",\r\n\t\t\t\"attachment_name\": \"hello name\",\r\n\t\t\t\"file_name\": \"logo_oneberry.png\",\r\n\t\t\t\"description\": \"hello desc\",\r\n\t\t\t\"file_upload\": 63,\r\n\t\t\t\"attachment_no\": \"\",\r\n\t\t\t\"date_uploaded\": \"\",\r\n\t\t\t\"file\": \"\",\r\n\t\t\t\"template_no\": \"\",\r\n\t\t\t\"upload_no\": \"\"\r\n\t\t}\r\n\t]\r\n}\r\n"
},
"url": {
"raw": "{{baseurl}}/change-request/form/FRM-20191004-0000072/file_upload/",
"raw": "{{baseurl}}/change-request/form/FRM-20191029-0000171/file_upload/",
"host": [
"{{baseurl}}"
],
"path": [
"change-request",
"form",
"FRM-20191004-0000072",
"FRM-20191029-0000171",
"file_upload",
""
]
......@@ -2272,14 +2582,14 @@
"method": "GET",
"header": [],
"url": {
"raw": "{{baseurl}}/change-request/template/TMP-20191022-0000092/",
"raw": "{{baseurl}}/change-request/template/TMP-20191025-0000032/",
"host": [
"{{baseurl}}"
],
"path": [
"change-request",
"template",
"TMP-20191022-0000092",
"TMP-20191025-0000032",
""
]
}
......@@ -2660,6 +2970,31 @@
}
},
"response": []
},
{
"name": "Default Approver",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseurl}}/change-request/default-approvers/?department_code=DEPARTMENT-20191121-0000064",
"host": [
"{{baseurl}}"
],
"path": [
"change-request",
"default-approvers",
""
],
"query": [
{
"key": "department_code",
"value": "DEPARTMENT-20191121-0000064"
}
]
}
},
"response": []
}
],
"protocolProfileBehavior": {},
......@@ -2738,7 +3073,7 @@
"method": "GET",
"header": [],
"url": {
"raw": "{{baseurl}}/change-request/form-user-list/?department_code=DEPARTMENT-20191001-0000017",
"raw": "{{baseurl}}/change-request/form-user-list/?department_code=DEPARTMENT-20191121-0000064",
"host": [
"{{baseurl}}"
],
......@@ -2750,7 +3085,7 @@
"query": [
{
"key": "department_code",
"value": "DEPARTMENT-20191001-0000017"
"value": "DEPARTMENT-20191121-0000064"
}
]
}
......@@ -2805,7 +3140,7 @@
"raw": ""
},
"url": {
"raw": "{{baseurl}}/management/notifications/?account_no=USER-20190927-0000011",
"raw": "{{baseurl}}/management/notifications/?account_no=USER-20191025-0000155&app=ams",
"host": [
"{{baseurl}}"
],
......@@ -2817,7 +3152,11 @@
"query": [
{
"key": "account_no",
"value": "USER-20190927-0000011"
"value": "USER-20191025-0000155"
},
{
"key": "app",
"value": "ams"
}
]
}
......@@ -2974,12 +3313,7 @@
],
"body": {
"mode": "raw",
"raw": "{\n\t\"name\": \"Asset Group 1\",\n\t\"asset_group\": \"JTC\"\n}",
"options": {
"raw": {
"language": "json"
}
}
"raw": "{\n\t\"name\": \"Asset Group 1\",\n\t\"asset_group\": \"JTC\"\n}"
},
"url": {
"raw": "{{baseurl}}/asset-management/asset-group/",
......@@ -3009,12 +3343,7 @@
],
"body": {
"mode": "raw",
"raw": "{\n\t\"name\": \"Asset Group 3\",\n\t\"asset_group\": \"JTCs\"\n}",
"options": {
"raw": {
"language": "json"
}
}
"raw": "{\n\t\"name\": \"Asset Group 3\",\n\t\"asset_group\": \"JTCs\"\n}"
},
"url": {
"raw": "{{baseurl}}/asset-management/asset-group/AMSGRP-20191025-0000002/",
......@@ -3036,6 +3365,10 @@
"request": {
"method": "DELETE",
"header": [],
"body": {
"mode": "raw",
"raw": ""
},
"url": {
"raw": "{{baseurl}}/asset-management/asset-group/AMSGRP-20191025-0000002/",
"host": [
......@@ -3070,6 +3403,25 @@
}
},
"response": []
},
{
"name": "List Asset Group",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{baseurl}}/asset-management/asset-group/",
"host": [
"{{baseurl}}"
],
"path": [
"asset-management",
"asset-group",
""
]
}
},
"response": []
}
],
"protocolProfileBehavior": {},
......@@ -3084,7 +3436,7 @@
"bearer": [
{
"key": "token",
"value": "1e3ef7cc7a343b5fa0b54bd2d1699cfee6ca6afe",
"value": "1bc82df8030501015e54bb3f1f78356b9041f796",
"type": "string"
}
]
......
......@@ -6,6 +6,8 @@ async-timeout==3.0.1
attrs==19.1.0
autobahn==19.9.2
Automat==0.7.0
cairocffi==1.1.0
CairoSVG==2.4.2
certifi==2019.6.16
cffi==1.12.3
channels==2.2.0
......@@ -14,7 +16,9 @@ chardet==3.0.4
colorama==0.4.1
constantly==15.1.0
cryptography==2.7
cssselect2==0.2.2
daphne==2.3.0
defusedxml==0.6.0
Django==2.2
django-cors-headers==2.5.2
django-filter==2.1.0
......@@ -25,6 +29,7 @@ et-xmlfile==1.0.1
gevent==1.4.0
greenlet==0.4.15
hiredis==1.0.0
html5lib==1.0.1
hyperlink==19.0.0
idna==2.8
incremental==17.5.0
......@@ -35,21 +40,31 @@ Markdown==3.1
mccabe==0.6.1
msgpack==0.6.1
mysqlclient==1.4.2.post1
numpy==1.17.3
openpyxl==3.0.0
pandas==0.25.3
pep8==1.7.1
Pillow==6.0.0
pycodestyle==2.5.0
pycparser==2.19
PyHamcrest==1.9.0
pylint==2.3.1
PyPDF2==1.26.0
Pyphen==0.9.5
python-dateutil==2.8.1
pytz==2018.9
reportlab==3.5.32
requests==2.22.0
six==1.12.0
sqlparse==0.3.0
tinycss2==1.0.2
Twisted==19.7.0
txaio==18.8.1
typed-ast==1.3.1
urllib3==1.25.3
webencodings==0.5.1
websocket==0.2.1
websocket-client==0.54.0
wrapt==1.11.1
xhtml2pdf==0.2.3
zope.interface==4.6.0
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