from datetime import datetime
from django.db.models.functions import Lower
from functools import wraps
from django.conf import settings
import requests
from app.entities import models
from datetime import timedelta
from django.db.models import Q
from app.applicationlayer.utils import main_threading, notification_create
from app.helper.email_service import sender
from app.applicationlayer.utils import log_save
from app.entities import enums
from app.applicationlayer.utils import model_to_dict
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
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


def entity_log_bulk(queryset, entity, tbl):
    try:
        for data in queryset:
            test = model_to_dict(data)
            log_save(
                enums.LogEnum.DELETED.value,
                entity,
                test['id'],
                test,
                ''
            )
            tbl.objects.filter(id=test['id']).delete()
        return True
    except IntegrityError as exc:
        raise APIException(detail=exc)


def get_dept_details(dept_no):
    dept_instance = models.Department.objects.filter(code=dept_no)

    return dept_instance


def get_companies_details(slug):
    company_instance = models.Company.objects.filter(code=slug)

    return company_instance


def get_account_details(id_number):
    account_instance = models.User.objects.filter(code=id_number)
    return account_instance


def get_allowed_company(id_number):
    return requests.get(f'{ALLOWED_COMPANY}?id_number={id_number}')


def get_approver_details(form_code):
    active_approver_instance = models.ChangeRequestFormApprovers.objects.filter(
        form_code=form_code, is_action=True)
    return active_approver_instance

class QuerySetHelper:

    @staticmethod
    def Sort(context):
        sort_field = context.request.query_params.get('sort_field')
        sort_order = context.request.query_params.get('sort_order')
        if sort_field and sort_order:
            if sort_order.lower() == 'asc':
                context.queryset = context.queryset.order_by(sort_field)
            else:
                context.queryset = context.queryset.order_by(f"-{sort_field}")
        return context.queryset

    @staticmethod
    def Search(context):
        search_field = context.request.query_params.get('search-field')
        search_key = context.request.query_params.get('search-key')
        if search_field and search_key:
            context.queryset = context.queryset(
                __raw__={f"{search_field}" : {"$regex" : f".*{search_key.lower()}.*"}}
            )
        return context.queryset
    
    @staticmethod
    def SearchDynamic(base_queryset,
                      ):
        search_field = context.request.query_params.get('search-field')
        search_key = context.request.query_params.get('search-key')
        if search_field and search_key:
            context.queryset = context.queryset(
                __raw__={f"{search_field}" : {"$regex" : f".*{search_key.lower()}.*"}}
            )
        return context.queryset

    @staticmethod
    def Filter(context):
        if int(len(context.request.query_params)) > 0:
            filtering_kwargs = {}
            with_params = []
            common_params = (
                'page', 'page-size', 'page_size', 'sort_order', 'sort_field'
            )
            for field, value in context.request.GET.items():
                filtering_kwargs = {}
                if value and field.lower() not in common_params:
                    filtering_kwargs[field] = {"$regex" : f".*{value.lower()}.*"}
                    filtering_kwargs[field] = {"$regex" : f".*{value}.*"}
                    # filtering_kwargs[field] = {"$regex" : f".*{value.lower()}.*"}
                    with_params.append(filtering_kwargs)
                    raw_query = {"$or": with_params}
                    context.queryset = context.queryset(__raw__=raw_query)
        return context.queryset


def ApproverStatus(status):
    choices = ["pending", "rejected", "approved", "completed", "cancelled",
               'acknowledged', 'accepted']
    if status not in choices:
        return False
    else:
        return True


def number_generator(prefix, id):
    date = '{:%Y%m%d}'.format(datetime.now())
    id_num = '{:07}'.format(id)
    autogenerated_no = prefix + '-' + date + '-' + id_num

    return autogenerated_no


def get_template_instance(form_code):
    template_instance = models.ChangeRequestFormHeader.objects.filter(
        Q(form_code=form_code)
    ).first()
    return template_instance


def send_mail_vendor(requestor,
                     form_code,
                     delegation,
                     msg,
                     action,
                     remarks,
                     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_to_priority = template_instance.requested_to_priority
    status = template_instance.status
    requested_to_user = template_instance.requested_to_user.code
    
    # receiver details
    vendor_instance = get_account_details(requested_to_user)
    vendor_name = vendor_instance.values_list('name', flat=True)[0]
    vendor_email = vendor_instance.values_list('email', flat=True)[0]
    vendor_code = vendor_instance.values_list('code', flat=True)[0]
    
    # sender details
    sender_instance = get_account_details(requestor)
    sender_name = sender_instance.values_list('name', flat=True)[0]
    sender_code = sender_instance.values_list('code', flat=True)[0]
    sender_email = sender_instance.values_list('email', flat=True)[0]
    
    # department details
    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 = vendor_name
    action_by = sender_name
    routing_level = routing_level
    status = 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 = remarks

    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,
            delegation_recipient, admin]
    
    main_threading(args, sender.routing_table_actions)

    message = f"{sender_name} {msg} ({template_name})"

    # create notification

    notification_create(form_code, message, vendor_code,
                        sender_code, 'cms')


def send_mail_requestor(current_user,
                        form_code,
                        delegation,
                        msg,
                        action,
                        remarks,
                        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_to_priority = template_instance.requested_to_priority
    cr_status = template_instance.status
    # receiver details  --------------------------------------------------

    requestor_instance = get_account_details(requested_by_user)
    requestor_name = requestor_instance.values_list('name', flat=True)[0]
    requestor_email = requestor_instance.values_list('email', flat=True)[0]
    requestor_code = requestor_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 = requestor_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 = 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,
            delegation_recipient, admin]
    
    main_threading(args, sender.routing_table_actions)

    message = f"{sender_name} {msg} ({template_name})"

    # create notification

    notification_create(form_code, message, requestor_code,
                        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):
    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

    # 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 next approver/s
    next_approver = models.ChangeRequestFormApprovers.objects.filter(
                                                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.name.lower() == 'vendor/implementor':
            msg = VENDOR_ACKNOWLEDGE_MESSAGE.split(';')[0]

        # next approver details  --------------------------------------------------
        receiver_instance = get_account_details(n_approver.user.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
        cr_number = cr_number
        cr_name = template_name
        company_requestedto = company_name
        department_requestedto = dept_name
        priority_level = requested_to_priority
        status = cr_status
        url = cr_link
        
        recipient = receiver_email
        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,
                delegation_recipient, admin]

        main_threading(args, sender.routing_table_actions_required)

        message = f"{sender_name} {msg} ({template_name})"

        # create notification

        notification_create(form_code, message, receiver_code,
                            sender_code, 'cms')


def cancel_overdue(request):
    date_submitted = datetime.now()
    requestor = request.data['requested_by_user']
    requestor = requests.get(f'{ACCOUNTS}{requestor}/')
    requestor = requestor.json()['results']

    cancel_date = date_submitted + timedelta(days=30)
    cancel_date = cancel_date.strftime('%Y-%m-%d 00:00:00.000')

    request.data['date_submitted'] = date_submitted
    request.data['cancel_date'] = cancel_date

    email_content_cancel = {
        "sender_account_no": requestor['id_number'],
        "receiver_account_no": requestor['id_number'],
        "email_code": "RMS-CRCANCELLED",
        "email_recipient": requestor['email'],
        "app": "CMS",
        "sent": "False",
        "name": requestor['name'],
        "status": "Pending",
        "auto_cancel_date": cancel_date,
        "cr_number": request.data['requested_to_template_id'],
        "cr_name": request.data['requested_to_template_name'],
        "company_requestedto": request.data['requested_to_company'],
        "department_requestedto": request.data['requested_to_department'],
        "priority_level": request.data['requested_to_priority'],
        "url": "http://devweb.rms.oneberrysystem.com/login"
    }

    exist_cancel_template = models.CancelDateCR.objects.filter(
        cr_number=request.data['requested_to_template_id']
    )
    if exist_cancel_template:
        exist_cancel_template.delete()

    models.CancelDateCR.objects.create(
        cr_number=request.data['requested_to_template_id'],
        trigger_date=cancel_date,
        email_content=email_content_cancel
    )

    requested_to_target_date = parser.parse(
        request.data['requested_to_target_date']
    )

    email_content_cancel['email_code'] = "RMS-CROVERDUE"
    email_content_cancel['target_date'] = requested_to_target_date

    overdue = requested_to_target_date + timedelta(days=30)
    overdue = overdue.strftime('%Y-%m-%d 00:00:00.000')

    models.TargetDateOverdue.objects.create(
        cr_number=form_code,
        trigger_date=overdue,
        email_content=email_content_cancel
    )
    return True


def get_max_batchno(request):
    try:
        max_id = models.ChangeRequestHistory.objects.all(
            ).order_by("-batch_no")[0]

        if max_id:
            max_batch = max_id.batch_no.split("-")
            max_batch = int(max_batch[2].lstrip("0")) + 1
            batchno = number_generator("BATCH", max_batch)
        else:
            batchno = number_generator("BATCH", 1)
    except:
        batchno = number_generator("BATCH", 1)

    return batchno


def crhistory_save(batch_no, main_action,
                   action, entity, form_code,
                   fromValue, toValue):

    models.ChangeRequestHistory.objects.create(
            batch_no=batch_no,
            main_action=main_action,
            action=action,
            entity=entity,
            form_code=form_code,
            fromValue=fromValue,
            toValue=toValue
        )
    
    return True


def crhistory_log_bulk_delete(queryset, entity, tbl, form_code,
                              batch_no, main_action):
    try:
        for data in queryset:
            test = model_to_dict(data)
            crhistory_save(batch_no,
                           main_action,
                           enums.CREnum.DELETED.value,
                           entity,
                           form_code,
                           test,
                           '')
            
            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)


def generate_template_id(prefix,
                         form_code,
                         template_no):

    try:
        max_id = models.ChangeRequestHistory.objects.filter(
            Q(template_no=template_no) &
            Q(entity=enums.CREntitiesEnum.CR_FRM_HEADER.value) &
            (Q(main_action=enums.CREnum.CREATE.value) |
             Q(main_action=enums.CREnum.SUBMIT.value))
            ).count()

        if max_id > 0:
            max_id = max_id + 1
            requested_to_template_id = number_generator(prefix, max_id)
        else:
            requested_to_template_id = number_generator(prefix, 1)
    except:
        requested_to_template_id = number_generator(prefix, 1)
    
    models.ChangeRequestFormHeader.objects.filter(
        form_code=form_code).update(
            requested_to_template_id=requested_to_template_id)

    return requested_to_template_id


def crhistory_create_save(batch_no, main_action,
                          action, entity, form_code, fromValue,
                          toValue, requested_to_template_id, template_no):

    models.ChangeRequestHistory.objects.create(
            batch_no=batch_no,
            main_action=main_action,
            action=action,
            entity=entity,
            form_code=form_code,
            fromValue=fromValue,
            toValue=toValue,
            requested_to_template_id=requested_to_template_id,
            template_no=template_no
    )
    
    return True


class BadRequestException(Exception):
    pass


def reminder_trigger_save(form_code,
                          date_now,
                          date_submitted_last_approver):

    approver_instance = get_approver_details(form_code)

    form_instance = models.ChangeRequestFormHeader.objects.get(
        form_code=form_code)

    date_from = date_now + timedelta(days=7)
    date_to = date_now + timedelta(days=29)
    auto_cancel_date = date_now + timedelta(days=30)

    # create log for auto_email
    counter = 0
    for approver in approver_instance:
        models.ReminderTrigger.objects.create(
            frm_approver=approver,
            date_from=date_from.strftime('%Y-%m-%d 00:00:00.000'),
            date_to=date_to.strftime('%Y-%m-%d 00:00:00.000'),
            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,
            form_code=form_instance
        )
        
        if counter == 0:
            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=date_submitted_last_approver,
                is_sent=False,
                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')