
from finance_and_accounting.utils import get_expenses_in_types, get_financial_year_net_income_values, get_previous_order_payments_value
from procurement.models import Supplier
from sales_and_marketing.models import LandedCost, LandedCostInstance, ProductDiscount, ProductPricing, ProductVAT, SalesOrder
from sales_and_marketing.serializers import CustomerOrderPaymentSerializer
from system_administration.utils import calculate_asset_depreciation, calculate_closing_inventory_value, calculate_product_cost_of_opening_inventory, calculate_purchase_order_value_for_the_year, calculate_single_asset_value_current, check_if_system_administrator, create_notifications, get_staff_profile_data
from access_control.permissions import user_has_permission
from warehouse_management.models import Category
from .models import *
from .serializers import *
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import TokenAuthentication
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.response import Response
from django.contrib.auth.models import User
from datetime import datetime
import json
from django.http import JsonResponse
from django.contrib.auth import authenticate, login, logout
from forex_python.converter import CurrencyRates
import pytz
import logging

from .posting_hooks import (
    post_customer_payment,
    post_expense_gl,
    post_payroll_accrual,
    post_sales_invoice,
)
from .petty_cash_posting import sync_petty_cash_running_balance


def _resolve_staff_for_finance(active_user):
    return StaffProfile.objects.filter(user=active_user).select_related(
        'company_department', 'company_branch', 'staff_position',
    ).first()


def _finance_head_access(staff_profile, company_profile):
    if not staff_profile:
        return False
    if check_if_system_administrator(staff_profile):
        return True
    dept = getattr(staff_profile, 'company_department', None)
    dept_name = dept.department_name if dept else ""
    return (
        dept_name == "finance_and_accounting"
        and staff_profile.is_head_of_department
        and staff_profile.has_read_write_priviledges
        and company_profile is not None
    )


def _finance_staff_missing_response(payload):
    return Response(
        {"message": "Staff profile not linked to this login.", "payload": payload},
        status=401,
    )


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def finance_accountant(request):
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    date_format_new = '%d/%m/%Y'
    current_date = datetime.now().date()
    company_serial_number = request.data["serial_number"]
    active_user = request.user
    payload = {}
    company_profile_map = {}
    company_branches_list = []
    loan_portfolio_list = []
    transaction_list = []
    transaction_map = {}
    assets_list = []
    dividends_list = []
    try:
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.dashboard.view"):
            active_staff_profile_data = get_staff_profile_data(active_user)
            company_profile_map["company_id"] = str(company_profile.id)
            company_profile_map["company_name"] = company_profile.company_name
            company_profile_map["company_phone"] = company_profile.company_phone
            company_profile_map["preferred_currency"] = company_profile.company_preferred_currency
            company_profile_map["company_postal_address"] = company_profile.company_postal_address
            all_branches = company_profile.company_branches.all().order_by("-id")
            company_loan_portfolio = company_profile.company_loan_portfolio.all().order_by("-id")
            all_transactions = Transaction.objects.filter(
                recycle_bin=False,).order_by("-id")
            all_assets = Asset.objects.filter(
                recycle_bin=False).order_by("-id")
            all_dividends = Dividend.objects.filter(
                recycle_bin=False).order_by("-id")
            for dividend in all_dividends:
                dividend_map = {}
                dividend_map["dividend_id"] = str(dividend.id)
                dividend_map["account_id"] = str(
                    dividend.account.id) if dividend.account is not None else ""
                dividend_map["dividend_title"] = dividend.dividend_title
                dividend_map["account_name"] = dividend.account.account_name if dividend.account is not None else ""
                dividend_map["account_number"] = dividend.account.account_number if dividend.account is not None else ""
                dividend_map["financial_year"] = dividend.financial_year
                dividend_map["dividend_amount_paid"] = dividend.dividend_amount_paid
                dividend_map["dividend_comment"] = dividend.dividend_comment
                dividend_map["created_on"] = datetime.strftime(
                    dividend.created_on.astimezone(target_timezone), date_format) if dividend.created_on is not None else ""
                dividend_map["last_updated_on"] = datetime.strftime(
                    dividend.last_updated_on.astimezone(target_timezone), date_format) if dividend.last_updated_on is not None else ""
                creator_map = {}
                creator_map["staff_id"] = str(
                    dividend.created_by.id) if dividend.created_by is not None else ""
                creator_map["staff_name"] = f'{dividend.created_by.first_name} {dividend.created_by.last_name}' if dividend.created_by is not None else ""
                creator_map["staff_position"] = dividend.created_by.staff_position.position_title if dividend.created_by is not None else ""
                dividend_map["created_by"] = creator_map
                creator_map = {}
                creator_map["staff_id"] = str(
                    dividend.last_updated_by.id) if dividend.last_updated_by is not None else ""
                creator_map["staff_name"] = f'{dividend.last_updated_by.first_name} {dividend.last_updated_by.last_name}' if dividend.last_updated_by is not None else ""
                creator_map["staff_position"] = dividend.last_updated_by.staff_position.position_title if dividend.last_updated_by is not None else ""
                dividend_map["last_updated_by"] = creator_map
                dividends_list.append(dividend_map)
            for asset in all_assets:
                asset_map = {}
                asset_map["asset_id"] = str(asset.id)
                asset_map["asset_name"] = asset.asset_name
                asset_map["serial_number"] = asset.serial_number
                asset_map["asset_category"] = asset.asset_category
                asset_map["purchase_date"] = datetime.strftime(
                    asset.purchase_date, date_format_new)
                asset_map["purchase_cost"] = asset.purchase_cost
                asset_map["vendor_name"] = asset.vendor_name
                asset_map["invoice_number"] = asset.invoice_number
                asset_map["useful_life_years"] = asset.useful_life_years
                asset_map["residual_value"] = asset.residual_value
                asset_map["depreciation_method"] = asset.depreciation_method
                asset_map["depriciation_rate"] = asset.depreciation_rate
                asset_map["status"] = asset.status
                asset_map["created_on"] = datetime.strftime(
                    asset.created_on.astimezone(target_timezone), date_format) if asset.created_on is not None else ""
                asset_map["last_updated_on"] = datetime.strftime(
                    asset.last_updated_on.astimezone(target_timezone), date_format) if asset.last_updated_on is not None else ""
                creator_map = {}
                creator_map["staff_id"] = str(
                    asset.created_by.id) if asset.created_by is not None else ""
                creator_map["staff_name"] = f'{asset.created_by.first_name} {asset.created_by.last_name}' if asset.created_by is not None else ""
                creator_map["staff_position"] = asset.created_by.staff_position.position_title if asset.created_by is not None else ""
                asset_map["created_by"] = creator_map
                creator_map = {}
                creator_map["staff_id"] = str(
                    asset.last_updated_by.id) if asset.last_updated_by is not None else ""
                creator_map["staff_name"] = f'{asset.last_updated_by.first_name} {asset.last_updated_by.last_name}' if asset.last_updated_by is not None else ""
                creator_map["staff_position"] = asset.last_updated_by.staff_position.position_title if asset.last_updated_by is not None else ""
                asset_map["last_updated_by"] = creator_map
                # asset_financial_years = asset.asset_financial_years.all().order_by("-financial_year")
                # asset_financial_year_list = []
                # for asset_financial_year in asset_financial_years:
                #     asset_financial_year_map = {}
                #     asset_financial_year_map["asset_financial_year_id"] = str(
                #         asset_financial_year.id)
                #     asset_financial_year_map["opening_value"] = asset_financial_year.opening_value
                #     asset_financial_year_map["depreciation_expense"] = asset_financial_year.depreciation_expense
                #     asset_financial_year_map["closing_value"] = asset_financial_year.closing_value
                #     asset_financial_year_map["financial_year"] = asset_financial_year.financial_year
                #     asset_financial_year_list.append(asset_financial_year_map)
                # asset_map["asset_financial_year_list"] = asset_financial_year_list
                assets_list.append(asset_map)
            for transaction in all_transactions:
                print("running")
                transaction_map = {}
                transaction_map["transaction_id"] = str(transaction.id)
                transaction_map["transaction_number"] = transaction.transaction_number
                transaction_map["transaction_mode"] = transaction.transaction_mode
                transaction_map["transaction_amount"] = transaction.transaction_amount
                transaction_map["transaction_currency"] = transaction.transaction_currency
                transaction_map["exchange_rate"] = transaction.exchange_rate
                transaction_map["expense_id"] = str(
                    transaction.expense.id) if transaction.expense is not None else ""
                transaction_map["deposit_id"] = str(
                    transaction.deposit.id) if transaction.deposit is not None else ""
                transaction_map["account_id"] = str(
                    transaction.account.id) if transaction.account is not None else ""
                transaction_map["loan_portfolio_id"] = str(
                    transaction.loan_payment.id) if transaction.loan_payment is not None else ""
                transaction_map["transaction_reference"] = transaction.transaction_reference
                transaction_map["created_on"] = datetime.strftime(
                    transaction.created_on.astimezone(target_timezone), date_format) if transaction.created_on is not None else ""
                transaction_map["last_updated_on"] = datetime.strftime(
                    transaction.last_updated_on.astimezone(target_timezone), date_format) if transaction.last_updated_on is not None else ""
                creator_map = {}
                if transaction.transaction_mode == "outflow":
                    if transaction.expense is not None:
                        creator_map["staff_id"] = str(
                            transaction.expense.created_by.id) if transaction.expense.created_by is not None else ""
                        creator_map["staff_name"] = f'{transaction.expense.created_by.first_name} {transaction.expense.created_by.last_name}' if transaction.expense.created_by is not None else ""
                        creator_map["staff_position"] = transaction.expense.created_by.staff_position.position_title if transaction.expense.created_by.staff_position is not None else ""
                        transaction_map["created_by"] = creator_map
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            transaction.expense.last_updated_by.id) if transaction.expense.last_updated_by is not None else ""
                        creator_map["staff_name"] = f'{transaction.expense.last_updated_by.first_name} {transaction.expense.last_updated_by.last_name}' if transaction.expense.last_updated_by is not None else ""
                        creator_map["staff_position"] = transaction.expense.last_updated_by.staff_position.position_title if transaction.expense.last_updated_by.staff_position is not None else ""
                        transaction_map["last_updated_by"] = creator_map
                    else:
                        creator_map["staff_id"] = str(
                            transaction.created_by.id) if transaction.created_by is not None else ""
                        creator_map["staff_name"] = f'{transaction.created_by.first_name} {transaction.created_by.last_name}' if transaction.created_by is not None else ""
                        creator_map["staff_position"] = transaction.created_by.staff_position.position_title if transaction.created_by is not None else ""
                        transaction_map["created_by"] = creator_map
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            transaction.last_updated_by.id) if transaction.last_updated_by is not None else ""
                        creator_map["staff_name"] = f'{transaction.last_updated_by.first_name} {transaction.last_updated_by.last_name}' if transaction.last_updated_by is not None else ""
                        creator_map["staff_position"] = transaction.last_updated_by.staff_position.position_title if transaction.last_updated_by is not None else ""
                        transaction_map["last_updated_by"] = creator_map
                else:
                    creator_map["staff_id"] = str(
                        transaction.deposit.created_by.id) if transaction.deposit.created_by is not None else ""
                    creator_map["staff_name"] = f'{transaction.deposit.created_by.first_name} {transaction.deposit.created_by.last_name}' if transaction.deposit.created_by is not None else ""
                    creator_map["staff_position"] = transaction.deposit.created_by.staff_position.position_title if transaction.deposit.created_by.staff_position is not None else ""
                    transaction_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        transaction.deposit.last_updated_by.id) if transaction.deposit.last_updated_by is not None else ""
                    creator_map["staff_name"] = f'{transaction.deposit.last_updated_by.first_name} {transaction.deposit.last_updated_by.last_name}' if transaction.deposit.last_updated_by is not None else ""
                    creator_map["staff_position"] = transaction.deposit.last_updated_by.staff_position.position_title if transaction.deposit.last_updated_by.staff_position is not None else ""
                    transaction_map["last_updated_by"] = creator_map
                transaction_list.append(transaction_map)
            for loan_portfolio in company_loan_portfolio:
                if loan_portfolio.recycle_bin != True:
                    loan_portfolio_map = {}
                    loan_portfolio_map["loan_id"] = str(loan_portfolio.id)
                    loan_portfolio_map["loan_title"] = loan_portfolio.loan_title
                    loan_portfolio_map["loan_type"] = loan_portfolio.loan_type
                    loan_portfolio_map["lender_name"] = loan_portfolio.lender_name
                    loan_portfolio_map["lender_phone"] = loan_portfolio.lender_phone
                    loan_portfolio_map["lender_email"] = loan_portfolio.lender_email
                    loan_portfolio_map["loan_amount"] = loan_portfolio.loan_amount
                    loan_portfolio_map["interest_rate"] = loan_portfolio.interest_rate
                    loan_portfolio_map["repayment_period"] = loan_portfolio.repayment_period
                    loan_portfolio_map["total_repayment_amount"] = loan_portfolio.total_repayment_amount
                    loan_portfolio_map["principal_paid"] = loan_portfolio.principal_paid
                    loan_portfolio_map["loan_currency"] = loan_portfolio.loan_currency
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        loan_portfolio.created_by.id) if loan_portfolio.created_by is not None else ""
                    creator_map["staff_name"] = f'{loan_portfolio.created_by.first_name} {loan_portfolio.created_by.last_name}' if loan_portfolio.created_by is not None else ""
                    creator_map["staff_position"] = loan_portfolio.created_by.staff_position.position_title if loan_portfolio.created_by.staff_position is not None else ""
                    loan_portfolio_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        loan_portfolio.last_updated_by.id) if loan_portfolio.last_updated_by is not None else ""
                    creator_map["staff_name"] = f'{loan_portfolio.last_updated_by.first_name} {loan_portfolio.last_updated_by.last_name}' if loan_portfolio.last_updated_by is not None else ""
                    creator_map["staff_position"] = loan_portfolio.last_updated_by.staff_position.position_title if loan_portfolio.last_updated_by.staff_position is not None else ""
                    loan_portfolio_map["last_updated_by"] = creator_map
                    loan_portfolio_map["created_on"] = datetime.strftime(
                        loan_portfolio.created_on.astimezone(target_timezone), date_format) if loan_portfolio.created_on is not None else ""
                    loan_portfolio_map["last_updated_on"] = datetime.strftime(
                        loan_portfolio.last_updated_on.astimezone(target_timezone), date_format) if loan_portfolio.last_updated_on is not None else ""
                    loan_payment_history_list = []
                    loan_payment_history = loan_portfolio.loan_payment_history.all().order_by("-id")
                    for loan_payment in loan_payment_history:
                        loan_payment_history_map = {}
                        loan_payment_history_map["loan_payment_id"] = str(
                            loan_payment.id)
                        loan_payment_history_map["transaction_amount"] = loan_payment.transaction_amount
                        loan_payment_history_list.append(
                            loan_payment_history_map)
                    loan_portfolio_map["loan_payment_history_list"] = loan_payment_history_list
                    loan_portfolio_list.append(loan_portfolio_map)
            for branch in all_branches:
                if branch.recycle_bin != True:
                    company_branch_map = {}
                    chart_of_account_list = []
                    expense_list = []
                    deposit_list = []
                    company_branch_map["branch_id"] = str(branch.id)
                    company_branch_map["branch_name"] = branch.branch_name
                    company_branch_map["is_main_branch"] = "true" if branch.main_branch == True else "false"
                    all_chart_of_accounts = branch.branch_chart_of_accounts.all().order_by("-id")
                    for account in all_chart_of_accounts:
                        if account.recycle_bin != True:
                            chart_of_account_map = {}
                            chart_of_account_map["account_id"] = str(
                                account.id)
                            chart_of_account_map["account_name"] = account.account_name
                            chart_of_account_map["account_number"] = account.account_number
                            chart_of_account_map["account_descriptions"] = account.account_descriptions
                            chart_of_account_map["banking_institution_name"] = account.banking_institution_name
                            chart_of_account_map["bank_branch_name"] = account.bank_branch_name
                            chart_of_account_map["bank_branch_code"] = account.bank_branch_code
                            chart_of_account_map["bank_swift_code"] = account.bank_swift_code
                            chart_of_account_map["bank_sort_code"] = account.bank_sort_code
                            chart_of_account_map["is_mpesa_account"] = "true" if account.is_mpesa_account == True else "false"
                            # chart_of_account_map["running_balance"] = account.running_balance
                            chart_of_account_map["account_currency"] = account.account_currency
                            chart_of_account_map["running_balance"] = account.running_balance
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                account.created_by.id) if account.created_by is not None else ""
                            creator_map["staff_name"] = f'{account.created_by.first_name} {account.created_by.last_name}' if account.created_by is not None else ""
                            creator_map["staff_position"] = account.created_by.staff_position.position_title if account.created_by.staff_position is not None else ""
                            chart_of_account_map["created_by"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                account.last_updated_by.id) if account.last_updated_by is not None else ""
                            creator_map["staff_name"] = f'{account.last_updated_by.first_name} {account.last_updated_by.last_name}' if account.last_updated_by is not None else ""
                            creator_map["staff_position"] = account.last_updated_by.staff_position.position_title if account.last_updated_by.staff_position is not None else ""
                            chart_of_account_map["last_updated_by"] = creator_map
                            chart_of_account_map["created_on"] = datetime.strftime(
                                account.created_on.astimezone(target_timezone), date_format) if account.created_on is not None else ""
                            chart_of_account_map["last_updated_on"] = datetime.strftime(
                                account.last_updated_on.astimezone(target_timezone), date_format) if account.last_updated_on is not None else ""
                            account_transactions = account.account_transactions.all().order_by("-id")
                            account_transactions_list = []
                            for account_transaction in account_transactions:
                                account_transactions_map = {}
                                account_transactions_map["account_transaction_id"] = str(
                                    account_transaction.id)
                                account_transactions_map["transaction_amount"] = account_transaction.transaction_amount
                                account_transactions_list.append(
                                    account_transactions_map)
                            chart_of_account_map["account_transactions_list"] = account_transactions_list
                            chart_of_account_list.append(chart_of_account_map)
                    company_branch_map["chart_of_account_list"] = chart_of_account_list
                    all_expenses = branch.branch_expenses.all().order_by("-id")
                    for expense in all_expenses:
                        expense_map = {}
                        expense_map["expense_id"] = str(expense.id)
                        expense_map["expense_number"] = expense.expense_number
                        expense_map["expense_title"] = expense.expense_title
                        expense_map["expense_description"] = expense.expense_description
                        expense_map["expense_type"] = expense.expense_type
                        expense_map["payroll_sheet_id"] = str(
                            expense.payroll_sheet.id) if expense.payroll_sheet is not None else ""
                        # expense_map["purchase_order_id"] = str(
                        #     expense.purchase_order.id) if expense.purchase_order is not None else ""
                        product_purchase_expenses = expense.product_purchase_instance.all()
                        purchase_expense_list = []
                        for purchase_expense in product_purchase_expenses:
                            if purchase_expense.recycle_bin != True:
                                purchase_expense_map = {}
                                purchase_expense_map["purchase_expense_id"] = str(
                                    purchase_expense.id)
                                purchase_expense_map["product_purchase_instance_id"] = str(
                                    purchase_expense.id)  # harmless and should not be used
                                purchase_expense_map["purchase_value_per_unit"] = purchase_expense.purchase_value_per_unit
                                purchase_expense_map["purchase_value_overall"] = purchase_expense.purchase_value_overall
                                purchase_expense_map["purchase_amount_paid_to_supplier"] = purchase_expense.purchase_amount_paid_to_supplier
                                purchase_expense_map["supplier_payment_settled"] = "true" if purchase_expense.supplier_payment_settled == True else "false"
                                purchase_expense_map["supplier_id"] = str(
                                    purchase_expense.supplier.id) if purchase_expense.supplier is not None else ""
                                purchase_expense_map["purchase_order_id"] = str(
                                    purchase_expense.purchase_order.id) if purchase_expense.purchase_order is not None else ""
                                purchase_expense_map["purchase_order_number"] = purchase_expense.purchase_order.purchase_order_number
                                purchase_expense_list.append(
                                    purchase_expense_map)
                        expense_map["purchase_expense_list"] = purchase_expense_list

                        expense_map["refund_id"] = str(
                            expense.refund.id) if expense.refund is not None else ""
                        expense_map["expense_amount"] = expense.expense_amount
                        try:
                            expense_map["expense_transaction_id"] = str(
                                Transaction.objects.get(expense=expense).id)
                        except:
                            expense_map["expense_transaction_id"] = ""
                        # expense_map["expense_transaction_id"] = str(
                        #     expense.expense_transaction.id) if expense.expense_transaction is not None else ""
                        expense_map["expense_settled"] = "true" if expense.expense_settled == True else "false"
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            expense.created_by.id) if expense.created_by is not None else ""
                        creator_map["staff_name"] = f'{expense.created_by.first_name} {expense.created_by.last_name}' if expense.created_by is not None else ""
                        creator_map["staff_position"] = expense.created_by.staff_position.position_title if expense.created_by.staff_position is not None else ""
                        expense_map["created_by"] = creator_map
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            expense.last_updated_by.id) if expense.last_updated_by is not None else ""
                        creator_map["staff_name"] = f'{expense.last_updated_by.first_name} {expense.last_updated_by.last_name}' if expense.last_updated_by is not None else ""
                        creator_map["staff_position"] = expense.last_updated_by.staff_position.position_title if expense.last_updated_by.staff_position is not None else ""
                        expense_map["last_updated_by"] = creator_map
                        # expense approved
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            expense.last_updated_by.id) if expense.expense_approved_by is not None else ""
                        creator_map["staff_name"] = f'{expense.expense_approved_by.first_name} {expense.expense_approved_by.last_name}' if expense.expense_approved_by is not None else ""
                        creator_map["staff_position"] = expense.expense_approved_by.staff_position.position_title if expense.expense_approved_by.staff_position is not None else ""
                        expense_map["expense_approved_by"] = creator_map
                        #
                        expense_map["created_on"] = datetime.strftime(
                            expense.created_on.astimezone(target_timezone), date_format) if expense.created_on is not None else ""
                        expense_map["last_updated_on"] = datetime.strftime(
                            expense.last_updated_on.astimezone(target_timezone), date_format) if expense.last_updated_on is not None else ""
                        expense_list.append(expense_map)
                    company_branch_map["expense_list"] = expense_list
                    all_deposits = branch.branch_deposits.all().order_by("-id")
                    for deposit in all_deposits:
                        deposit_map = {}
                        deposit_map["deposit_id"] = str(deposit.id)
                        deposit_map["deposit_number"] = deposit.deposit_number
                        deposit_map["deposit_source"] = deposit.deposit_source
                        deposit_map["deposit_amount"] = deposit.deposit_amount
                        deposit_map["order_payment_reference"] = deposit.order_payment_reference
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            deposit.created_by.id) if deposit.created_by is not None else ""
                        creator_map["staff_name"] = f'{deposit.created_by.first_name} {deposit.created_by.last_name}' if deposit.created_by is not None else ""
                        creator_map["staff_position"] = deposit.created_by.staff_position.position_title if deposit.created_by.staff_position is not None else ""
                        deposit_map["created_by"] = creator_map
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            deposit.last_updated_by.id) if deposit.last_updated_by is not None else ""
                        creator_map["staff_name"] = f'{deposit.last_updated_by.first_name} {deposit.last_updated_by.last_name}' if deposit.last_updated_by is not None else ""
                        creator_map["staff_position"] = deposit.last_updated_by.staff_position.position_title if deposit.last_updated_by.staff_position is not None else ""
                        deposit_map["last_updated_by"] = creator_map
                        deposit_map["created_on"] = datetime.strftime(
                            deposit.created_on.astimezone(target_timezone), date_format) if deposit.created_on is not None else ""
                        deposit_map["last_updated_on"] = datetime.strftime(
                            deposit.last_updated_on.astimezone(target_timezone), date_format) if deposit.last_updated_on is not None else ""
                        deposit_list.append(deposit_map)
                    company_branch_map["deposit_list"] = deposit_list
                    company_branches_list.append(company_branch_map)
            company_profile_map["company_branches_list"] = company_branches_list
            payload["company_profile"] = company_profile_map
            payload["active_staff_profile_data"] = active_staff_profile_data
            payload["loan_portfolio_list"] = loan_portfolio_list
            payload["transaction_list"] = transaction_list
            payload["assets_list"] = assets_list
            payload["dividends_list"] = dividends_list
            return Response({"message": "true", "payload": payload}, status=200)
        else:
            return Response({"message": "false", "payload": payload}, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "false", "payload": payload}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def finance_reporting(request):
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    current_date = datetime.now().date()
    company_serial_number = request.data["serial_number"]
    active_user = request.user
    payload = {}
    company_profile_map = {}
    company_branches_list = []
    company_branch_map = {}
    transaction_list = []
    transaction_map = {}
    supplier_list = []
    purchase_order_list = []
    journal_entries_list = []
    try:
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.financial_reports.view"):
            active_staff_profile_data = get_staff_profile_data(active_user)
            company_profile_map["company_id"] = str(company_profile.id)
            company_profile_map["company_name"] = company_profile.company_name
            company_profile_map["company_phone"] = company_profile.company_phone
            company_profile_map["preferred_currency"] = company_profile.company_preferred_currency
            company_profile_map["company_postal_address"] = company_profile.company_postal_address
            all_branches = company_profile.company_branches.all().order_by("-id")
            # company_loan_portfolio = company_profile.company_loan_portfolio.all().order_by("-id")
            all_transactions = Transaction.objects.filter(
                recycle_bin=False,).order_by("-id")
            all_suppliers = Supplier.objects.all().order_by("-id")
            company_purchase_orders = company_profile.company_purchase_orders.filter(
                recycle_bin=False).order_by("-id")
            all_journal_entries = Journal_Entry.objects.all().order_by("-id")
            for journal_entry in all_journal_entries:
                journal_entry_map = {}
                journal_entry_map["journal_entry_id"] = str(journal_entry.id)
                journal_entry_map["transaction_id"] = str(
                    journal_entry.transaction.id) if journal_entry.transaction is not None else ""
                journal_entry_map["customer_order_invoice_id"] = str(
                    journal_entry.customer_order_invoice.id) if journal_entry.customer_order_invoice is not None else ""
                journal_entry_map["journal_entry_number"] = journal_entry.journal_entry_number
                journal_entry_map["journal_description"] = journal_entry.journal_description
                journal_entry_map["created_on"] = datetime.strftime(
                    journal_entry.created_on.astimezone(target_timezone), date_format) if journal_entry.created_on is not None else ""
                journal_entry_map["last_updated_on"] = datetime.strftime(
                    journal_entry.last_updated_on.astimezone(target_timezone), date_format) if journal_entry.last_updated_on is not None else ""
                journal_entry_map["journal_reference"] = journal_entry.journal_reference
                journal_entry_map["journal_tag"] = journal_entry.journal_tag
                # journal_entry_map["journal_tag"] = journal_entry.journal_tag
                creator_map = {}
                creator_map["staff_id"] = str(
                    journal_entry.created_by.id) if journal_entry.created_by is not None else ""
                creator_map["staff_name"] = f'{journal_entry.created_by.first_name} {journal_entry.created_by.last_name}' if journal_entry.created_by is not None else ""
                creator_map["staff_position"] = journal_entry.created_by.staff_position.position_title if journal_entry.created_by.staff_position is not None else ""
                journal_entry_map["created_by"] = creator_map
                creator_map = {}
                creator_map["staff_id"] = str(
                    journal_entry.last_updated_by.id) if journal_entry.last_updated_by is not None else ""
                creator_map["staff_name"] = f'{journal_entry.last_updated_by.first_name} {journal_entry.last_updated_by.last_name}' if journal_entry.last_updated_by is not None else ""
                creator_map["staff_position"] = journal_entry.last_updated_by.staff_position.position_title if journal_entry.last_updated_by.staff_position is not None else ""
                journal_entry_map["last_updated_by"] = creator_map
                journal_debit_entries = journal_entry.journal_debit_entries.all().order_by("-id")
                journal_debit_list = []
                for journal_debit in journal_debit_entries:
                    journal_debit_map = {}
                    journal_debit_map["journal_debit_id"] = str(
                        journal_debit.id)
                    journal_debit_map["journal_account_debit_id"] = str(
                        journal_debit.journal_account_debit.id) if journal_debit.journal_account_debit is not None else ""
                    journal_debit_map["journal_account_debit_name"] = journal_debit.journal_account_debit.account_name if journal_debit.journal_account_debit is not None else ""
                    journal_debit_map["debit_amount"] = journal_debit.debit_amount
                    journal_debit_list.append(journal_debit_map)
                journal_entry_map["journal_debit_list"] = journal_debit_list
                #
                journal_credit_entries = journal_entry.journal_credit_entries.all().order_by("-id")
                journal_credit_list = []
                for journal_credit in journal_credit_entries:
                    journal_credit_map = {}
                    journal_credit_map["journal_credit_id"] = str(
                        journal_debit.id)
                    journal_credit_map["journal_account_credit_id"] = str(
                        journal_credit.journal_account_credit.id) if journal_credit.journal_account_credit is not None else ""
                    journal_credit_map["journal_account_credit_name"] = journal_credit.journal_account_credit.account_name if journal_credit.journal_account_credit is not None else ""
                    journal_credit_map["credit_amount"] = journal_credit.credit_amount
                    journal_credit_list.append(journal_credit_map)
                journal_entry_map["journal_credit_list"] = journal_credit_list
                journal_entries_list.append(journal_entry_map)
            for transaction in all_transactions:
                transaction_map = {}
                transaction_map["transaction_id"] = str(transaction.id)
                transaction_map["transaction_number"] = transaction.transaction_number
                transaction_map["transaction_mode"] = transaction.transaction_mode
                transaction_map["transaction_amount"] = transaction.transaction_amount
                transaction_map["transaction_currency"] = transaction.transaction_currency
                transaction_map["exchange_rate"] = transaction.exchange_rate
                transaction_map["expense_id"] = str(
                    transaction.expense.id) if transaction.expense is not None else ""
                transaction_map["deposit_id"] = str(
                    transaction.deposit.id) if transaction.deposit is not None else ""
                transaction_map["account_id"] = str(
                    transaction.account.id) if transaction.account is not None else ""
                transaction_map["loan_portfolio_id"] = str(
                    transaction.loan_payment.id) if transaction.loan_payment is not None else ""
                transaction_map["transaction_reference"] = transaction.transaction_reference
                transaction_map["created_on"] = datetime.strftime(
                    transaction.created_on.astimezone(target_timezone), date_format) if transaction.created_on is not None else ""
                transaction_map["last_updated_on"] = datetime.strftime(
                    transaction.last_updated_on.astimezone(target_timezone), date_format) if transaction.last_updated_on is not None else ""
                creator_map = {}

                if transaction.transaction_mode == "outflow":
                    # print("running")
                    creator_map["staff_id"] = str(
                        transaction.expense.created_by.id) if transaction.expense is not None else ""
                    creator_map["staff_name"] = f'{transaction.expense.created_by.first_name} {transaction.expense.created_by.last_name}' if transaction.expense is not None else ""
                    creator_map["staff_position"] = transaction.expense.created_by.staff_position.position_title if transaction.expense is not None else ""
                    transaction_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        transaction.expense.last_updated_by.id) if transaction.expense is not None else ""
                    creator_map["staff_name"] = f'{transaction.expense.last_updated_by.first_name} {transaction.expense.last_updated_by.last_name}' if transaction.expense is not None else ""
                    creator_map["staff_position"] = transaction.expense.last_updated_by.staff_position.position_title if transaction.expense is not None else ""
                    transaction_map["last_updated_by"] = creator_map

                else:
                    creator_map["staff_id"] = str(
                        transaction.deposit.created_by.id) if transaction.deposit is not None else ""
                    creator_map["staff_name"] = f'{transaction.deposit.created_by.first_name} {transaction.deposit.created_by.last_name}' if transaction.deposit is not None else ""
                    creator_map["staff_position"] = transaction.deposit.created_by.staff_position.position_title if transaction.deposit is not None else ""
                    transaction_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        transaction.deposit.last_updated_by.id) if transaction.deposit is not None else ""
                    creator_map["staff_name"] = f'{transaction.deposit.last_updated_by.first_name} {transaction.deposit.last_updated_by.last_name}' if transaction.deposit is not None else ""
                    creator_map["staff_position"] = transaction.deposit.last_updated_by.staff_position.position_title if transaction.deposit is not None else ""
                    transaction_map["last_updated_by"] = creator_map
                transaction_list.append(transaction_map)
            for supplier in all_suppliers:
                if supplier.recycle_bin != True:
                    supplier_map = {}
                    # supplied_products_list = []
                    supplier_map["supplier_id"] = str(supplier.id)
                    # supplier_map["preferred_currency"] = company_profile.company_preferred_currency
                    supplier_map["supplier_name"] = supplier.supplier_name
                    supplier_list.append(supplier_map)
            for purchase_order in company_purchase_orders:
                product_purchase_instances_list = []
                purchase_order_product_instances_list = []
                purchase_order_map = {}
                purchase_order_map["purchase_order_id"] = str(
                    purchase_order.id)
                purchase_order_map["purchase_order_number"] = purchase_order.purchase_order_number
                purchase_order_map["currency"] = company_profile.company_preferred_currency
                purchase_order_map["purchase_value_overall"] = purchase_order.purchase_value_overall
                purchase_order_map["purchase_order_approved"] = "true" if purchase_order.purchase_order_approved == True else "false"
                purchase_order_map["purchase_order_landed_costs_overall"] = purchase_order.purchase_order_landed_costs_overall
                purchase_order_map["created_on"] = datetime.strftime(
                    purchase_order.created_on.astimezone(target_timezone), date_format) if purchase_order.created_on is not None else ""
                purchase_order_map["last_updated_on"] = datetime.strftime(
                    purchase_order.last_updated_on.astimezone(target_timezone), date_format) if purchase_order.last_updated_on is not None else ""
                creator_map = {}
                creator_map["staff_id"] = str(
                    purchase_order.created_by.id) if purchase_order.created_by is not None else ""
                creator_map["staff_name"] = f'{purchase_order.created_by.first_name} {purchase_order.created_by.last_name}' if purchase_order.created_by is not None else ""
                creator_map["staff_position"] = purchase_order.created_by.staff_position.position_title if purchase_order.created_by is not None else ""
                purchase_order_map["created_by"] = creator_map
                creator_map = {}
                creator_map["staff_id"] = str(
                    purchase_order.last_updated_by.id) if purchase_order.last_updated_by is not None else ""
                creator_map["staff_name"] = f'{purchase_order.last_updated_by.first_name} {purchase_order.last_updated_by.last_name}' if purchase_order.last_updated_by is not None else ""
                creator_map["staff_position"] = purchase_order.last_updated_by.staff_position.position_title if purchase_order.last_updated_by is not None else ""
                purchase_order_map["last_updated_by"] = creator_map
                #
                creator_map = {}
                creator_map["staff_id"] = str(
                    purchase_order.purchase_order_approved_by.id) if purchase_order.purchase_order_approved_by is not None else ""
                creator_map["staff_name"] = f'{purchase_order.purchase_order_approved_by.first_name} {purchase_order.purchase_order_approved_by.last_name}' if purchase_order.purchase_order_approved_by is not None else ""
                creator_map["staff_position"] = purchase_order.purchase_order_approved_by.staff_position.position_title if purchase_order.purchase_order_approved_by is not None else ""
                purchase_order_map["purchase_order_approved_by"] = creator_map
                purchase_order_product_instances = purchase_order.purchase_order_product_instances.filter(
                    recycle_bin=False).order_by("-id")
                # print(len(purchase_order_product_instances))
                for product_purchase_instance in purchase_order_product_instances:
                    purchase_order_product_instance_map = {}
                    # print(product_purchase_instance.id)
                    landed_cost_product_purchase_instances_list = []
                    purchase_order_product_instance_map["product_purchase_instance_id"] = str(
                        product_purchase_instance.id)
                    purchase_order_product_instance_map["product_id"] = str(
                        product_purchase_instance.purchase_product.id) if product_purchase_instance.purchase_product is not None else ""
                    purchase_order_product_instance_map["purchase_order_number"] = purchase_order.purchase_order_number
                    purchase_order_product_instance_map["supplier_id"] = str(
                        product_purchase_instance.supplier.id) if product_purchase_instance.supplier is not None else ""
                    purchase_order_product_instance_map[
                        "purchase_value_per_unit"] = product_purchase_instance.purchase_value_per_unit
                    purchase_order_product_instance_map[
                        "cost_currency"] = product_purchase_instance.cost_currency
                    purchase_order_product_instance_map[
                        "exchange_rate"] = product_purchase_instance.exchange_rate
                    purchase_order_product_instance_map[
                        "purchase_value_overall"] = product_purchase_instance.purchase_value_overall
                    purchase_order_product_instance_map[
                        "purchase_amount_paid_to_supplier"] = product_purchase_instance.purchase_amount_paid_to_supplier
                    purchase_order_product_instance_map[
                        "supplier_payment_settled"] = "true" if product_purchase_instance.supplier_payment_settled == True else "false"
                    # purchase_order_product_instance_map[
                    #     "supplier_payment_settled"] = "true" if product_purchase_instance.supplier_payment_settled == True else "false"
                    purchase_order_product_instance_map[
                        "product_purchase_delivered"] = "true" if product_purchase_instance.product_purchase_delivered == True else "false"
                    purchase_order_product_instance_map[
                        "quantity_purchased"] = product_purchase_instance.quantity_purchased
                    purchase_order_product_instance_map[
                        "quantity_delivered"] = product_purchase_instance.quantity_delivered
                    # purchase_order_product_instance_map[
                    #     "quantity_delivered"] = product_purchase_instance.quantity_delivered
                    purchase_order_product_instance_map["created_on"] = datetime.strftime(
                        purchase_order.created_on, date_format) if product_purchase_instance.created_on is not None else ""
                    purchase_order_product_instance_map["last_updated_on"] = datetime.strftime(
                        product_purchase_instance.last_updated_on, date_format) if product_purchase_instance.last_updated_on is not None else ""
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        product_purchase_instance.created_by.id) if product_purchase_instance.created_by is not None else ""
                    creator_map["staff_name"] = f'{product_purchase_instance.created_by.first_name} {product_purchase_instance.created_by.last_name}' if product_purchase_instance.created_by is not None else ""
                    creator_map["staff_position"] = product_purchase_instance.created_by.staff_position.position_title if product_purchase_instance.created_by is not None else ""
                    purchase_order_product_instance_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        product_purchase_instance.last_updated_by.id) if product_purchase_instance.last_updated_by is not None else ""
                    creator_map["staff_name"] = f'{product_purchase_instance.last_updated_by.first_name} {product_purchase_instance.last_updated_by.last_name}' if product_purchase_instance.last_updated_by is not None else ""
                    creator_map["staff_position"] = product_purchase_instance.last_updated_by.staff_position.position_title if product_purchase_instance.last_updated_by is not None else ""
                    purchase_order_product_instance_map["last_updated_by"] = creator_map
                    landed_cost_product_purchase_instances = product_purchase_instance.landed_cost_product_purchase_instances.all().order_by("-id")
                    for landed_cost_instance in landed_cost_product_purchase_instances:
                        # print(landed_cost_instance)
                        landed_cost_instance_map = {}
                        landed_cost_instance_map["landed_cost_id"] = str(
                            landed_cost_instance.landed_cost.id) if landed_cost_instance.landed_cost is not None else ""
                        landed_cost_instance_map["landed_cost_instance_id"] = str(
                            landed_cost_instance.id)
                        landed_cost_instance_map["cost_value"] = landed_cost_instance.cost_value
                        landed_cost_instance_map["exchange_rate"] = landed_cost_instance.exchange_rate
                        landed_cost_instance_map["cost_currency"] = landed_cost_instance.cost_currency
                        landed_cost_instance_map["cost_amount_paid"] = landed_cost_instance.cost_amount_paid
                        landed_cost_instance_map["cost_amount_due"] = landed_cost_instance.cost_amount_due
                        landed_cost_instance_map["cost_payment_settled"] = "true" if landed_cost_instance.cost_payment_settled == True else "false"
                        # print(landed_cost_instance_map)
                        landed_cost_product_purchase_instances_list.append(
                            landed_cost_instance_map)
                    purchase_order_product_instance_map[
                        "landed_cost_product_purchase_instances_list"] = landed_cost_product_purchase_instances_list
                    purchase_order_product_instances_list.append(
                        purchase_order_product_instance_map)
                    # print(landed_cost_product_purchase_instances_list)
                    landed_cost_product_purchase_instances_list = []
                    purchase_order_product_instances_list.append(
                        purchase_order_product_instance_map)
                # print(len(purchase_order_product_instances_list))
                purchase_order_map["purchase_order_product_instances_list"] = purchase_order_product_instances_list
                # print(
                #     purchase_order_map["purchase_order_product_instances_list"])
                purchase_order_product_instances_list = []
                purchase_order_list.append(purchase_order_map)
            for branch in all_branches:
                if branch.recycle_bin != True:
                    company_branch_map = {}
                    deposit_list = []
                    expense_list = []
                    chart_of_account_list = []
                    company_branch_map["branch_id"] = str(branch.id)
                    company_branch_map["branch_name"] = branch.branch_name
                    company_branch_map["is_main_branch"] = "true" if branch.main_branch == True else "false"
                    all_deposits = branch.branch_deposits.all().order_by("-id")
                    for deposit in all_deposits:
                        deposit_map = {}
                        deposit_map["deposit_id"] = str(deposit.id)
                        deposit_map["deposit_number"] = deposit.deposit_number
                        deposit_map["deposit_source"] = deposit.deposit_source
                        deposit_map["deposit_amount"] = deposit.deposit_amount
                        deposit_map["order_payment_reference"] = deposit.order_payment_reference
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            deposit.created_by.id) if deposit.created_by is not None else ""
                        creator_map["staff_name"] = f'{deposit.created_by.first_name} {deposit.created_by.last_name}' if deposit.created_by is not None else ""
                        creator_map["staff_position"] = deposit.created_by.staff_position.position_title if deposit.created_by is not None else ""
                        deposit_map["created_by"] = creator_map
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            deposit.last_updated_by.id) if deposit.last_updated_by is not None else ""
                        creator_map["staff_name"] = f'{deposit.last_updated_by.first_name} {deposit.last_updated_by.last_name}' if deposit.last_updated_by is not None else ""
                        creator_map["staff_position"] = deposit.last_updated_by.staff_position.position_title if deposit.last_updated_by is not None else ""
                        deposit_map["last_updated_by"] = creator_map
                        deposit_map["created_on"] = datetime.strftime(
                            deposit.created_on.astimezone(target_timezone), date_format) if deposit.created_on is not None else ""
                        deposit_map["last_updated_on"] = datetime.strftime(
                            deposit.last_updated_on.astimezone(target_timezone), date_format) if deposit.last_updated_on is not None else ""
                        deposit_list.append(deposit_map)
                    company_branch_map["deposit_list"] = deposit_list
                    all_expenses = branch.branch_expenses.all().order_by("-id")
                    for expense in all_expenses:
                        expense_map = {}
                        expense_map["expense_id"] = str(expense.id)
                        expense_map["expense_number"] = expense.expense_number
                        expense_map["expense_title"] = expense.expense_title
                        expense_map["expense_description"] = expense.expense_description
                        expense_map["expense_type"] = expense.expense_type
                        expense_map["payroll_sheet_id"] = str(
                            expense.payroll_sheet.id) if expense.payroll_sheet is not None else ""
                        # expense_map["purchase_order_id"] = str(
                        #     expense.purchase_order.id) if expense.purchase_order is not None else ""
                        product_purchase_expenses = expense.product_purchase_instance.all()
                        purchase_expense_list = []
                        for purchase_expense in product_purchase_expenses:
                            if purchase_expense.recycle_bin != True:
                                purchase_expense_map = {}
                                purchase_expense_map["purchase_expense_id"] = str(
                                    purchase_expense.id)
                                purchase_expense_map["product_purchase_instance_id"] = str(
                                    purchase_expense.id)
                                purchase_expense_map["purchase_value_per_unit"] = purchase_expense.purchase_value_per_unit
                                purchase_expense_map["purchase_value_overall"] = purchase_expense.purchase_value_overall
                                purchase_expense_map["purchase_amount_paid_to_supplier"] = purchase_expense.purchase_amount_paid_to_supplier
                                purchase_expense_map["supplier_payment_settled"] = "true" if purchase_expense.supplier_payment_settled == True else "false"
                                purchase_expense_map["supplier_id"] = str(
                                    purchase_expense.supplier.id)
                                purchase_expense_map["purchase_order_id"] = str(
                                    purchase_expense.purchase_order.id)
                                purchase_expense_map["purchase_order_number"] = purchase_expense.purchase_order.purchase_order_number
                                purchase_expense_list.append(
                                    purchase_expense_map)
                        expense_map["purchase_expense_list"] = purchase_expense_list

                        expense_map["refund_id"] = str(
                            expense.refund.id) if expense.refund is not None else ""
                        expense_map["expense_amount"] = expense.expense_amount
                        try:
                            expense_map["expense_transaction_id"] = str(
                                Transaction.objects.get(expense=expense).id)
                        except:
                            expense_map["expense_transaction_id"] = ""
                        # expense_map["expense_transaction_id"] = str(
                        #     expense.expense_transaction.id) if expense.expense_transaction is not None else ""
                        expense_map["expense_settled"] = "true" if expense.expense_settled == True else "false"
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            expense.created_by.id) if expense.created_by is not None else ""
                        creator_map["staff_name"] = f'{expense.created_by.first_name} {expense.created_by.last_name}' if expense.created_by is not None else ""
                        creator_map["staff_position"] = expense.created_by.staff_position.position_title if expense.created_by is not None else ""
                        expense_map["created_by"] = creator_map
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            expense.last_updated_by.id) if expense.last_updated_by is not None else ""
                        creator_map["staff_name"] = f'{expense.last_updated_by.first_name} {expense.last_updated_by.last_name}' if expense.last_updated_by is not None else ""
                        creator_map["staff_position"] = expense.last_updated_by.staff_position.position_title if expense.last_updated_by is not None else ""
                        expense_map["last_updated_by"] = creator_map
                        # expense approved
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            expense.last_updated_by.id) if expense.expense_approved_by is not None else ""
                        creator_map["staff_name"] = f'{expense.expense_approved_by.first_name} {expense.expense_approved_by.last_name}' if expense.expense_approved_by is not None else ""
                        creator_map["staff_position"] = expense.expense_approved_by.staff_position.position_title if expense.expense_approved_by is not None else ""
                        expense_map["expense_approved_by"] = creator_map
                        #
                        expense_map["created_on"] = datetime.strftime(
                            expense.created_on.astimezone(target_timezone), date_format) if expense.created_on is not None else ""
                        expense_map["last_updated_on"] = datetime.strftime(
                            expense.last_updated_on.astimezone(target_timezone), date_format) if expense.last_updated_on is not None else ""
                        expense_list.append(expense_map)
                    company_branch_map["expense_list"] = expense_list
                    all_chart_of_accounts = branch.branch_chart_of_accounts.all().order_by("-id")
                    for account in all_chart_of_accounts:
                        if account.recycle_bin != True:
                            chart_of_account_map = {}
                            chart_of_account_map["account_id"] = str(
                                account.id)
                            chart_of_account_map["account_name"] = account.account_name
                            chart_of_account_map["account_number"] = account.account_number
                            chart_of_account_map["account_descriptions"] = account.account_descriptions
                            chart_of_account_map["banking_institution_name"] = account.banking_institution_name
                            chart_of_account_map["bank_branch_name"] = account.bank_branch_name
                            chart_of_account_map["bank_branch_code"] = account.bank_branch_code
                            chart_of_account_map["bank_swift_code"] = account.bank_swift_code
                            chart_of_account_map["bank_sort_code"] = account.bank_sort_code
                            chart_of_account_map["is_mpesa_account"] = "true" if account.is_mpesa_account == True else "false"
                            # chart_of_account_map["running_balance"] = account.running_balance
                            chart_of_account_map["account_currency"] = account.account_currency
                            chart_of_account_map["running_balance"] = account.running_balance
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                account.created_by.id) if account.created_by is not None else ""
                            creator_map["staff_name"] = f'{account.created_by.first_name} {account.created_by.last_name}' if account.created_by is not None else ""
                            creator_map["staff_position"] = account.created_by.staff_position.position_title if account.created_by is not None else ""
                            chart_of_account_map["created_by"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                account.last_updated_by.id) if account.last_updated_by is not None else ""
                            creator_map["staff_name"] = f'{account.last_updated_by.first_name} {account.last_updated_by.last_name}' if account.last_updated_by is not None else ""
                            creator_map["staff_position"] = account.last_updated_by.staff_position.position_title if account.last_updated_by is not None else ""
                            chart_of_account_map["last_updated_by"] = creator_map
                            chart_of_account_map["created_on"] = datetime.strftime(
                                account.created_on.astimezone(target_timezone), date_format) if account.created_on is not None else ""
                            chart_of_account_map["last_updated_on"] = datetime.strftime(
                                account.last_updated_on.astimezone(target_timezone), date_format) if account.last_updated_on is not None else ""
                            account_transactions = account.account_transactions.all().order_by("-id")
                            account_transactions_list = []
                            for account_transaction in account_transactions:
                                account_transactions_map = {}
                                account_transactions_map["account_transaction_id"] = str(
                                    account_transaction.id)
                                account_transactions_map["transaction_amount"] = account_transaction.transaction_amount
                                account_transactions_list.append(
                                    account_transactions_map)
                            chart_of_account_map["account_transactions_list"] = account_transactions_list
                            chart_of_account_list.append(chart_of_account_map)
                    company_branch_map["chart_of_account_list"] = chart_of_account_list
                    branch_customer_orders = branch.branch_customer_orders.all().order_by("-id")
                    customer_orders_list = []
                    for customer_order in branch_customer_orders:
                        if customer_order.recycle_bin != True:
                            customer_order_map = {}
                            customer_order_items_list = []
                            order_items_return_list = []
                            customer_order_payments_list = []
                            customer_order_map["customer_order_id"] = str(
                                customer_order.id)
                            customer_order_map["customer_order_number"] = customer_order.customer_order_number
                            customer_order_map["customer_order_type"] = customer_order.customer_order_type
                            customer_order_map["customer_order_description"] = customer_order.customer_order_description
                            customer_order_map["customer_order_total_gross_value"] = customer_order.customer_order_total_gross_value
                            customer_order_map["customer_order_total_discount"] = customer_order.customer_order_total_discount
                            customer_order_map["customer_order_total_net_value"] = customer_order.customer_order_total_net_value
                            customer_order_map["customer_order_approved"] = "true" if customer_order.customer_order_approved == True else "false"
                            customer_order_map["customer_order_fulfilled_for_transit"] = "true" if customer_order.customer_order_fulfilled_for_transit == True else "false"
                            customer_order_map["customer_ordered_delivered_to_destination"] = "true" if customer_order.customer_ordered_delivered_to_destination == True else "false"
                            customer_order_map["customer_order_picked_by_customer"] = "true" if customer_order.customer_order_picked_by_customer == True else "false"
                            customer_order_map["customer_order_cancelled_by_customer"] = "true" if customer_order.customer_order_cancelled_by_customer == True else "false"
                            customer_order_map["customer_order_cancelled_by_sales_team"] = "true" if customer_order.customer_order_cancelled_by_sales_team == True else "false"
                            customer_order_map["customer_order_total_amount_paid"] = customer_order.customer_order_total_amount_paid
                            customer_order_map["expected_delivery_date"] = customer_order.expected_delivery_date if customer_order.expected_delivery_date is not None else ""
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                customer_order.sales_person.id) if customer_order.sales_person is not None else ""
                            creator_map["staff_name"] = f'{customer_order.sales_person.first_name} {customer_order.sales_person.last_name}' if customer_order.sales_person is not None else ""
                            creator_map["staff_position"] = customer_order.sales_person.staff_position.position_title if customer_order.sales_person.staff_position is not None else ""
                            customer_order_map["sales_person"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                customer_order.created_by.id) if customer_order.created_by is not None else ""
                            creator_map["staff_name"] = f'{customer_order.created_by.first_name} {customer_order.created_by.last_name}' if customer_order.created_by is not None else ""
                            creator_map["staff_position"] = customer_order.created_by.staff_position.position_title if customer_order.created_by is not None else ""
                            customer_order_map["created_by"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                customer_order.last_updated_by.id) if customer_order.last_updated_by is not None else ""
                            creator_map["staff_name"] = f'{customer_order.last_updated_by.first_name} {customer_order.last_updated_by.last_name}' if customer_order.last_updated_by is not None else ""
                            creator_map["staff_position"] = customer_order.last_updated_by.staff_position.position_title if customer_order.last_updated_by is not None else ""
                            customer_order_map["last_updated_by"] = creator_map
                            customer_map = {}
                            customer_map["customer_profile_id"] = str(
                                customer_order.customer_profile.id) if customer_order.customer_profile is not None else ""
                            customer_map["customer_name"] = f"{customer_order.customer_profile.customer_first_name} {customer_order.customer_profile.customer_last_name}" if customer_order.customer_profile is not None else ""
                            customer_map["company_name"] = customer_order.customer_profile.company_name if customer_order.customer_profile is not None else ""
                            customer_map["customer_type"] = customer_order.customer_profile.customer_type if customer_order.customer_profile is not None else ""
                            customer_map["email_address"] = customer_order.customer_profile.email_address if customer_order.customer_profile is not None else ""
                            customer_map["phone_number"] = customer_order.customer_profile.phone_number if customer_order.customer_profile is not None else ""
                            customer_order_map["customer_map"] = customer_map
                            customer_order_map["created_on"] = datetime.strftime(
                                customer_order.created_on.astimezone(target_timezone), date_format) if customer_order.created_on is not None else ""
                            customer_order_map["last_updated_on"] = datetime.strftime(
                                customer_order.last_updated_on.astimezone(target_timezone), date_format) if customer_order.last_updated_on is not None else ""
                            customer_order_items = customer_order.customer_order_items.all().order_by("-id")
                            for customer_order_item in customer_order_items:
                                customer_order_item_map = {}
                                customer_order_item_map["customer_order_item_id"] = str(
                                    customer_order_item.id)
                                customer_order_item_map["product_id"] = str(
                                    customer_order_item.product.id)
                                customer_order_item_map["product_name"] = customer_order_item.product.product_name
                                customer_order_item_map["quantity"] = customer_order_item.quantity
                                customer_order_item_map["price_per_item"] = customer_order_item.price_per_item
                                customer_order_item_map["discount_per_item"] = customer_order_item.discount_per_item
                                customer_order_item_map["gross_subtotal"] = customer_order_item.gross_subtotal
                                customer_order_item_map["total_discount"] = customer_order_item.total_discount
                                customer_order_item_map["net_subtotal"] = customer_order_item.net_subtotal
                                customer_order_item_map["sales_item_order_fulfilled"] = "true" if customer_order_item.sales_item_order_fulfilled == True else "false"
                                customer_order_items_list.append(
                                    customer_order_item_map)
                            customer_order_map["customer_order_items_list"] = customer_order_items_list
                            customer_order_payments = customer_order.customer_order_payments.all().order_by("-id")
                            for order_payment in customer_order_payments:
                                if order_payment.recycle_bin != True:
                                    customer_order_payment_map = {}
                                    refunds_list = []
                                    customer_order_payment_map["customer_order_payment_id"] = str(
                                        order_payment.id)
                                    customer_order_payment_map["payment_number"] = order_payment.payment_number
                                    customer_order_payment_map["payment_amount"] = order_payment.payment_amount
                                    customer_order_payment_map["payment_method"] = order_payment.payment_method
                                    customer_order_payment_map["payer_account_number"] = order_payment.payer_account_number
                                    customer_order_payment_map["account_paid_to"] = order_payment.account_paid_to.account_number if order_payment.account_paid_to is not None else ""
                                    customer_order_payment_map["currency"] = order_payment.account_paid_to.account_currency if order_payment.account_paid_to is not None else ""
                                    creator_map = {}
                                    creator_map["staff_id"] = str(
                                        order_payment.created_by.id) if order_payment.created_by is not None else ""
                                    creator_map["staff_name"] = f'{order_payment.created_by.first_name} {order_payment.created_by.last_name}' if order_payment.created_by is not None else ""
                                    creator_map["staff_position"] = order_payment.created_by.staff_position.position_title if order_payment.created_by.staff_position is not None else ""
                                    customer_order_payment_map["created_by"] = creator_map
                                    creator_map = {}
                                    creator_map["staff_id"] = str(
                                        order_payment.last_updated_by.id) if order_payment.last_updated_by is not None else ""
                                    creator_map["staff_name"] = f'{order_payment.last_updated_by.first_name} {order_payment.last_updated_by.last_name}' if order_payment.last_updated_by is not None else ""
                                    creator_map["staff_position"] = order_payment.last_updated_by.staff_position.position_title if order_payment.last_updated_by is not None else ""
                                    customer_order_payment_map["last_updated_by"] = creator_map
                                    customer_order_payment_map["created_on"] = datetime.strftime(
                                        order_payment.created_on.astimezone(target_timezone), date_format) if order_payment.created_on is not None else ""
                                    customer_order_payment_map["last_updated_on"] = datetime.strftime(
                                        order_payment.last_updated_on.astimezone(target_timezone), date_format) if order_payment.last_updated_on is not None else ""
                                    # attach refunds
                                    # payment_refunds = order_payment.payment_refunds.all().order_by("-id")
                                    # for refund in payment_refunds:
                                    #     if refund.recycle_bin != True:
                                    #         refund_map = {}
                                    #         refund_map["refund_id"] = str(
                                    #             refund.id)
                                    #         refund_map["order_item_return_id"] = str(
                                    #             refund.order_item_return.id) if refund.order_item_return is not None else ""
                                    #         refund_map["refund_amount"] = refund.refund_amount
                                    #         refund_map["refund_approved"] = "true" if refund.refund_approved == True else "false"
                                    #         refund_map["refund_fullfilled"] = "true" if refund.refund_fullfilled == True else "false"
                                    #         creator_map = {}
                                    #         creator_map["staff_id"] = str(
                                    #             refund.created_by.id) if refund.created_by is not None else ""
                                    #         creator_map["staff_name"] = f'{refund.created_by.first_name} {refund.created_by.last_name}' if refund.created_by is not None else ""
                                    #         creator_map["staff_position"] = refund.created_by.staff_position.position_title if refund.created_by.staff_position is not None else ""
                                    #         refund_map["created_by"] = creator_map
                                    #         creator_map = {}
                                    #         creator_map["staff_id"] = str(
                                    #             refund.last_updated_by.id) if refund.last_updated_by is not None else ""
                                    #         creator_map["staff_name"] = f'{refund.last_updated_by.first_name} {refund.last_updated_by.last_name}' if refund.last_updated_by is not None else ""
                                    #         creator_map["staff_position"] = refund.last_updated_by.staff_position.position_title if refund.last_updated_by.staff_position is not None else ""
                                    #         refund_map["last_updated_by"] = creator_map
                                    #         refund_map["created_on"] = datetime.strftime(
                                    #             refund.created_on.astimezone(target_timezone), date_format) if refund.created_on is not None else ""
                                    #         refund_map["last_updated_on"] = datetime.strftime(
                                    #             refund.last_updated_on.astimezone(target_timezone), date_format) if refund.last_updated_on is not None else ""
                                    #         refunds_list.append(refund_map)
                                    # customer_order_payment_map["refunds_list"] = refunds_list
                                    customer_order_payments_list.append(
                                        customer_order_payment_map)
                            customer_order_map["customer_order_payments_list"] = customer_order_payments_list
                            customer_orders_list.append(customer_order_map)
                    company_branch_map["customer_orders_list"] = customer_orders_list
                    company_branches_list.append(company_branch_map)
            # print(purchase_order_list)
            company_profile_map["purchase_order_list"] = purchase_order_list
            company_profile_map["company_branches_list"] = company_branches_list
            payload["company_profile"] = company_profile_map
            payload["active_staff_profile_data"] = active_staff_profile_data
            payload["transaction_list"] = transaction_list
            payload["supplier_list"] = supplier_list
            payload["journal_entries_list"] = journal_entries_list
            return Response({"message": "true", "payload": payload}, status=200)
        else:
            return Response({"message": "false", "payload": payload}, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "false", "payload": payload}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def finance_sale(request):
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    current_date = datetime.now().date()
    company_serial_number = request.data["serial_number"]
    active_user = request.user
    payload = {}
    company_profile_map = {}
    company_branches_list = []
    company_branch_map = {}
    page_index = request.data.get("pageIndex", "1")
    start_index = 0
    last_index = 0
    try:
        if page_index == "1":
            start_index = 0
            last_index = 50
        elif page_index == "2":
            start_index = 50
            last_index = 100
        elif page_index == "3":
            start_index = 100
            last_index = 150
        elif page_index == "4":
            start_index = 150
            last_index = 200
        else:
            start_index = 200
            last_index = 0
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.dashboard.view"):
            active_staff_profile_data = get_staff_profile_data(active_user)
            company_profile_map["company_id"] = str(company_profile.id)
            company_profile_map["company_name"] = company_profile.company_name
            company_profile_map["company_phone"] = company_profile.company_phone
            company_profile_map["preferred_currency"] = company_profile.company_preferred_currency
            company_profile_map["company_postal_address"] = company_profile.company_postal_address
            all_branches = company_profile.company_branches.all().order_by("-id")
            for branch in all_branches:
                if branch.recycle_bin != True:
                    company_branch_map = {}
                    chart_of_account_list = []
                    expense_list = []
                    deposit_list = []
                    company_branch_map["branch_id"] = str(branch.id)
                    company_branch_map["branch_name"] = branch.branch_name
                    company_branch_map["is_main_branch"] = "true" if branch.main_branch == True else "false"
                    all_chart_of_accounts = branch.branch_chart_of_accounts.all().order_by("-id")
                    customer_orders_count = branch.branch_customer_orders.filter(
                        recycle_bin=False).count()
                    # print(customer_orders_count)
                    #
                    if last_index != 0:
                        branch_customer_orders = branch.branch_customer_orders.filter(
                            recycle_bin=False,).order_by(
                                "-id")[start_index:last_index]
                    else:
                        branch_customer_orders = branch.branch_customer_orders.filter(
                            recycle_bin=False,).order_by(
                            "-id")[start_index:]
                    #
                    customer_orders_list = []
                    for customer_order in branch_customer_orders:
                        if customer_order.recycle_bin != True:
                            customer_order_map = {}
                            customer_order_items_list = []
                            order_items_return_list = []
                            customer_order_payments_list = []
                            customer_order_map["customer_order_id"] = str(
                                customer_order.id)
                            customer_order_map["customer_order_number"] = customer_order.customer_order_number
                            customer_order_map["customer_order_type"] = customer_order.customer_order_type
                            customer_order_map["customer_order_description"] = customer_order.customer_order_description
                            customer_order_map["customer_order_total_gross_value"] = customer_order.customer_order_total_gross_value
                            customer_order_map["customer_order_total_discount"] = customer_order.customer_order_total_discount
                            customer_order_map["customer_order_total_net_value"] = customer_order.customer_order_total_net_value
                            customer_order_map["customer_order_approved"] = "true" if customer_order.customer_order_approved == True else "false"
                            customer_order_map["customer_order_fulfilled_for_transit"] = "true" if customer_order.customer_order_fulfilled_for_transit == True else "false"
                            customer_order_map["customer_ordered_delivered_to_destination"] = "true" if customer_order.customer_ordered_delivered_to_destination == True else "false"
                            customer_order_map["customer_order_picked_by_customer"] = "true" if customer_order.customer_order_picked_by_customer == True else "false"
                            customer_order_map["customer_order_cancelled_by_customer"] = "true" if customer_order.customer_order_cancelled_by_customer == True else "false"
                            customer_order_map["customer_order_cancelled_by_sales_team"] = "true" if customer_order.customer_order_cancelled_by_sales_team == True else "false"
                            customer_order_map["customer_order_total_amount_paid"] = customer_order.customer_order_total_amount_paid
                            customer_order_map["expected_delivery_date"] = customer_order.expected_delivery_date if customer_order.expected_delivery_date is not None else ""
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                customer_order.sales_person.id) if customer_order.sales_person is not None else ""
                            creator_map["staff_name"] = f'{customer_order.sales_person.first_name} {customer_order.sales_person.last_name}' if customer_order.sales_person is not None else ""
                            creator_map["staff_position"] = customer_order.sales_person.staff_position.position_title if customer_order.sales_person.staff_position is not None else ""
                            customer_order_map["sales_person"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                customer_order.created_by.id) if customer_order.created_by is not None else ""
                            creator_map["staff_name"] = f'{customer_order.created_by.first_name} {customer_order.created_by.last_name}' if customer_order.created_by is not None else ""
                            creator_map["staff_position"] = customer_order.created_by.staff_position.position_title if customer_order.created_by.staff_position is not None else ""
                            customer_order_map["created_by"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                customer_order.last_updated_by.id) if customer_order.last_updated_by is not None else ""
                            creator_map["staff_name"] = f'{customer_order.last_updated_by.first_name} {customer_order.last_updated_by.last_name}' if customer_order.last_updated_by is not None else ""
                            creator_map["staff_position"] = customer_order.last_updated_by.staff_position.position_title if customer_order.last_updated_by.staff_position is not None else ""
                            customer_order_map["last_updated_by"] = creator_map
                            customer_map = {}
                            customer_map["customer_profile_id"] = str(
                                customer_order.customer_profile.id) if customer_order.customer_profile is not None else ""
                            customer_map["customer_name"] = f"{customer_order.customer_profile.customer_first_name} {customer_order.customer_profile.customer_last_name}" if customer_order.customer_profile is not None else ""
                            customer_map["company_name"] = customer_order.customer_profile.company_name if customer_order.customer_profile is not None else ""
                            customer_map["customer_type"] = customer_order.customer_profile.customer_type if customer_order.customer_profile is not None else ""
                            customer_map["email_address"] = customer_order.customer_profile.email_address if customer_order.customer_profile is not None else ""
                            customer_map["phone_number"] = customer_order.customer_profile.phone_number if customer_order.customer_profile is not None else ""
                            customer_order_map["customer_map"] = customer_map
                            customer_order_map["created_on"] = datetime.strftime(
                                customer_order.created_on.astimezone(target_timezone), date_format) if customer_order.created_on is not None else ""
                            customer_order_map["last_updated_on"] = datetime.strftime(
                                customer_order.last_updated_on.astimezone(target_timezone), date_format) if customer_order.last_updated_on is not None else ""
                            customer_order_items = customer_order.customer_order_items.all().order_by("-id")
                            for customer_order_item in customer_order_items:
                                customer_order_item_map = {}
                                customer_order_item_map["customer_order_item_id"] = str(
                                    customer_order_item.id)
                                customer_order_item_map["product_id"] = str(
                                    customer_order_item.product.id)
                                customer_order_item_map["product_name"] = customer_order_item.product.product_name
                                customer_order_item_map["quantity"] = customer_order_item.quantity
                                customer_order_item_map["price_per_item"] = customer_order_item.price_per_item
                                customer_order_item_map["discount_per_item"] = customer_order_item.discount_per_item
                                customer_order_item_map["gross_subtotal"] = customer_order_item.gross_subtotal
                                customer_order_item_map["total_discount"] = customer_order_item.total_discount
                                customer_order_item_map["net_subtotal"] = customer_order_item.net_subtotal
                                customer_order_item_map["sales_item_order_fulfilled"] = "true" if customer_order_item.sales_item_order_fulfilled == True else "false"
                                customer_order_items_list.append(
                                    customer_order_item_map)
                            customer_order_map["customer_order_items_list"] = customer_order_items_list
                            # attach sales order to customer_order
                            try:
                                sales_order = SalesOrder.objects.get(
                                    customer_order=customer_order)
                                sales_order_map = {}
                                sales_order_items_list = []
                                sales_order_map["sales_order_id"] = str(
                                    sales_order.id)
                                sales_order_map["sales_order_number"] = sales_order.sales_order_number
                                sales_order_map["sale_outlet_id"] = str(
                                    sales_order.sale_outlet.id) if sales_order.sale_outlet is not None else ""
                                sales_order_map["sale_outlet_name"] = sales_order.sale_outlet.sale_outlet_name if sales_order.sale_outlet is not None else ""
                                sales_order_map["warehouse_id"] = str(
                                    sales_order.warehouse.id) if sales_order.warehouse is not None else ""
                                sales_order_map["warehouse_name"] = sales_order.warehouse.warehouse_name if sales_order.warehouse is not None else ""
                                sales_order_map["sales_order_description"] = sales_order.sales_order_description
                                sales_order_map["sales_order_approved"] = "true" if sales_order.sales_order_approved == True else "false"
                                sales_order_map["sales_order_fulfilled"] = "true" if sales_order.sales_order_fulfilled == True else "false"
                                creator_map = {}
                                creator_map["staff_id"] = str(
                                    sales_order.created_by.id) if sales_order.created_by is not None else ""
                                creator_map["staff_name"] = f'{sales_order.created_by.first_name} {sales_order.created_by.last_name}' if sales_order.created_by is not None else ""
                                creator_map["staff_position"] = sales_order.created_by.staff_position.position_title if sales_order.created_by.staff_position is not None else ""
                                sales_order_map["created_by"] = creator_map
                                creator_map = {}
                                creator_map["staff_id"] = str(
                                    sales_order.last_updated_by.id) if sales_order.last_updated_by is not None else ""
                                creator_map["staff_name"] = f'{sales_order.last_updated_by.first_name} {sales_order.last_updated_by.last_name}' if sales_order.last_updated_by is not None else ""
                                creator_map["staff_position"] = sales_order.last_updated_by.staff_position.position_title if sales_order.last_updated_by.staff_position is not None else ""
                                sales_order_map["last_updated_by"] = creator_map
                                sales_order_map["created_on"] = datetime.strftime(
                                    sales_order.created_on.astimezone(target_timezone), date_format) if sales_order.created_on is not None else ""
                                sales_order_map["last_updated_on"] = datetime.strftime(
                                    sales_order.last_updated_on.astimezone(target_timezone), date_format) if sales_order.last_updated_on is not None else ""
                                # attach sales order items
                                sales_order_sales_items = sales_order.sales_order_sales_items.all().order_by("-id")
                                for sales_order_item in sales_order_sales_items:
                                    sales_order_item_map = {}
                                    sales_order_item_map["sales_order_item_id"] = str(
                                        sales_order_item.id)
                                    sales_order_item_map["inventory_id"] = str(
                                        sales_order_item.inventory.id) if sales_order_item.inventory is not None else ""
                                    sales_order_item_map["quantity"] = sales_order_item.quantity
                                    sales_order_item_map["sales_item_order_fulfilled"] = "true" if sales_order_item.sales_item_order_fulfilled == True else "false"
                                    sales_order_items_list.append(
                                        sales_order_item_map)
                                sales_order_map["sales_order_items_list"] = sales_order_items_list
                                customer_order_map["sales_order_map"] = sales_order_map

                            except:
                                sales_order_map = {}
                                sales_order_map["sales_order_id"] = ""
                                sales_order_map["sales_order_number"] = ""
                                sales_order_map["sale_outlet_id"] = ""
                                sales_order_map["sale_outlet_name"] = ""
                                sales_order_map["warehouse_id"] = ""
                                sales_order_map["warehouse_name"] = ""
                                sales_order_map["sales_order_description"] = ""
                                sales_order_map["sales_order_approved"] = ""
                                sales_order_map["sales_order_fulfilled"] = ""
                                creator_map = {}
                                creator_map["staff_id"] = ""
                                creator_map["staff_name"] = ""
                                creator_map["staff_position"] = ""
                                sales_order_map["created_by"] = creator_map
                                creator_map = {}
                                creator_map["staff_id"] = ""
                                creator_map["staff_name"] = ""
                                creator_map["staff_position"] = ""
                                sales_order_map["last_updated_by"] = creator_map
                                sales_order_map["created_on"] = ""
                                sales_order_map["last_updated_on"] = ""
                                sales_order_map["sales_order_items_list"] = []
                                customer_order_map["sales_order_map"] = sales_order_map
                            # add customer order invoice
                            try:
                                customer_order_invoice = CustomerOrderInvoice.objects.get(
                                    customer_order=customer_order)
                                customer_order_invoice_map = {}
                                customer_order_invoice_map["customer_order_invoice_id"] = str(
                                    customer_order_invoice.id)
                                customer_order_invoice_map["customer_order_number"] = customer_order_invoice.customer_order.customer_order_number
                                customer_order_invoice_map["customer_order_invoice_number"] = customer_order_invoice.invoice_number
                                customer_order_invoice_map["customer_order_invoice_amount_due"] = customer_order_invoice.invoice_amount_due
                                customer_order_invoice_map["customer_order_invoice_amount_paid"] = customer_order_invoice.invoice_amount_paid
                                customer_order_invoice_map["customer_order_invoice_currency"] = customer_order_invoice.invoice_currency
                                customer_order_invoice_map["customer_order_invoice_settled"] = "true" if customer_order_invoice.invoice_settled == True else "false"
                                customer_order_invoice_map["created_on"] = datetime.strftime(
                                    customer_order_invoice.created_on.astimezone(target_timezone), date_format) if customer_order_invoice.created_on is not None else ""
                                customer_order_invoice_map["last_updated_on"] = datetime.strftime(
                                    customer_order_invoice.last_updated_on.astimezone(target_timezone), date_format) if customer_order_invoice.last_updated_on is not None else ""
                                creator_map = {}
                                creator_map["staff_id"] = str(
                                    customer_order_invoice.created_by.id) if customer_order_invoice.created_by is not None else ""
                                creator_map["staff_name"] = f'{customer_order_invoice.created_by.first_name} {customer_order_invoice.created_by.last_name}' if customer_order_invoice.created_by is not None else ""
                                creator_map["staff_position"] = customer_order_invoice.created_by.staff_position.position_title if customer_order_invoice.created_by.staff_position is not None else ""
                                customer_order_invoice_map["created_by"] = creator_map
                                creator_map = {}
                                creator_map["staff_id"] = str(
                                    customer_order_invoice.last_updated_by.id) if customer_order_invoice.last_updated_by is not None else ""
                                creator_map["staff_name"] = f'{customer_order_invoice.last_updated_by.first_name} {customer_order_invoice.last_updated_by.last_name}' if customer_order_invoice.last_updated_by is not None else ""
                                creator_map["staff_position"] = customer_order_invoice.last_updated_by.staff_position.position_title if customer_order_invoice.last_updated_by.staff_position is not None else ""
                                customer_order_invoice_map["last_updated_by"] = creator_map
                                customer_order_map["customer_order_invoice"] = customer_order_invoice_map
                            except:  # Exception as e:
                                # print(e)
                                customer_order_invoice_map = {}
                                customer_order_invoice_map["customer_order_invoice_id"] = ""
                                customer_order_invoice_map["customer_order_number"] = ""
                                customer_order_invoice_map["customer_order_invoice_number"] = ""
                                customer_order_invoice_map["customer_order_invoice_amount_due"] = ""
                                customer_order_invoice_map["customer_order_invoice_amount_paid"] = ""
                                customer_order_invoice_map["customer_order_invoice_currency"] = ""
                                customer_order_invoice_map["customer_order_invoice_settled"] = ""
                                customer_order_invoice_map["created_on"] = ""
                                customer_order_invoice_map["last_updated_on"] = ""
                                creator_map = {}
                                creator_map["staff_id"] = ""
                                creator_map["staff_name"] = ""
                                creator_map["staff_position"] = ""
                                customer_order_invoice_map["created_by"] = creator_map
                                creator_map = {}
                                creator_map["staff_id"] = ""
                                creator_map["staff_name"] = ""
                                creator_map["staff_position"] = ""
                                customer_order_invoice_map["last_updated_by"] = creator_map
                                customer_order_map["customer_order_invoice"] = customer_order_invoice_map

                            # attach order item returns
                            customer_order_items_return = customer_order.customer_order_items_return.all().order_by("-id")
                            for order_item_return in customer_order_items_return:
                                if order_item_return.recycle_bin != True:
                                    order_item_return_map = {}
                                    return_items_list = []
                                    order_item_return_map["order_item_return_id"] = str(
                                        order_item_return.id)
                                    order_item_return_map["refund_requested"] = "true" if order_item_return.refund_requested == True else "false"
                                    order_item_return_map["date_of_return"] = order_item_return.date_of_return if order_item_return.date_of_return is not None else ""
                                    order_item_return_map["created_on"] = datetime.strftime(
                                        order_item_return.created_on.astimezone(target_timezone), date_format) if order_item_return.created_on is not None else ""
                                    order_item_return_map["last_updated_on"] = datetime.strftime(
                                        order_item_return.last_updated_on.astimezone(target_timezone), date_format) if order_item_return.last_updated_on is not None else ""
                                    order_items_return = order_item_return.order_items_return
                                    for item_return in order_items_return:
                                        return_item_map = {}
                                        return_item_map["item_return_id"] = str(
                                            item_return.id)
                                        return_item_map["customer_order_item_id"] = str(
                                            item_return.ordered_item_returned.id) if item_return.ordered_item_returned is not None else ""
                                        return_item_map["reason_for_return"] = item_return.reason_for_return
                                        return_items_list.append(
                                            return_item_map)
                                    order_item_return_map["return_items_list"] = return_items_list
                                    order_items_return_list.append(
                                        order_item_return_map)
                            customer_order_map["order_items_return_list"] = order_items_return_list
                            # attach customer order payments
                            customer_order_payments = customer_order.customer_order_payments.all().order_by("-id")
                            for order_payment in customer_order_payments:
                                if order_payment.recycle_bin != True:
                                    customer_order_payment_map = {}
                                    refunds_list = []
                                    customer_order_payment_map["customer_order_payment_id"] = str(
                                        order_payment.id)
                                    customer_order_payment_map["payment_number"] = order_payment.payment_number
                                    customer_order_payment_map["payment_amount"] = order_payment.payment_amount
                                    customer_order_payment_map["payment_method"] = order_payment.payment_method
                                    customer_order_payment_map["payer_account_number"] = order_payment.payer_account_number
                                    customer_order_payment_map["account_paid_to"] = order_payment.account_paid_to.account_number if order_payment.account_paid_to is not None else ""
                                    customer_order_payment_map["currency"] = order_payment.account_paid_to.account_currency if order_payment.account_paid_to is not None else ""
                                    creator_map = {}
                                    creator_map["staff_id"] = str(
                                        order_payment.created_by.id) if order_payment.created_by is not None else ""
                                    creator_map["staff_name"] = f'{order_payment.created_by.first_name} {order_payment.created_by.last_name}' if order_payment.created_by is not None else ""
                                    creator_map["staff_position"] = order_payment.created_by.staff_position.position_title if order_payment.created_by.staff_position is not None else ""
                                    customer_order_payment_map["created_by"] = creator_map
                                    creator_map = {}
                                    creator_map["staff_id"] = str(
                                        order_payment.last_updated_by.id) if order_payment.last_updated_by is not None else ""
                                    creator_map["staff_name"] = f'{order_payment.last_updated_by.first_name} {order_payment.last_updated_by.last_name}' if order_payment.last_updated_by is not None else ""
                                    creator_map["staff_position"] = order_payment.last_updated_by.staff_position.position_title if order_payment.last_updated_by.staff_position is not None else ""
                                    customer_order_payment_map["last_updated_by"] = creator_map
                                    customer_order_payment_map["created_on"] = datetime.strftime(
                                        order_payment.created_on.astimezone(target_timezone), date_format) if order_payment.created_on is not None else ""
                                    customer_order_payment_map["last_updated_on"] = datetime.strftime(
                                        order_payment.last_updated_on.astimezone(target_timezone), date_format) if order_payment.last_updated_on is not None else ""
                                    # attach refunds
                                    payment_refunds = order_payment.payment_refunds.all().order_by("-id")
                                    for refund in payment_refunds:
                                        if refund.recycle_bin != True:
                                            refund_map = {}
                                            refund_map["refund_id"] = str(
                                                refund.id)
                                            refund_map["order_item_return_id"] = str(
                                                refund.order_item_return.id) if refund.order_item_return is not None else ""
                                            refund_map["refund_amount"] = refund.refund_amount
                                            refund_map["refund_approved"] = "true" if refund.refund_approved == True else "false"
                                            refund_map["refund_fullfilled"] = "true" if refund.refund_fullfilled == True else "false"
                                            creator_map = {}
                                            creator_map["staff_id"] = str(
                                                refund.created_by.id) if refund.created_by is not None else ""
                                            creator_map["staff_name"] = f'{refund.created_by.first_name} {refund.created_by.last_name}' if refund.created_by is not None else ""
                                            creator_map["staff_position"] = refund.created_by.staff_position.position_title if refund.created_by.staff_position is not None else ""
                                            refund_map["created_by"] = creator_map
                                            creator_map = {}
                                            creator_map["staff_id"] = str(
                                                refund.last_updated_by.id) if refund.last_updated_by is not None else ""
                                            creator_map["staff_name"] = f'{refund.last_updated_by.first_name} {refund.last_updated_by.last_name}' if refund.last_updated_by is not None else ""
                                            creator_map["staff_position"] = refund.last_updated_by.staff_position.position_title if refund.last_updated_by.staff_position is not None else ""
                                            refund_map["last_updated_by"] = creator_map
                                            refund_map["created_on"] = datetime.strftime(
                                                refund.created_on.astimezone(target_timezone), date_format) if refund.created_on is not None else ""
                                            refund_map["last_updated_on"] = datetime.strftime(
                                                refund.last_updated_on.astimezone(target_timezone), date_format) if refund.last_updated_on is not None else ""
                                            refunds_list.append(refund_map)
                                    customer_order_payment_map["refunds_list"] = refunds_list
                                    customer_order_payments_list.append(
                                        customer_order_payment_map)
                            customer_order_map["customer_order_payments_list"] = customer_order_payments_list
                            customer_orders_list.append(customer_order_map)
                    company_branch_map["customer_orders_list"] = customer_orders_list
                    company_branch_map["customer_orders_count"] = str(
                        customer_orders_count)
                    # end of customer orders
                    for account in all_chart_of_accounts:
                        if account.recycle_bin != True:
                            chart_of_account_map = {}
                            chart_of_account_map["account_id"] = str(
                                account.id)
                            chart_of_account_map["account_name"] = account.account_name
                            chart_of_account_map["account_number"] = account.account_number
                            chart_of_account_map["account_descriptions"] = account.account_descriptions
                            chart_of_account_map["banking_institution_name"] = account.banking_institution_name
                            chart_of_account_map["bank_branch_name"] = account.bank_branch_name
                            chart_of_account_map["bank_branch_code"] = account.bank_branch_code
                            chart_of_account_map["bank_swift_code"] = account.bank_swift_code
                            chart_of_account_map["bank_sort_code"] = account.bank_sort_code
                            chart_of_account_map["is_mpesa_account"] = "true" if account.is_mpesa_account == True else "false"
                            # chart_of_account_map["running_balance"] = account.running_balance
                            chart_of_account_map["account_currency"] = account.account_currency
                            chart_of_account_map["running_balance"] = account.running_balance
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                account.created_by.id) if account.created_by is not None else ""
                            creator_map["staff_name"] = f'{account.created_by.first_name} {account.created_by.last_name}' if account.created_by is not None else ""
                            creator_map["staff_position"] = account.created_by.staff_position.position_title if account.created_by.staff_position is not None else ""
                            chart_of_account_map["created_by"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                account.last_updated_by.id) if account.last_updated_by is not None else ""
                            creator_map["staff_name"] = f'{account.last_updated_by.first_name} {account.last_updated_by.last_name}' if account.last_updated_by is not None else ""
                            creator_map["staff_position"] = account.last_updated_by.staff_position.position_title if account.last_updated_by.staff_position is not None else ""
                            chart_of_account_map["last_updated_by"] = creator_map
                            chart_of_account_map["created_on"] = datetime.strftime(
                                account.created_on.astimezone(target_timezone), date_format) if account.created_on is not None else ""
                            chart_of_account_map["last_updated_on"] = datetime.strftime(
                                account.last_updated_on.astimezone(target_timezone), date_format) if account.last_updated_on is not None else ""
                            # account_transactions = account.account_transactions.all().order_by("-id")
                            account_transactions_list = []
                            # for account_transaction in account_transactions:
                            #     account_transactions_map = {}
                            #     account_transactions_map["account_transaction_id"] = str(
                            #         account_transaction.id)
                            #     account_transactions_map["transaction_amount"] = account_transaction.transaction_amount
                            #     account_transactions_list.append(
                            #         account_transactions_map)
                            chart_of_account_map["account_transactions_list"] = account_transactions_list
                            chart_of_account_list.append(chart_of_account_map)

                    # all_expenses = branch.branch_expenses.all().order_by("-id")
                    # for expense in all_expenses:
                    #     expense_map = {}
                    #     expense_map["expense_id"] = str(expense.id)
                    #     expense_map["expense_number"] = expense.expense_number
                    #     expense_map["expense_title"] = expense.expense_title
                    #     expense_map["expense_description"] = expense.expense_description
                    #     expense_map["expense_type"] = expense.expense_type
                    #     expense_map["payroll_sheet_id"] = str(
                    #         expense.payroll_sheet.id) if expense.payroll_sheet is not None else ""
                    #     # expense_map["purchase_order_id"] = str(
                    #     #     expense.purchase_order.id) if expense.purchase_order is not None else ""
                    #     product_purchase_expenses = expense.product_purchase_instance.all()
                    #     purchase_expense_list = []
                    #     for purchase_expense in product_purchase_expenses:
                    #         if purchase_expense.recycle_bin != True:
                    #             purchase_expense_map = {}
                    #             purchase_expense_map["purchase_expense_id"] = str(
                    #                 purchase_expense.id)
                    #             purchase_expense_map["product_purchase_instance_id"] = str(
                    #                 purchase_expense.id)
                    #             purchase_expense_map["purchase_value_per_unit"] = purchase_expense.purchase_value_per_unit
                    #             purchase_expense_map["purchase_value_overall"] = purchase_expense.purchase_value_overall
                    #             purchase_expense_map["purchase_amount_paid_to_supplier"] = purchase_expense.purchase_amount_paid_to_supplier
                    #             purchase_expense_map["supplier_payment_settled"] = "true" if purchase_expense.supplier_payment_settled == True else "false"
                    #             purchase_expense_map["supplier_id"] = str(
                    #                 purchase_expense.supplier.id)
                    #             purchase_expense_map["purchase_order_id"] = str(
                    #                 purchase_expense.purchase_order.id)
                    #             purchase_expense_map["purchase_order_number"] = purchase_expense.purchase_order.purchase_order_number
                    #             purchase_expense_list.append(
                    #                 purchase_expense_map)
                    #     expense_map["purchase_expense_list"] = purchase_expense_list

                    #     expense_map["refund_id"] = str(
                    #         expense.refund.id) if expense.refund is not None else ""
                    #     expense_map["expense_amount"] = expense.expense_amount
                    #     try:
                    #         expense_map["expense_transaction_id"] = str(
                    #             Transaction.objects.get(expense=expense).id)
                    #     except:
                    #         expense_map["expense_transaction_id"] = ""
                    #     # expense_map["expense_transaction_id"] = str(
                    #     #     expense.expense_transaction.id) if expense.expense_transaction is not None else ""
                    #     expense_map["expense_settled"] = "true" if expense.expense_settled == True else "false"
                    #     creator_map = {}
                    #     creator_map["staff_id"] = str(
                    #         expense.created_by.id) if expense.created_by is not None else ""
                    #     creator_map["staff_name"] = f'{expense.created_by.first_name} {expense.created_by.last_name}' if expense.created_by is not None else ""
                    #     creator_map["staff_position"] = expense.created_by.staff_position.position_title if expense.created_by.staff_position is not None else ""
                    #     expense_map["created_by"] = creator_map
                    #     creator_map = {}
                    #     creator_map["staff_id"] = str(
                    #         expense.last_updated_by.id) if expense.last_updated_by is not None else ""
                    #     creator_map["staff_name"] = f'{expense.last_updated_by.first_name} {expense.last_updated_by.last_name}' if expense.last_updated_by is not None else ""
                    #     creator_map["staff_position"] = expense.last_updated_by.staff_position.position_title if expense.last_updated_by.staff_position is not None else ""
                    #     expense_map["last_updated_by"] = creator_map
                    #     # expense approved
                    #     creator_map = {}
                    #     creator_map["staff_id"] = str(
                    #         expense.last_updated_by.id) if expense.expense_approved_by is not None else ""
                    #     creator_map["staff_name"] = f'{expense.expense_approved_by.first_name} {expense.expense_approved_by.last_name}' if expense.expense_approved_by is not None else ""
                    #     creator_map["staff_position"] = expense.expense_approved_by.staff_position.position_title if expense.expense_approved_by.staff_position is not None else ""
                    #     expense_map["expense_approved_by"] = creator_map
                    #     #
                    #     expense_map["created_on"] = datetime.strftime(
                    #         expense.created_on.astimezone(target_timezone), date_format) if expense.created_on is not None else ""
                    #     expense_map["last_updated_on"] = datetime.strftime(
                    #         expense.last_updated_on.astimezone(target_timezone), date_format) if expense.last_updated_on is not None else ""
                    #     expense_list.append(expense_map)

                    # all_deposits = branch.branch_deposits.all().order_by("-id")
                    # for deposit in all_deposits:
                    #     deposit_map = {}
                    #     deposit_map["deposit_id"] = str(deposit.id)
                    #     deposit_map["deposit_number"] = deposit.deposit_number
                    #     deposit_map["deposit_source"] = deposit.deposit_source
                    #     deposit_map["deposit_amount"] = deposit.deposit_amount
                    #     deposit_map["order_payment_reference"] = deposit.order_payment_reference
                    #     creator_map = {}
                    #     creator_map["staff_id"] = str(
                    #         deposit.created_by.id) if deposit.created_by is not None else ""
                    #     creator_map["staff_name"] = f'{deposit.created_by.first_name} {deposit.created_by.last_name}' if deposit.created_by is not None else ""
                    #     creator_map["staff_position"] = deposit.created_by.staff_position.position_title if deposit.created_by.staff_position is not None else ""
                    #     deposit_map["created_by"] = creator_map
                    #     creator_map = {}
                    #     creator_map["staff_id"] = str(
                    #         deposit.last_updated_by.id) if deposit.last_updated_by is not None else ""
                    #     creator_map["staff_name"] = f'{deposit.last_updated_by.first_name} {deposit.last_updated_by.last_name}' if deposit.last_updated_by is not None else ""
                    #     creator_map["staff_position"] = deposit.last_updated_by.staff_position.position_title if deposit.last_updated_by.staff_position is not None else ""
                    #     deposit_map["last_updated_by"] = creator_map
                    #     deposit_map["created_on"] = datetime.strftime(
                    #         deposit.created_on.astimezone(target_timezone), date_format) if deposit.created_on is not None else ""
                    #     deposit_map["last_updated_on"] = datetime.strftime(
                    #         deposit.last_updated_on.astimezone(target_timezone), date_format) if deposit.last_updated_on is not None else ""
                    #     deposit_list.append(deposit_map)
                    company_branch_map["deposit_list"] = deposit_list
                    company_branch_map["expense_list"] = expense_list
                    company_branch_map["chart_of_account_list"] = chart_of_account_list
                    company_branches_list.append(company_branch_map)
            company_profile_map["company_branches_list"] = company_branches_list
            payload["company_profile"] = company_profile_map
            payload["active_staff_profile_data"] = active_staff_profile_data
            return Response({"message": "true", "payload": payload}, status=200)
        else:
            return Response({"message": "false", "payload": payload}, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "false", "payload": payload}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def finance_purchase_orders(request):
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    current_date = datetime.now().date()
    company_serial_number = request.data["serial_number"]
    active_user = request.user
    payload = {}
    company_profile_map = {}
    company_branches_list = []
    company_branch_map = {}
    supplier_list = []
    landed_costs_list = []
    purchase_order_list = []
    purchase_order_product_instances_list = []
    purchase_order_product_instance_map = {}
    category_list = []
    try:
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.dashboard.view"):
            active_staff_profile_data = get_staff_profile_data(active_user)
            company_profile_map["company_id"] = str(company_profile.id)
            company_profile_map["company_name"] = company_profile.company_name
            company_profile_map["company_phone"] = company_profile.company_phone
            company_profile_map["preferred_currency"] = company_profile.company_preferred_currency
            company_profile_map["company_postal_address"] = company_profile.company_postal_address
            # company_loan_portfolio = company_profile.company_loan_portfolio.all().order_by("-id")
            all_suppliers = Supplier.objects.all().order_by("-id")
            # all_branches = company_profile.company_branches.all().order_by("-id")
            all_categories = Category.objects.all().order_by("-id")
            company_purchase_orders = company_profile.company_purchase_orders.filter(
                recycle_bin=False).order_by("-id")
            all_landed_costs = LandedCost.objects.filter(
                recycle_bin=False, company_profile=company_profile).order_by("-id")
            for category in all_categories:
                if category.recycle_bin != True:
                    category_map = {}
                    product_list = []
                    category_map["category_id"] = str(category.id)
                    category_map["category_name"] = category.category_name
                    category_map["category_description"] = category.category_description
                    category_products = category.category_products.all().order_by("-id")
                    for product in category_products:
                        if product.recycle_bin != True:
                            product_map = {}
                            product_image_catalogues_list = []
                            product_features_catalogues_list = []
                            product_components_list = []
                            product_brands_list = []
                            product_pricing_map = {}  # 0netoone
                            product_discount_map = {}  # onetoone
                            product_vat_map = {}  # onetoone
                            product_map["product_id"] = str(product.id)
                            product_map["product_name"] = product.product_name
                            product_map["stock_keeping_unit"] = product.stock_keeping_unit
                            product_map["unit_of_measurement"] = product.unit_of_measurement
                            product_map["product_description"] = product.product_description
                            # attaching product specific details
                            # attaching product images
                            # attach product features and attributes
                            # attach product pricing
                            try:
                                product_pricing = ProductPricing.objects.get(
                                    product=product)
                                product_pricing_map["product_pricing_id"] = str(
                                    product_pricing.id)
                                product_pricing_map["product_net_price"] = product_pricing.product_net_price
                            except:
                                product_pricing_map["product_pricing_id"] = ""
                                product_pricing_map["product_net_price"] = ""
                            product_map["product_pricing_map"] = product_pricing_map
                            # attach product discount
                            try:
                                product_discount = ProductDiscount.objects.get(
                                    product=product)
                                product_discount_map["product_discount_id"] = str(
                                    product_discount.id)
                                product_discount_map["discount_type"] = product_discount.discount_type
                                product_discount_map["discount_value"] = product_discount.discount_value
                            except:
                                product_discount_map["product_discount_id"] = ""
                                product_discount_map["discount_type"] = ""
                                product_discount_map["discount_value"] = ""
                            product_map["product_discount_map"] = product_discount_map
                            # attach product vat
                            try:
                                product_vat = ProductVAT.objects.get(
                                    product=product)
                                product_vat_map["product_vat_id"] = str(
                                    product_vat.id)
                                product_vat_map["vat_percentage_value"] = product_vat.vat_percentage_value
                            except:
                                product_vat_map["product_vat_id"] = ""
                                product_vat_map["vat_percentage_value"] = ""
                            product_map["product_vat_map"] = product_vat_map
                            product_list.append(product_map)
                    category_map["product_list"] = product_list
                    category_list.append(category_map)
            for landed_cost in all_landed_costs:
                landed_cost_instances_list = []
                landed_cost_map = {}
                landed_cost_map["landed_cost_id"] = str(landed_cost.id)
                landed_cost_map["name_of_expense"] = landed_cost.name_of_expense
                landed_cost_map["description_of_calculation"] = landed_cost.description_of_calculation
                creator_map = {}
                creator_map["staff_id"] = str(
                    landed_cost.created_by.id) if landed_cost.created_by is not None else ""
                creator_map["staff_name"] = f'{landed_cost.created_by.first_name} {landed_cost.created_by.last_name}' if landed_cost.created_by is not None else ""
                creator_map["staff_position"] = landed_cost.created_by.staff_position.position_title if landed_cost.created_by is not None else ""
                landed_cost_map["created_by"] = creator_map
                creator_map = {}
                creator_map["staff_id"] = str(
                    landed_cost.last_updated_by.id) if landed_cost.last_updated_by is not None else ""
                creator_map["staff_name"] = f'{landed_cost.last_updated_by.first_name} {landed_cost.last_updated_by.last_name}' if landed_cost.last_updated_by is not None else ""
                creator_map["staff_position"] = landed_cost.last_updated_by.staff_position.position_title if landed_cost.last_updated_by is not None else ""
                landed_cost_map["last_updated_by"] = creator_map
                landed_cost_map["created_on"] = datetime.strftime(
                    landed_cost.created_on.astimezone(target_timezone), date_format) if landed_cost.created_on is not None else ""
                landed_cost_map["last_updated_on"] = datetime.strftime(
                    landed_cost.last_updated_on.astimezone(target_timezone), date_format) if landed_cost.last_updated_on is not None else ""
                landed_cost_instances = landed_cost.landed_cost_instances.all().order_by("-id")
                for landed_cost_instance in landed_cost_instances:
                    landed_cost_instance_map = {}
                    landed_cost_instance_map["landed_cost_id"] = str(
                        landed_cost.id)
                    landed_cost_instance_map["landed_cost_instance_id"] = str(
                        landed_cost_instance.id)
                    landed_cost_instance_map["cost_value"] = landed_cost_instance.cost_value
                    landed_cost_instance_map["exchange_rate"] = landed_cost_instance.exchange_rate
                    landed_cost_instance_map["cost_currency"] = landed_cost_instance.cost_currency
                    landed_cost_instance_map["cost_amount_paid"] = landed_cost_instance.cost_amount_paid
                    landed_cost_instance_map["cost_amount_due"] = landed_cost_instance.cost_amount_due
                    landed_cost_instance_map["cost_payment_settled"] = "true" if landed_cost_instance.cost_payment_settled == True else "false"
                    landed_cost_instances_list.append(landed_cost_instance_map)
                landed_cost_map["landed_cost_instances_list"] = landed_cost_instances_list
                landed_costs_list.append(landed_cost_map)
            company_profile_map["landed_costs_list"] = landed_costs_list
            for purchase_order in company_purchase_orders:
                product_purchase_instances_list = []
                purchase_order_map = {}
                purchase_order_map["purchase_order_id"] = str(
                    purchase_order.id)
                purchase_order_map["purchase_order_number"] = purchase_order.purchase_order_number
                purchase_order_map["currency"] = company_profile.company_preferred_currency
                purchase_order_map["purchase_value_overall"] = purchase_order.purchase_value_overall
                purchase_order_map["purchase_order_approved"] = "true" if purchase_order.purchase_order_approved == True else "false"
                purchase_order_map["purchase_order_landed_costs_overall"] = purchase_order.purchase_order_landed_costs_overall
                purchase_order_map["created_on"] = datetime.strftime(
                    purchase_order.created_on.astimezone(target_timezone), date_format) if purchase_order.created_on is not None else ""
                purchase_order_map["last_updated_on"] = datetime.strftime(
                    purchase_order.last_updated_on.astimezone(target_timezone), date_format) if purchase_order.last_updated_on is not None else ""
                creator_map = {}
                creator_map["staff_id"] = str(
                    purchase_order.created_by.id) if purchase_order.created_by is not None else ""
                creator_map["staff_name"] = f'{purchase_order.created_by.first_name} {purchase_order.created_by.last_name}' if purchase_order.created_by is not None else ""
                creator_map["staff_position"] = purchase_order.created_by.staff_position.position_title if purchase_order.created_by is not None else ""
                purchase_order_map["created_by"] = creator_map
                creator_map = {}
                creator_map["staff_id"] = str(
                    purchase_order.last_updated_by.id) if purchase_order.last_updated_by is not None else ""
                creator_map["staff_name"] = f'{purchase_order.last_updated_by.first_name} {purchase_order.last_updated_by.last_name}' if purchase_order.last_updated_by is not None else ""
                creator_map["staff_position"] = purchase_order.last_updated_by.staff_position.position_title if purchase_order.last_updated_by is not None else ""
                purchase_order_map["last_updated_by"] = creator_map
                #
                creator_map = {}
                creator_map["staff_id"] = str(
                    purchase_order.purchase_order_approved_by.id) if purchase_order.purchase_order_approved_by is not None else ""
                creator_map["staff_name"] = f'{purchase_order.purchase_order_approved_by.first_name} {purchase_order.purchase_order_approved_by.last_name}' if purchase_order.purchase_order_approved_by is not None else ""
                creator_map["staff_position"] = purchase_order.purchase_order_approved_by.staff_position.position_title if purchase_order.purchase_order_approved_by is not None else ""
                purchase_order_map["purchase_order_approved_by"] = creator_map
                purchase_order_product_instances = purchase_order.purchase_order_product_instances.filter(
                    recycle_bin=False).order_by("-id")
                # print(len(purchase_order_product_instances))
                for product_purchase_instance in purchase_order_product_instances:
                    purchase_order_product_instance_map = {}
                    # print(product_purchase_instance.id)
                    landed_cost_product_purchase_instances_list = []
                    purchase_order_product_instance_map["product_purchase_instance_id"] = str(
                        product_purchase_instance.id)
                    purchase_order_product_instance_map["product_id"] = str(
                        product_purchase_instance.purchase_product.id) if product_purchase_instance.purchase_product is not None else ""
                    purchase_order_product_instance_map["purchase_order_number"] = purchase_order.purchase_order_number
                    purchase_order_product_instance_map["supplier_id"] = str(
                        product_purchase_instance.supplier.id) if product_purchase_instance.supplier is not None else ""
                    purchase_order_product_instance_map[
                        "purchase_value_per_unit"] = product_purchase_instance.purchase_value_per_unit
                    purchase_order_product_instance_map[
                        "cost_currency"] = product_purchase_instance.cost_currency
                    purchase_order_product_instance_map[
                        "exchange_rate"] = product_purchase_instance.exchange_rate
                    purchase_order_product_instance_map[
                        "purchase_value_overall"] = product_purchase_instance.purchase_value_overall
                    purchase_order_product_instance_map[
                        "purchase_amount_paid_to_supplier"] = product_purchase_instance.purchase_amount_paid_to_supplier
                    purchase_order_product_instance_map[
                        "supplier_payment_settled"] = "true" if product_purchase_instance.supplier_payment_settled == True else "false"
                    # purchase_order_product_instance_map[
                    #     "supplier_payment_settled"] = "true" if product_purchase_instance.supplier_payment_settled == True else "false"
                    purchase_order_product_instance_map[
                        "product_purchase_delivered"] = "true" if product_purchase_instance.product_purchase_delivered == True else "false"
                    purchase_order_product_instance_map[
                        "quantity_purchased"] = product_purchase_instance.quantity_purchased
                    purchase_order_product_instance_map[
                        "quantity_delivered"] = product_purchase_instance.quantity_delivered
                    # purchase_order_product_instance_map[
                    #     "quantity_delivered"] = product_purchase_instance.quantity_delivered
                    purchase_order_product_instance_map["created_on"] = datetime.strftime(
                        purchase_order.created_on, date_format) if product_purchase_instance.created_on is not None else ""
                    purchase_order_product_instance_map["last_updated_on"] = datetime.strftime(
                        product_purchase_instance.last_updated_on, date_format) if product_purchase_instance.last_updated_on is not None else ""
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        product_purchase_instance.created_by.id) if product_purchase_instance.created_by is not None else ""
                    creator_map["staff_name"] = f'{product_purchase_instance.created_by.first_name} {product_purchase_instance.created_by.last_name}' if product_purchase_instance.created_by is not None else ""
                    creator_map["staff_position"] = product_purchase_instance.created_by.staff_position.position_title if product_purchase_instance.created_by is not None else ""
                    purchase_order_product_instance_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        product_purchase_instance.last_updated_by.id) if product_purchase_instance.last_updated_by is not None else ""
                    creator_map["staff_name"] = f'{product_purchase_instance.last_updated_by.first_name} {product_purchase_instance.last_updated_by.last_name}' if product_purchase_instance.last_updated_by is not None else ""
                    creator_map["staff_position"] = product_purchase_instance.last_updated_by.staff_position.position_title if product_purchase_instance.last_updated_by is not None else ""
                    purchase_order_product_instance_map["last_updated_by"] = creator_map
                    landed_cost_product_purchase_instances = product_purchase_instance.landed_cost_product_purchase_instances.all().order_by("-id")
                    for landed_cost_instance in landed_cost_product_purchase_instances:
                        # print(landed_cost_instance)
                        landed_cost_instance_map = {}
                        landed_cost_instance_map["landed_cost_id"] = str(
                            landed_cost_instance.landed_cost.id) if landed_cost_instance.landed_cost is not None else ""
                        landed_cost_instance_map["landed_cost_instance_id"] = str(
                            landed_cost_instance.id)
                        landed_cost_instance_map["cost_value"] = landed_cost_instance.cost_value
                        landed_cost_instance_map["exchange_rate"] = landed_cost_instance.exchange_rate
                        landed_cost_instance_map["cost_currency"] = landed_cost_instance.cost_currency
                        landed_cost_instance_map["cost_amount_paid"] = landed_cost_instance.cost_amount_paid
                        landed_cost_instance_map["cost_amount_due"] = landed_cost_instance.cost_amount_due
                        landed_cost_instance_map["cost_payment_settled"] = "true" if landed_cost_instance.cost_payment_settled == True else "false"
                        # print(landed_cost_instance_map)
                        landed_cost_product_purchase_instances_list.append(
                            landed_cost_instance_map)
                    purchase_order_product_instance_map[
                        "landed_cost_product_purchase_instances_list"] = landed_cost_product_purchase_instances_list
                    purchase_order_product_instances_list.append(
                        purchase_order_product_instance_map)
                    # print(landed_cost_product_purchase_instances_list)
                    landed_cost_product_purchase_instances_list = []
                # print(len(purchase_order_product_instances_list))
                purchase_order_map["purchase_order_product_instances_list"] = purchase_order_product_instances_list
                # print(
                #     purchase_order_map["purchase_order_product_instances_list"])
                purchase_order_product_instances_list = []
                purchase_order_list.append(purchase_order_map)
            company_profile_map["purchase_order_list"] = purchase_order_list
            for supplier in all_suppliers:
                if supplier.recycle_bin != True:
                    supplier_map = {}
                    supplied_products_list = []
                    supplier_map["supplier_id"] = str(supplier.id)
                    supplier_map["preferred_currency"] = company_profile.company_preferred_currency
                    supplier_map["supplier_name"] = supplier.supplier_name
                    supplier_map["supplier_phone"] = supplier.supplier_phone
                    supplier_map["supplier_email"] = supplier.supplier_email
                    supplier_map["supplier_address"] = supplier.supplier_address
                    supplier_map["supplier_description"] = supplier.supplier_description
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        supplier.created_by.id) if supplier.created_by is not None else ""
                    creator_map["staff_name"] = f'{supplier.created_by.first_name} {supplier.created_by.last_name}' if supplier.created_by is not None else ""
                    creator_map["staff_position"] = supplier.created_by.staff_position.position_title if supplier.created_by is not None else ""
                    supplier_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        supplier.last_updated_by.id) if supplier.last_updated_by is not None else ""
                    creator_map["staff_name"] = f'{supplier.last_updated_by.first_name} {supplier.last_updated_by.last_name}' if supplier.last_updated_by is not None else ""
                    creator_map["staff_position"] = supplier.last_updated_by.staff_position.position_title if supplier.last_updated_by is not None else ""
                    supplier_map["last_updated_by"] = creator_map
                    supplier_map["created_on"] = datetime.strftime(
                        supplier.created_on.astimezone(target_timezone), date_format) if supplier.created_on is not None else ""
                    supplier_map["last_updated_on"] = datetime.strftime(
                        supplier.last_updated_on.astimezone(target_timezone), date_format) if supplier.last_updated_on is not None else ""
                    # supplied products
                    supplied_products = supplier.supplied_products.all()
                    for supplied_product in supplied_products:
                        supplied_product_map = {}
                        supplied_product_map["product_id"] = str(
                            supplied_product.id)
                        supplied_product_map["product_name"] = supplied_product.product_name
                        supplied_products_list.append(supplied_product_map)
                    supplier_map["supplied_products_list"] = supplied_products_list
                    # supllier payment details
                    supplier_payment_details = supplier.supplier_payment_details.all().order_by("-id")
                    supplier_payment_details_list = []
                    for supplier_payment_detail in supplier_payment_details:
                        supplier_payment_detail_map = {}
                        supplier_payment_detail_map["supplier_payment_detail_id"] = str(
                            supplier_payment_detail.id)
                        supplier_payment_detail_map["bank_institution_name"] = supplier_payment_detail.banking_institution_name
                        supplier_payment_detail_map["bank_account_name"] = supplier_payment_detail.bank_account_name
                        supplier_payment_detail_map["bank_account_number"] = supplier_payment_detail.bank_account_number
                        supplier_payment_detail_map["bank_branch_name"] = supplier_payment_detail.bank_branch_name
                        supplier_payment_detail_map["bank_branch_code"] = supplier_payment_detail.bank_branch_code
                        supplier_payment_detail_map["bank_swift_code"] = supplier_payment_detail.bank_swift_code
                        supplier_payment_detail_map["created_on"] = datetime.strftime(
                            supplier_payment_detail.created_on.astimezone(target_timezone), date_format) if supplier_payment_detail.created_on is not None else ""
                        supplier_payment_detail_map["last_updated_on"] = datetime.strftime(
                            supplier_payment_detail.last_updated_on.astimezone(target_timezone), date_format) if supplier_payment_detail.last_updated_on is not None else ""
                        supplier_payment_details_list.append(
                            supplier_payment_detail_map)
                    supplier_map["supplier_payment_details_list"] = supplier_payment_details_list
                    supplier_product_purchase_instances = supplier.supplier_product_purchase_instances.all().order_by("-id")
                    supplied_product_history_list = []
                    for supplied_product in supplier_product_purchase_instances:
                        if supplied_product.recycle_bin != True:
                            supplied_product_map = {}
                            supplied_product_map["purchase_order_number"] = supplied_product.purchase_order.purchase_order_number if supplied_product.purchase_order is not None else ""
                            # try:
                            #     supplied_product_map["purchase_requisition_number"] = supplied_product.purchase_requisition_instance.purchase_requisition.purchase_requisition_number
                            # except:
                            #     supplied_product_map["purchase_requisition_number"] = "Deleted"
                            supplied_product_map["quantity_delivered"] = supplied_product.quantity_delivered
                            supplied_product_map["purchase_value_per_unit"] = supplied_product.purchase_value_per_unit
                            supplied_product_map["purchase_value_overall"] = supplied_product.purchase_value_overall
                            supplied_product_map["purchase_amount_paid_to_supplier"] = supplied_product.purchase_amount_paid_to_supplier
                            supplied_product_map["supplier_payment_settled"] = "true" if supplied_product.supplier_payment_settled == True else "false"
                            supplied_product_map["product_purchase_delivered"] = "true" if supplied_product.product_purchase_delivered == True else "false"
                            try:
                                supplied_product_map["product_name"] = supplied_product.purchase_requisition_instance.product.product_name
                            except:
                                supplied_product_map["product_name"] = "Deleted product"
                            supplied_product_history_list.append(
                                supplied_product_map)
                    supplier_map["supplied_product_history_list"] = supplied_product_history_list
                    supplier_list.append(supplier_map)
            payload["company_profile"] = company_profile_map
            payload["active_staff_profile_data"] = active_staff_profile_data
            payload["supplier_list"] = supplier_list
            payload["category_list"] = category_list
            return Response({"message": "true", "payload": payload}, status=200)
        else:
            return Response({"message": "false", "payload": payload}, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "false", "payload": payload}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def finance_payroll_sheet(request):
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    company_serial_number = request.data["serial_number"]
    active_user = request.user
    payload = {}
    company_profile_map = {}
    payroll_sheets_list = []
    try:
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.payroll_finance.view"):
            active_staff_profile_data = get_staff_profile_data(active_user)
            company_profile_map["company_id"] = str(company_profile.id)
            company_profile_map["company_name"] = company_profile.company_name
            company_profile_map["company_phone"] = company_profile.company_phone
            company_profile_map["preferred_currency"] = company_profile.company_preferred_currency
            company_profile_map["company_postal_address"] = company_profile.company_postal_address
            all_payroll_sheets = PayrollSheet.objects.filter(
                recycle_bin=False).order_by("-id")
            for payroll_sheet in all_payroll_sheets:
                payroll_sheet_map = {}
                payroll_sheet_map["payroll_sheet_id"] = str(
                    payroll_sheet.id)
                payroll_sheet_map["payroll_sheet_title"] = payroll_sheet.payroll_sheet_title
                payroll_sheet_map["payroll_sheet_number"] = payroll_sheet.payroll_sheet_number
                payroll_sheet_map["payroll_sheet_description"] = payroll_sheet.payroll_sheet_description
                payroll_sheet_map["payroll_sheet_for_the_month_of"] = payroll_sheet.payroll_sheet_for_the_month_of
                payroll_sheet_map["payroll_sheet_for_the_year"] = payroll_sheet.payroll_sheet_for_the_year
                payroll_sheet_map["payroll_sheet_value"] = payroll_sheet.payroll_sheet_value
                # added
                payroll_sheet_map["payroll_sheet_total_net_pay_value"] = payroll_sheet.payroll_sheet_total_net_pay_value
                payroll_sheet_map["payroll_sheet_total_bonus_value"] = payroll_sheet.payroll_sheet_total_bonus_value
                payroll_sheet_map["payroll_sheet_total_deduction_value"] = payroll_sheet.payroll_sheet_total_deduction_value
                payroll_sheet_map["payroll_sheet_total_commission_value"] = payroll_sheet.payroll_sheet_total_commission_value
                payroll_sheet_map["payroll_sheet_approved_by_system_administrator"] = "true" if payroll_sheet.payroll_sheet_approved_by_system_administrator == True else "false"
                payroll_sheet_map["is_terminal_dues"] = "true" if payroll_sheet.is_terminal_dues == True else "false"
                payroll_sheet_map["currency"] = company_profile.company_preferred_currency
                # end added
                payroll_sheet_map["payroll_sheet_approved_by_finance"] = "true" if payroll_sheet.payroll_sheet_approved_by_finance == True else "false"
                payroll_sheet_map["payroll_sheet_payment_settled"] = "true" if payroll_sheet.payroll_sheet_payment_settled == True else "false"
                staff_map = {}
                staff_map["staff_id"] = str(
                    payroll_sheet.created_by.id) if payroll_sheet.created_by is not None else ""
                staff_map["staff_name"] = f'{payroll_sheet.created_by.first_name} {payroll_sheet.created_by.last_name}' if payroll_sheet.created_by is not None else ""
                staff_map["staff_position"] = payroll_sheet.created_by.staff_position.position_title if payroll_sheet.created_by.staff_position is not None else ""
                payroll_sheet_map["created_by"] = staff_map
                staff_map = {}
                staff_map["staff_id"] = str(
                    payroll_sheet.last_updated_by.id) if payroll_sheet.last_updated_by is not None else ""
                staff_map["staff_name"] = f'{payroll_sheet.last_updated_by.first_name} {payroll_sheet.last_updated_by.last_name}' if payroll_sheet.last_updated_by is not None else ""
                staff_map["staff_position"] = payroll_sheet.last_updated_by.staff_position.position_title if payroll_sheet.last_updated_by.staff_position is not None else ""
                payroll_sheet_map["last_updated_by"] = staff_map
                payroll_sheet_map["created_on"] = datetime.strftime(
                    payroll_sheet.created_on.astimezone(target_timezone), date_format) if payroll_sheet.created_on is not None else ""
                payroll_sheet_map["last_updated_on"] = datetime.strftime(
                    payroll_sheet.last_updated_on.astimezone(target_timezone), date_format) if payroll_sheet.last_updated_on is not None else ""
                payroll_instances_list = []
                payroll_instances = payroll_sheet.staff_payroll_items.all().order_by('-id')
                for payroll_instance in payroll_instances:
                    if payroll_instance.recycle_bin == False:
                        payroll_instance_map = {}
                        payroll_instance_map["payroll_instance_id"] = str(
                            payroll_instance.id)
                        payroll_instance_map["staff_id"] = str(
                            payroll_instance.staff_profile.id)
                        payroll_instance_map["staff_number"] = payroll_instance.staff_profile.staff_number
                        payroll_instance_map["first_name"] = payroll_instance.staff_profile.first_name
                        payroll_instance_map["last_name"] = payroll_instance.staff_profile.last_name
                        payroll_instance_map["email_address"] = payroll_instance.staff_profile.email_address
                        payroll_instance_map["identification_number"] = payroll_instance.staff_profile.identification_number
                        payroll_instance_map["phone_number"] = payroll_instance.staff_profile.phone_number
                        payroll_instance_map["kra_pin"] = payroll_instance.staff_profile.kra_pin
                        payroll_instance_map["type_of_employment"] = payroll_instance.staff_profile.type_of_employment
                        payroll_instance_map["banking_institution_name"] = payroll_instance.staff_profile.banking_institution_name
                        payroll_instance_map["bank_account_name"] = payroll_instance.staff_profile.bank_account_name
                        payroll_instance_map["bank_account_number"] = payroll_instance.staff_profile.bank_account_number
                        payroll_instance_map["bank_branch_name"] = payroll_instance.staff_profile.bank_branch_name
                        payroll_instance_map["bank_branch_code"] = payroll_instance.staff_profile.bank_branch_code
                        payroll_instance_map["bank_swift_code"] = payroll_instance.staff_profile.bank_swift_code
                        payroll_instance_map["basic_salary"] = payroll_instance.staff_profile.basic_salary
                        payroll_instance_map["personal_email"] = payroll_instance.staff_profile.personal_email
                        payroll_instance_map["nhif_number"] = payroll_instance.staff_profile.nhif_number
                        payroll_instance_map["nssf_number"] = payroll_instance.staff_profile.nssf_number
                        payroll_instance_map["staff_position"] = payroll_instance.staff_profile.staff_position.position_title
                        payroll_instance_map["employment_start_date"] = payroll_instance.staff_profile.employment_start_date
                        payroll_instance_map["company_department"] = payroll_instance.staff_profile.company_department.department_name
                        deduction_instances = payroll_instance.deduction_instance.all().order_by('-id')
                        deduction_instances_list = []
                        for deduction_instance in deduction_instances:
                            if deduction_instance.recycle_bin == False:
                                deduction_instance_map = {}
                                deduction_instance_map["deduction_instance_id"] = str(
                                    deduction_instance.id)
                                deduction_instance_map["deduction_id"] = str(
                                    deduction_instance.deduction.id) if deduction_instance.deduction is not None else ""
                                deduction_instance_map["deduction_title"] = deduction_instance.deduction.deduction_title
                                deduction_instance_map["deduction_instance_value"] = deduction_instance.deduction_instance_value

                                deduction_instances_list.append(
                                    deduction_instance_map)
                        payroll_instance_map["deduction_instances_list"] = deduction_instances_list
                        payroll_instance_map["gross_salary"] = payroll_instance.gross_salary
                        bonus_instances = payroll_instance.bonus_instance.all().order_by('-id')
                        bonus_instances_list = []
                        for bonus_instance in bonus_instances:
                            if bonus_instance.recycle_bin == False:
                                bonus_instance_map = {}
                                bonus_instance_map["bonus_instance_id"] = str(
                                    bonus_instance.id)
                                bonus_instance_map["bonus_id"] = str(
                                    bonus_instance.bonus.id) if bonus_instance.bonus is not None else ""
                                bonus_instance_map["bonus_instance_value"] = bonus_instance.bonus_instance_value
                                bonus_instance_map["bonus_title"] = bonus_instance.bonus.bonus_title

                                bonus_instances_list.append(
                                    bonus_instance_map)
                        payroll_instance_map["bonus_instances_list"] = bonus_instances_list
                        payroll_instance_map["net_salary"] = payroll_instance.net_salary
                        #
                        payroll_instance_commissions = payroll_instance.staff_payroll_instance_commissions.all()
                        payroll_instance_commissions_list = []
                        for commission_sheet_instance in payroll_instance_commissions:
                            if commission_sheet_instance.recycle_bin == False:
                                commission_sheet_instance_map = {}
                                commission_sheet_instance_map["commission_sheet_instance_id"] = str(
                                    commission_sheet_instance.id)
                                commission_sheet_instance_map["customer_order_id"] = str(
                                    commission_sheet_instance.customer_order.id) if commission_sheet_instance.customer_order is not None else ""
                                commission_sheet_instance_map[
                                    "commission_value"] = commission_sheet_instance.commission_value
                                commission_sheet_instance_map[
                                    "commission_sheet_id"] = str(commission_sheet_instance.commission_sheet.id) if commission_sheet_instance.commission_sheet is not None else ""
                                commission_sheet_instance_map[
                                    "commission_sheet_number"] = commission_sheet_instance.commission_sheet.commission_sheet_number if commission_sheet_instance.commission_sheet is not None else ""
                                commission_sheet_instance_map[
                                    "commission_sheet_title"] = commission_sheet_instance.commission_sheet.commission_sheet_title if commission_sheet_instance.commission_sheet is not None else ""
                                payroll_instance_commissions_list.append(
                                    commission_sheet_instance_map)
                        payroll_instance_map["payroll_instance_commissions_list"] = payroll_instance_commissions_list
                        payroll_instance_map["commissions_total"] = payroll_instance.commissions_total
                        payroll_instance_map["is_prorated"] = "true" if payroll_instance.is_prorated == True else "false"
                        payroll_instance_map["pro_rate_factor"] = payroll_instance.pro_rate_factor
                        #
                        staff_map = {}
                        staff_map["staff_id"] = str(
                            payroll_instance.created_by.id) if payroll_instance.created_by is not None else ""
                        staff_map["staff_name"] = f'{payroll_instance.created_by.first_name} {payroll_instance.created_by.last_name}' if payroll_instance.created_by is not None else ""
                        staff_map["staff_position"] = payroll_instance.created_by.staff_position.position_title if payroll_instance.created_by.staff_position is not None else ""
                        payroll_instance_map["created_by"] = staff_map
                        staff_map = {}
                        staff_map["staff_id"] = str(
                            payroll_instance.last_updated_by.id) if payroll_instance.last_updated_by is not None else ""
                        staff_map["staff_name"] = f'{payroll_instance.last_updated_by.first_name} {payroll_instance.last_updated_by.last_name}' if payroll_instance.last_updated_by is not None else ""
                        staff_map["staff_position"] = payroll_instance.last_updated_by.staff_position.position_title if payroll_instance.last_updated_by.staff_position is not None else ""
                        payroll_instance_map["last_updated_by"] = staff_map
                        payroll_instance_map["created_on"] = datetime.strftime(
                            payroll_instance.created_on.astimezone(target_timezone), date_format) if payroll_instance.created_on is not None else ""
                        payroll_instance_map["last_updated_on"] = datetime.strftime(
                            payroll_instance.last_updated_on.astimezone(target_timezone), date_format) if payroll_instance.last_updated_on is not None else ""
                        payroll_instances_list.append(
                            payroll_instance_map)
                # print(payroll_instances_list)
                # payroll_sheet_map["payroll_instances_list"] = payroll_instances_list
                # payroll_sheets_list.append(payroll_sheet_map)
                payroll_sheet_map["payroll_instances_list"] = payroll_instances_list
                payroll_sheets_list.append(payroll_sheet_map)
            company_profile_map["payroll_sheets_list"] = payroll_sheets_list
            payload["active_staff_profile_data"] = active_staff_profile_data
            payload["company_profile"] = company_profile_map
            return Response({"message": "true", "payload": payload}, status=200)
        else:
            return Response({"message": "false", "payload": payload}, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "false", "payload": payload}, status=500)


# @api_view(['POST'])
# @authentication_classes([TokenAuthentication])
# @permission_classes([IsAuthenticated])
# def finance_payroll_sheet(request):
#     target_timezone = pytz.timezone('Africa/Nairobi')
#     date_format = '%d/%m/%Y, %H:%M'
#     company_serial_number = request.data["serial_number"]
#     active_user = request.user
#     payload = {}
#     company_profile_map = {}
#     company_branches_list = []
#     company_branch_map = {}
#     deductions_list = []
#     staff_positions_list = []
#     company_departments_list = []
#     try:
#         company_profile = CompanyProfile.objects.get(
#             company_serial_number=company_serial_number)
#         staff_profile = StaffProfile.objects.get(user=active_user)
#         if staff_profile.company_department.department_name == "finance_and_accounting" and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
#             active_staff_profile_data = get_staff_profile_data(active_user)
#             company_profile_map["company_id"] = str(company_profile.id)
#             company_profile_map["company_name"] = company_profile.company_name
#             company_profile_map["company_phone"] = company_profile.company_phone
#             company_profile_map["preferred_currency"] = company_profile.company_preferred_currency
#             company_profile_map["company_postal_address"] = company_profile.company_postal_address
#             #
#             company_departments = company_profile.company_departments.all().order_by('-id')
#             all_branches = company_profile.company_branches.all().order_by("-id")
#             for department in company_departments:
#                 if department.recycle_bin == False:
#                     department_map = {}
#                     department_map["department_id"] = str(department.id)
#                     department_map["department_name"] = department.department_name
#                     department_map["department_description"] = department.department_description
#                     department_map["created_on"] = datetime.strftime(
#                         department.created_on.astimezone(target_timezone), date_format)
#                     department_map["last_updated_on"] = datetime.strftime(
#                         department.last_updated_on.astimezone(target_timezone), date_format)
#                     company_departments_list.append(department_map)
#             #
#             staff_positions = company_profile.company_staff_positions.all().order_by('-id')
#             for position in staff_positions:
#                 if position.recycle_bin == False:
#                     staff_position_map = {}
#                     staff_position_map["staff_position_id"] = str(position.id)
#                     staff_position_map["position_title"] = position.position_title
#                     staff_position_map["position_description"] = position.position_description
#                     staff_position_map["salary"] = position.salary
#                     staff_position_map["created_on"] = datetime.strftime(
#                         position.created_on.astimezone(target_timezone), date_format) if position.created_on is not None else ""
#                     staff_position_map["last_updated_on"] = datetime.strftime(
#                         position.last_updated_on.astimezone(target_timezone), date_format) if position.last_updated_on is not None else ""
#                     staff_positions_list.append(staff_position_map)
#             deductions = company_profile.company_deductions.all().order_by('-id')
#             for deduction in deductions:
#                 if deduction.recycle_bin == False:
#                     deduction_map = {}
#                     deduction_map["deduction_id"] = str(deduction.id)
#                     deduction_map["deduction_title"] = deduction.deduction_title
#                     deduction_map["deduction_description"] = deduction.deduction_description
#                     deduction_map["deduction_type"] = deduction.deduction_type
#                     deduction_map["deduction_module"] = deduction.deduction_module
#                     deduction_map["deduction_value"] = deduction.deduction_value
#                     deduction_map["date_effective_from"] = deduction.date_effective_from
#                     deduction_map["date_effective_to"] = deduction.date_effective_to
#                     staff_map = {}
#                     staff_map["staff_id"] = str(
#                         deduction.created_by.id) if deduction.created_by is not None else ""
#                     staff_map["staff_name"] = f'{deduction.created_by.first_name} {deduction.created_by.last_name}' if deduction.created_by is not None else ""
#                     staff_map["staff_position"] = deduction.created_by.staff_position.position_title if deduction.created_by.staff_position is not None else ""
#                     deduction_map["created_by"] = staff_map
#                     staff_map = {}
#                     staff_map["staff_id"] = str(
#                         deduction.last_updated_by.id) if deduction.last_updated_by is not None else ""
#                     staff_map["staff_name"] = f'{deduction.last_updated_by.first_name} {deduction.last_updated_by.last_name}' if deduction.last_updated_by is not None else ""
#                     staff_map["staff_position"] = deduction.last_updated_by.staff_position.position_title if deduction.last_updated_by.staff_position is not None else ""
#                     deduction_map["last_updated_by"] = staff_map
#                     deduction_map["created_on"] = datetime.strftime(
#                         deduction.created_on.astimezone(target_timezone), date_format) if deduction.created_on is not None else ""
#                     deduction_map["last_updated_on"] = datetime.strftime(
#                         deduction.last_updated_on.astimezone(target_timezone), date_format) if deduction.last_updated_on is not None else ""
#                     deductions_list.append(deduction_map)
#             for branch in all_branches:
#                 if branch.recycle_bin != True:
#                     company_branch_map = {}
#                     company_branch_map["branch_id"] = str(branch.id)
#                     company_branch_map["branch_name"] = branch.branch_name
#                     company_branch_map["is_main_branch"] = "true" if branch.main_branch == True else "false"
#                     payroll_sheets_list = []
#                     payroll_sheets = branch.branch_payroll_sheets.all().order_by('-id')
#                     for payroll_sheet in payroll_sheets:
#                         if payroll_sheet.recycle_bin == False:
#                             payroll_sheet_map = {}
#                             payroll_sheet_map["payroll_sheet_id"] = str(
#                                 payroll_sheet.id)
#                             payroll_sheet_map["payroll_sheet_title"] = payroll_sheet.payroll_sheet_title
#                             payroll_sheet_map["payroll_sheet_number"] = payroll_sheet.payroll_sheet_number
#                             payroll_sheet_map["payroll_sheet_description"] = payroll_sheet.payroll_sheet_description
#                             payroll_sheet_map["payroll_sheet_for_the_month_of"] = payroll_sheet.payroll_sheet_for_the_month_of
#                             payroll_sheet_map["payroll_sheet_for_the_year"] = payroll_sheet.payroll_sheet_for_the_year
#                             payroll_sheet_map["payroll_sheet_value"] = payroll_sheet.payroll_sheet_value
#                             # added
#                             payroll_sheet_map["payroll_sheet_total_net_pay_value"] = payroll_sheet.payroll_sheet_total_net_pay_value
#                             payroll_sheet_map["payroll_sheet_total_bonus_value"] = payroll_sheet.payroll_sheet_total_bonus_value
#                             payroll_sheet_map["payroll_sheet_total_deduction_value"] = payroll_sheet.payroll_sheet_total_deduction_value
#                             payroll_sheet_map["payroll_sheet_total_commission_value"] = payroll_sheet.payroll_sheet_total_commission_value
#                             payroll_sheet_map["payroll_sheet_approved_by_system_administrator"] = "true" if payroll_sheet.payroll_sheet_approved_by_system_administrator == True else "false"
#                             payroll_sheet_map["is_terminal_dues"] = "true" if payroll_sheet.is_terminal_dues == True else "false"
#                             payroll_sheet_map["currency"] = company_profile.company_preferred_currency
#                             # end added
#                             payroll_sheet_map["payroll_sheet_approved_by_finance"] = "true" if payroll_sheet.payroll_sheet_approved_by_finance == True else "false"
#                             payroll_sheet_map["payroll_sheet_payment_settled"] = "true" if payroll_sheet.payroll_sheet_payment_settled == True else "false"
#                             staff_map = {}
#                             staff_map["staff_id"] = str(
#                                 payroll_sheet.created_by.id) if payroll_sheet.created_by is not None else ""
#                             staff_map["staff_name"] = f'{payroll_sheet.created_by.first_name} {payroll_sheet.created_by.last_name}' if payroll_sheet.created_by is not None else ""
#                             staff_map["staff_position"] = payroll_sheet.created_by.staff_position.position_title if payroll_sheet.created_by.staff_position is not None else ""
#                             payroll_sheet_map["created_by"] = staff_map
#                             staff_map = {}
#                             staff_map["staff_id"] = str(
#                                 payroll_sheet.last_updated_by.id) if payroll_sheet.last_updated_by is not None else ""
#                             staff_map["staff_name"] = f'{payroll_sheet.last_updated_by.first_name} {payroll_sheet.last_updated_by.last_name}' if payroll_sheet.last_updated_by is not None else ""
#                             staff_map["staff_position"] = payroll_sheet.last_updated_by.staff_position.position_title if payroll_sheet.last_updated_by.staff_position is not None else ""
#                             payroll_sheet_map["last_updated_by"] = staff_map
#                             payroll_sheet_map["created_on"] = datetime.strftime(
#                                 payroll_sheet.created_on.astimezone(target_timezone), date_format) if payroll_sheet.created_on is not None else ""
#                             payroll_sheet_map["last_updated_on"] = datetime.strftime(
#                                 payroll_sheet.last_updated_on.astimezone(target_timezone), date_format) if payroll_sheet.last_updated_on is not None else ""
#                             payroll_instances_list = []
#                             payroll_instances = payroll_sheet.staff_payroll_items.all().order_by('-id')
#                             for payroll_instance in payroll_instances:
#                                 if payroll_instance.recycle_bin == False:
#                                     payroll_instance_map = {}
#                                     payroll_instance_map["payroll_instance_id"] = str(
#                                         payroll_instance.id)
#                                     payroll_instance_map["staff_id"] = str(
#                                         payroll_instance.staff_profile.id)
#                                     deduction_instances = payroll_instance.deduction_instance.all().order_by('-id')
#                                     deduction_instances_list = []
#                                     for deduction_instance in deduction_instances:
#                                         if deduction_instance.recycle_bin == False:
#                                             deduction_instance_map = {}
#                                             deduction_instance_map["deduction_instance_id"] = str(
#                                                 deduction_instance.id)
#                                             deduction_instance_map["deduction_id"] = str(
#                                                 deduction_instance.deduction.id) if deduction_instance.deduction is not None else ""
#                                             deduction_instance_map["deduction_title"] = deduction_instance.deduction.deduction_title
#                                             deduction_instance_map["deduction_instance_value"] = deduction_instance.deduction_instance_value
#                                             staff_map = {}
#                                             staff_map["staff_id"] = str(
#                                                 deduction_instance.created_by.id) if deduction_instance.created_by is not None else ""
#                                             staff_map["staff_name"] = f'{deduction_instance.created_by.first_name} {deduction_instance.created_by.last_name}' if deduction_instance.created_by is not None else ""
#                                             staff_map["staff_position"] = deduction_instance.created_by.staff_position.position_title if deduction_instance.created_by.staff_position is not None else ""
#                                             deduction_instance_map["created_by"] = staff_map
#                                             staff_map = {}
#                                             staff_map["staff_id"] = str(
#                                                 deduction_instance.last_updated_by.id) if deduction_instance.last_updated_by is not None else ""
#                                             staff_map["staff_name"] = f'{deduction_instance.last_updated_by.first_name} {deduction_instance.last_updated_by.last_name}' if deduction_instance.last_updated_by is not None else ""
#                                             staff_map["staff_position"] = deduction_instance.last_updated_by.staff_position.position_title if deduction_instance.last_updated_by.staff_position is not None else ""
#                                             deduction_instance_map["last_updated_by"] = staff_map
#                                             deduction_instance_map["created_on"] = datetime.strftime(
#                                                 deduction_instance.created_on.astimezone(target_timezone), date_format) if deduction_instance.created_on is not None else ""
#                                             deduction_instance_map["last_updated_on"] = datetime.strftime(
#                                                 deduction_instance.last_updated_on.astimezone(target_timezone), date_format) if deduction_instance.last_updated_on is not None else ""
#                                             deduction_instances_list.append(
#                                                 deduction_instance_map)
#                                     payroll_instance_map["deduction_instances_list"] = deduction_instances_list
#                                     payroll_instance_map["gross_salary"] = payroll_instance.gross_salary
#                                     bonus_instances = payroll_instance.bonus_instance.all().order_by('-id')
#                                     bonus_instances_list = []
#                                     for bonus_instance in bonus_instances:
#                                         if bonus_instance.recycle_bin == False:
#                                             bonus_instance_map = {}
#                                             bonus_instance_map["bonus_instance_id"] = str(
#                                                 bonus_instance.id)
#                                             bonus_instance_map["bonus_id"] = str(
#                                                 bonus_instance.bonus.id) if bonus_instance.bonus is not None else ""
#                                             bonus_instance_map["bonus_instance_value"] = bonus_instance.bonus_instance_value
#                                             bonus_instance_map["bonus_title"] = bonus_instance.bonus.bonus_title
#                                             staff_map = {}
#                                             staff_map["staff_id"] = str(
#                                                 bonus_instance.created_by.id) if bonus_instance.created_by is not None else ""
#                                             staff_map["staff_name"] = f'{bonus_instance.created_by.first_name} {bonus_instance.created_by.last_name}' if bonus_instance.created_by is not None else ""
#                                             staff_map["staff_position"] = bonus_instance.created_by.staff_position.position_title if bonus_instance.created_by.staff_position is not None else ""
#                                             bonus_instance_map["created_by"] = staff_map
#                                             staff_map = {}
#                                             staff_map["staff_id"] = str(
#                                                 bonus_instance.last_updated_by.id) if bonus_instance.last_updated_by is not None else ""
#                                             staff_map["staff_name"] = f'{bonus_instance.last_updated_by.first_name} {bonus_instance.last_updated_by.last_name}' if bonus_instance.last_updated_by is not None else ""
#                                             staff_map["staff_position"] = bonus_instance.last_updated_by.staff_position.position_title if bonus_instance.last_updated_by.staff_position is not None else ""
#                                             bonus_instance_map["last_updated_by"] = staff_map
#                                             bonus_instance_map["created_on"] = datetime.strftime(
#                                                 bonus_instance.created_on.astimezone(target_timezone), date_format) if deduction_instance.created_on is not None else ""
#                                             bonus_instance_map["last_updated_on"] = datetime.strftime(
#                                                 bonus_instance.last_updated_on.astimezone(target_timezone), date_format) if bonus_instance.last_updated_on is not None else ""
#                                             bonus_instances_list.append(
#                                                 bonus_instance_map)
#                                     payroll_instance_map["bonus_instances_list"] = bonus_instances_list
#                                     payroll_instance_map["net_salary"] = payroll_instance.net_salary
#                                     #
#                                     payroll_instance_commissions = payroll_instance.staff_payroll_instance_commissions.all()
#                                     payroll_instance_commissions_list = []
#                                     for commission_sheet_instance in payroll_instance_commissions:
#                                         if commission_sheet_instance.recycle_bin == False:
#                                             commission_sheet_instance_map = {}
#                                             commission_sheet_instance_map["commission_sheet_instance_id"] = str(
#                                                 commission_sheet_instance.id)
#                                             commission_sheet_instance_map["customer_order_id"] = str(
#                                                 commission_sheet_instance.customer_order.id) if commission_sheet_instance.customer_order is not None else ""
#                                             commission_sheet_instance_map[
#                                                 "commission_value"] = commission_sheet_instance.commission_value
#                                             commission_sheet_instance_map[
#                                                 "commission_sheet_id"] = str(commission_sheet_instance.commission_sheet.id) if commission_sheet_instance.commission_sheet is not None else ""
#                                             commission_sheet_instance_map[
#                                                 "commission_sheet_number"] = commission_sheet_instance.commission_sheet.commission_sheet_number if commission_sheet_instance.commission_sheet is not None else ""
#                                             commission_sheet_instance_map[
#                                                 "commission_sheet_title"] = commission_sheet_instance.commission_sheet.commission_sheet_title if commission_sheet_instance.commission_sheet is not None else ""
#                                             payroll_instance_commissions_list.append(
#                                                 commission_sheet_instance_map)
#                                     payroll_instance_map["payroll_instance_commissions_list"] = payroll_instance_commissions_list
#                                     payroll_instance_map["commissions_total"] = payroll_instance.commissions_total
#                                     payroll_instance_map["is_prorated"] = "true" if payroll_instance.is_prorated == True else "false"
#                                     payroll_instance_map["pro_rate_factor"] = payroll_instance.pro_rate_factor
#                                     #
#                                     staff_map = {}
#                                     staff_map["staff_id"] = str(
#                                         payroll_instance.created_by.id) if payroll_instance.created_by is not None else ""
#                                     staff_map["staff_name"] = f'{payroll_instance.created_by.first_name} {payroll_instance.created_by.last_name}' if payroll_instance.created_by is not None else ""
#                                     staff_map["staff_position"] = payroll_instance.created_by.staff_position.position_title if payroll_instance.created_by.staff_position is not None else ""
#                                     payroll_instance_map["created_by"] = staff_map
#                                     staff_map = {}
#                                     staff_map["staff_id"] = str(
#                                         payroll_instance.last_updated_by.id) if payroll_instance.last_updated_by is not None else ""
#                                     staff_map["staff_name"] = f'{payroll_instance.last_updated_by.first_name} {payroll_instance.last_updated_by.last_name}' if payroll_instance.last_updated_by is not None else ""
#                                     staff_map["staff_position"] = payroll_instance.last_updated_by.staff_position.position_title if payroll_instance.last_updated_by.staff_position is not None else ""
#                                     payroll_instance_map["last_updated_by"] = staff_map
#                                     payroll_instance_map["created_on"] = datetime.strftime(
#                                         payroll_instance.created_on.astimezone(target_timezone), date_format) if payroll_instance.created_on is not None else ""
#                                     payroll_instance_map["last_updated_on"] = datetime.strftime(
#                                         payroll_instance.last_updated_on.astimezone(target_timezone), date_format) if payroll_instance.last_updated_on is not None else ""
#                                     payroll_instances_list.append(
#                                         payroll_instance_map)
#                             # print(payroll_instances_list)
#                             # payroll_sheet_map["payroll_instances_list"] = payroll_instances_list
#                             # payroll_sheets_list.append(payroll_sheet_map)
#                             payroll_sheet_map["payroll_instances_list"] = payroll_instances_list
#                             payroll_sheets_list.append(payroll_sheet_map)
#                     company_branch_map["payroll_sheets_list"] = payroll_sheets_list
#                     # end payroll sheets
#                     company_branches_list.append(company_branch_map)
#             company_profile_map["company_branches_list"] = company_branches_list
#             payload["company_profile"] = company_profile_map
#             payload["active_staff_profile_data"] = active_staff_profile_data
#             payload["staff_positions_list"] = staff_positions_list
#             payload["deductions_list"] = deductions_list
#             payload["company_departments_list"] = company_departments_list
#             return Response({"message": "true", "payload": payload}, status=200)
#         else:
#             return Response({"message": "false", "payload": payload}, status=401)
#     except Exception as e:
#         print(e)
#         return Response({"message": "false", "payload": payload}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def finance_and_accounting_dashboard(request):
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    current_date = datetime.now().date()
    company_serial_number = request.data.get("serial_number", "")
    active_user = request.user
    payload = {}
    company_profile_map = {}
    company_branches_list = []
    company_branch_map = {}
    loan_portfolio_list = []
    loan_portfolio_map = {}
    chart_of_account_list = []
    chart_of_account_map = {}
    expense_list = []
    expense_map = {}
    deposit_list = []
    deposit_map = {}
    transaction_list = []
    transaction_map = {}
    landed_costs_list = []
    purchase_order_list = []
    supplier_list = []
    purchase_order_product_instances_list = []
    purchase_order_product_instance_map = {}
    category_list = []
    deductions_list = []
    bonuses_list = []
    staff_positions_list = []
    company_departments_list = []
    # accounts_payable_list = []
    try:
        if not company_serial_number:
            return Response({"message": "serial_number is required", "payload": payload}, status=400)
        try:
            company_profile = CompanyProfile.objects.get(
                company_serial_number=company_serial_number)
        except CompanyProfile.DoesNotExist:
            company_profile = CompanyProfile.objects.order_by("id").first()
            if company_profile is None:
                return Response({"message": "No company found for this serial number", "payload": payload}, status=404)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if company_profile and user_has_permission(staff_profile, "finance_and_accounting.dashboard.view"):
            active_staff_profile_data = get_staff_profile_data(active_user)
            company_profile_map["company_id"] = str(company_profile.id)
            company_profile_map["company_name"] = company_profile.company_name
            company_profile_map["company_phone"] = company_profile.company_phone
            company_profile_map["preferred_currency"] = company_profile.company_preferred_currency
            company_profile_map["company_postal_address"] = company_profile.company_postal_address
            company_loan_portfolio = company_profile.company_loan_portfolio.all().order_by("-id")
            all_suppliers = Supplier.objects.all().order_by("-id")
            all_branches = company_profile.company_branches.all().order_by("-id")
            all_categories = Category.objects.all().order_by("-id")
            all_landed_costs = LandedCost.objects.filter(
                recycle_bin=False, company_profile=company_profile).order_by("-id")
            all_transactions = Transaction.objects.filter(
                recycle_bin=False,).order_by("-id")
            company_purchase_orders = company_profile.company_purchase_orders.filter(
                recycle_bin=False).order_by("-id")
            #
            company_departments = company_profile.company_departments.all().order_by('-id')
            for department in company_departments:
                if department.recycle_bin == False:
                    department_map = {}
                    department_map["department_id"] = str(department.id)
                    department_map["department_name"] = department.department_name
                    department_map["department_description"] = department.department_description
                    department_map["created_on"] = datetime.strftime(
                        department.created_on.astimezone(target_timezone), date_format)
                    department_map["last_updated_on"] = datetime.strftime(
                        department.last_updated_on.astimezone(target_timezone), date_format)
                    company_departments_list.append(department_map)
            #
            staff_positions = company_profile.company_staff_positions.all().order_by('-id')
            for position in staff_positions:
                if position.recycle_bin == False:
                    staff_position_map = {}
                    staff_position_map["staff_position_id"] = str(position.id)
                    staff_position_map["position_title"] = position.position_title
                    staff_position_map["position_description"] = position.position_description
                    staff_position_map["salary"] = position.salary
                    staff_position_map["created_on"] = datetime.strftime(
                        position.created_on.astimezone(target_timezone), date_format) if position.created_on is not None else ""
                    staff_position_map["last_updated_on"] = datetime.strftime(
                        position.last_updated_on.astimezone(target_timezone), date_format) if position.last_updated_on is not None else ""
                    staff_positions_list.append(staff_position_map)
            deductions = company_profile.company_deductions.all().order_by('-id')
            for deduction in deductions:
                if deduction.recycle_bin == False:
                    deduction_map = {}
                    deduction_map["deduction_id"] = str(deduction.id)
                    deduction_map["deduction_title"] = deduction.deduction_title
                    deduction_map["deduction_description"] = deduction.deduction_description
                    deduction_map["deduction_type"] = deduction.deduction_type
                    deduction_map["deduction_module"] = deduction.deduction_module
                    deduction_map["deduction_value"] = deduction.deduction_value
                    deduction_map["date_effective_from"] = deduction.date_effective_from
                    deduction_map["date_effective_to"] = deduction.date_effective_to
                    staff_map = {}
                    staff_map["staff_id"] = str(
                        deduction.created_by.id) if deduction.created_by is not None else ""
                    staff_map["staff_name"] = f'{deduction.created_by.first_name} {deduction.created_by.last_name}' if deduction.created_by is not None else ""
                    staff_map["staff_position"] = deduction.created_by.staff_position.position_title if deduction.created_by is not None and deduction.created_by.staff_position is not None else ""
                    deduction_map["created_by"] = staff_map
                    staff_map = {}
                    staff_map["staff_id"] = str(
                        deduction.last_updated_by.id) if deduction.last_updated_by is not None else ""
                    staff_map["staff_name"] = f'{deduction.last_updated_by.first_name} {deduction.last_updated_by.last_name}' if deduction.last_updated_by is not None else ""
                    staff_map["staff_position"] = deduction.last_updated_by.staff_position.position_title if deduction.last_updated_by is not None and deduction.last_updated_by.staff_position is not None else ""
                    deduction_map["last_updated_by"] = staff_map
                    deduction_map["created_on"] = datetime.strftime(
                        deduction.created_on.astimezone(target_timezone), date_format) if deduction.created_on is not None else ""
                    deduction_map["last_updated_on"] = datetime.strftime(
                        deduction.last_updated_on.astimezone(target_timezone), date_format) if deduction.last_updated_on is not None else ""
                    deductions_list.append(deduction_map)
            # bonuses
            bonuses = company_profile.company_bonuses.all().order_by('-id')
            for bonus in bonuses:
                if bonus.recycle_bin == False:
                    bonus_map = {}
                    bonus_map["bonus_id"] = str(bonus.id)
                    bonus_map["bonus_title"] = bonus.bonus_title
                    bonus_map["bonus_description"] = bonus.bonus_description
                    bonus_map["bonus_type"] = bonus.bonus_type
                    bonus_map["bonus_amount"] = bonus.bonus_amount
                    bonus_map["date_effective_from"] = datetime.strftime(
                        bonus.date_effective_from, '%d/%m/%Y')
                    bonus_map["date_effective_to"] = datetime.strftime(
                        bonus.date_effective_to, '%d/%m/%Y')
                    staff_map = {}
                    staff_map["staff_id"] = str(
                        bonus.created_by.id) if bonus.created_by is not None else ""
                    staff_map["staff_name"] = f'{bonus.created_by.first_name} {bonus.created_by.last_name}' if bonus.created_by is not None else ""
                    staff_map["staff_position"] = bonus.created_by.staff_position.position_title if bonus.created_by is not None and bonus.created_by.staff_position is not None else ""
                    bonus_map["created_by"] = staff_map
                    staff_map = {}
                    staff_map["staff_id"] = str(
                        bonus.last_updated_by.id) if bonus.last_updated_by is not None else ""
                    staff_map["staff_name"] = f'{bonus.last_updated_by.first_name} {bonus.last_updated_by.last_name}' if bonus.last_updated_by is not None else ""
                    staff_map["staff_position"] = bonus.last_updated_by.staff_position.position_title if bonus.last_updated_by is not None and bonus.last_updated_by.staff_position is not None else ""
                    bonus_map["last_updated_by"] = staff_map
                    bonus_map["created_on"] = datetime.strftime(
                        bonus.created_on.astimezone(target_timezone), date_format) if bonus.created_on is not None else ""
                    bonus_map["last_updated_on"] = datetime.strftime(
                        bonus.last_updated_on.astimezone(target_timezone), date_format) if bonus.last_updated_on is not None else ""
                    bonuses_list.append(bonus_map)
            #
            for transaction in all_transactions:
                transaction_map = {}
                transaction_map["transaction_id"] = str(transaction.id)
                transaction_map["transaction_number"] = transaction.transaction_number
                transaction_map["transaction_mode"] = transaction.transaction_mode
                transaction_map["transaction_amount"] = transaction.transaction_amount
                transaction_map["transaction_currency"] = transaction.transaction_currency
                transaction_map["exchange_rate"] = transaction.exchange_rate
                transaction_map["expense_id"] = str(
                    transaction.expense.id) if transaction.expense is not None else ""
                transaction_map["deposit_id"] = str(
                    transaction.deposit.id) if transaction.deposit is not None else ""
                transaction_map["account_id"] = str(
                    transaction.account.id) if transaction.account is not None else ""
                transaction_map["loan_portfolio_id"] = str(
                    transaction.loan_payment.id) if transaction.loan_payment is not None else ""
                transaction_map["transaction_reference"] = transaction.transaction_reference
                transaction_map["created_on"] = datetime.strftime(
                    transaction.created_on.astimezone(target_timezone), date_format) if transaction.created_on is not None else ""
                transaction_map["last_updated_on"] = datetime.strftime(
                    transaction.last_updated_on.astimezone(target_timezone), date_format) if transaction.last_updated_on is not None else ""
                creator_map = {}
                if transaction.transaction_mode == "outflow":
                    creator_map["staff_id"] = str(
                        transaction.expense.created_by.id) if transaction.expense is not None and transaction.expense.created_by is not None else ""
                    creator_map["staff_name"] = f'{transaction.expense.created_by.first_name} {transaction.expense.created_by.last_name}' if transaction.expense is not None and transaction.expense.created_by is not None else ""
                    creator_map["staff_position"] = transaction.expense.created_by.staff_position.position_title if transaction.expense is not None and transaction.expense.created_by is not None and transaction.expense.created_by.staff_position is not None else ""
                    transaction_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        transaction.expense.last_updated_by.id) if transaction.expense is not None and transaction.expense.last_updated_by is not None else ""
                    creator_map["staff_name"] = f'{transaction.expense.last_updated_by.first_name} {transaction.expense.last_updated_by.last_name}' if transaction.expense is not None and transaction.expense.last_updated_by is not None else ""
                    creator_map["staff_position"] = transaction.expense.last_updated_by.staff_position.position_title if transaction.expense is not None and transaction.expense.last_updated_by is not None and transaction.expense.last_updated_by.staff_position is not None else ""
                    transaction_map["last_updated_by"] = creator_map
                else:
                    creator_map["staff_id"] = str(
                        transaction.deposit.created_by.id) if transaction.deposit is not None and transaction.deposit.created_by is not None else ""
                    creator_map["staff_name"] = f'{transaction.deposit.created_by.first_name} {transaction.deposit.created_by.last_name}' if transaction.deposit is not None and transaction.deposit.created_by is not None else ""
                    creator_map["staff_position"] = transaction.deposit.created_by.staff_position.position_title if transaction.deposit is not None and transaction.deposit.created_by is not None and transaction.deposit.created_by.staff_position is not None else ""
                    transaction_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        transaction.deposit.last_updated_by.id) if transaction.deposit is not None and transaction.deposit.last_updated_by is not None else ""
                    creator_map["staff_name"] = f'{transaction.deposit.last_updated_by.first_name} {transaction.deposit.last_updated_by.last_name}' if transaction.deposit is not None and transaction.deposit.last_updated_by is not None else ""
                    creator_map["staff_position"] = transaction.deposit.last_updated_by.staff_position.position_title if transaction.deposit is not None and transaction.deposit.last_updated_by is not None and transaction.deposit.last_updated_by.staff_position is not None else ""
                    transaction_map["last_updated_by"] = creator_map
                transaction_list.append(transaction_map)
            for loan_portfolio in company_loan_portfolio:
                if loan_portfolio.recycle_bin != True:
                    loan_portfolio_map = {}
                    loan_portfolio_map["loan_id"] = str(loan_portfolio.id)
                    loan_portfolio_map["loan_title"] = loan_portfolio.loan_title
                    loan_portfolio_map["loan_type"] = loan_portfolio.loan_type
                    loan_portfolio_map["lender_name"] = loan_portfolio.lender_name
                    loan_portfolio_map["lender_phone"] = loan_portfolio.lender_phone
                    loan_portfolio_map["lender_email"] = loan_portfolio.lender_email
                    loan_portfolio_map["loan_amount"] = loan_portfolio.loan_amount
                    loan_portfolio_map["interest_rate"] = loan_portfolio.interest_rate
                    loan_portfolio_map["repayment_period"] = loan_portfolio.repayment_period
                    loan_portfolio_map["total_repayment_amount"] = loan_portfolio.total_repayment_amount
                    loan_portfolio_map["principal_paid"] = loan_portfolio.principal_paid
                    loan_portfolio_map["loan_currency"] = loan_portfolio.loan_currency
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        loan_portfolio.created_by.id) if loan_portfolio.created_by is not None else ""
                    creator_map["staff_name"] = f'{loan_portfolio.created_by.first_name} {loan_portfolio.created_by.last_name}' if loan_portfolio.created_by is not None else ""
                    creator_map["staff_position"] = loan_portfolio.created_by.staff_position.position_title if loan_portfolio.created_by is not None and loan_portfolio.created_by.staff_position is not None else ""
                    loan_portfolio_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        loan_portfolio.last_updated_by.id) if loan_portfolio.last_updated_by is not None else ""
                    creator_map["staff_name"] = f'{loan_portfolio.last_updated_by.first_name} {loan_portfolio.last_updated_by.last_name}' if loan_portfolio.last_updated_by is not None else ""
                    creator_map["staff_position"] = loan_portfolio.last_updated_by.staff_position.position_title if loan_portfolio.last_updated_by is not None and loan_portfolio.last_updated_by.staff_position is not None else ""
                    loan_portfolio_map["last_updated_by"] = creator_map
                    loan_portfolio_map["created_on"] = datetime.strftime(
                        loan_portfolio.created_on.astimezone(target_timezone), date_format) if loan_portfolio.created_on is not None else ""
                    loan_portfolio_map["last_updated_on"] = datetime.strftime(
                        loan_portfolio.last_updated_on.astimezone(target_timezone), date_format) if loan_portfolio.last_updated_on is not None else ""
                    loan_payment_history_list = []
                    loan_payment_history = loan_portfolio.loan_payment_history.all().order_by("-id")
                    for loan_payment in loan_payment_history:
                        loan_payment_history_map = {}
                        loan_payment_history_map["loan_payment_id"] = str(
                            loan_payment.id)
                        loan_payment_history_map["transaction_amount"] = loan_payment.transaction_amount
                        loan_payment_history_list.append(
                            loan_payment_history_map)
                    loan_portfolio_map["loan_payment_history_list"] = loan_payment_history_list
                    loan_portfolio_list.append(loan_portfolio_map)
            for landed_cost in all_landed_costs:
                landed_cost_instances_list = []
                landed_cost_map = {}
                landed_cost_map["landed_cost_id"] = str(landed_cost.id)
                landed_cost_map["name_of_expense"] = landed_cost.name_of_expense
                landed_cost_map["description_of_calculation"] = landed_cost.description_of_calculation
                creator_map = {}
                creator_map["staff_id"] = str(
                    landed_cost.created_by.id) if landed_cost.created_by is not None else ""
                creator_map["staff_name"] = f'{landed_cost.created_by.first_name} {landed_cost.created_by.last_name}' if landed_cost.created_by is not None else ""
                creator_map["staff_position"] = landed_cost.created_by.staff_position.position_title if landed_cost.created_by is not None and landed_cost.created_by.staff_position is not None else ""
                landed_cost_map["created_by"] = creator_map
                creator_map = {}
                creator_map["staff_id"] = str(
                    landed_cost.last_updated_by.id) if landed_cost.last_updated_by is not None else ""
                creator_map["staff_name"] = f'{landed_cost.last_updated_by.first_name} {landed_cost.last_updated_by.last_name}' if landed_cost.last_updated_by is not None else ""
                creator_map["staff_position"] = landed_cost.last_updated_by.staff_position.position_title if landed_cost.last_updated_by is not None and landed_cost.last_updated_by.staff_position is not None else ""
                landed_cost_map["last_updated_by"] = creator_map
                landed_cost_map["created_on"] = datetime.strftime(
                    landed_cost.created_on.astimezone(target_timezone), date_format) if landed_cost.created_on is not None else ""
                landed_cost_map["last_updated_on"] = datetime.strftime(
                    landed_cost.last_updated_on.astimezone(target_timezone), date_format) if landed_cost.last_updated_on is not None else ""
                landed_cost_instances = landed_cost.landed_cost_instances.all().order_by("-id")
                for landed_cost_instance in landed_cost_instances:
                    landed_cost_instance_map = {}
                    landed_cost_instance_map["landed_cost_id"] = str(
                        landed_cost.id)
                    landed_cost_instance_map["landed_cost_instance_id"] = str(
                        landed_cost_instance.id)
                    landed_cost_instance_map["cost_value"] = landed_cost_instance.cost_value
                    landed_cost_instance_map["exchange_rate"] = landed_cost_instance.exchange_rate
                    landed_cost_instance_map["cost_currency"] = landed_cost_instance.cost_currency
                    landed_cost_instance_map["cost_amount_paid"] = landed_cost_instance.cost_amount_paid
                    landed_cost_instance_map["cost_amount_due"] = landed_cost_instance.cost_amount_due
                    landed_cost_instance_map["cost_payment_settled"] = "true" if landed_cost_instance.cost_payment_settled == True else "false"
                    landed_cost_instances_list.append(landed_cost_instance_map)
                landed_cost_map["landed_cost_instances_list"] = landed_cost_instances_list
                landed_costs_list.append(landed_cost_map)
            company_profile_map["landed_costs_list"] = landed_costs_list
            for purchase_order in company_purchase_orders:
                product_purchase_instances_list = []
                purchase_order_map = {}
                purchase_order_map["purchase_order_id"] = str(
                    purchase_order.id)
                purchase_order_map["purchase_order_number"] = purchase_order.purchase_order_number
                purchase_order_map["currency"] = company_profile.company_preferred_currency
                purchase_order_map["purchase_value_overall"] = purchase_order.purchase_value_overall
                purchase_order_map["purchase_order_approved"] = "true" if purchase_order.purchase_order_approved == True else "false"
                purchase_order_map["purchase_order_landed_costs_overall"] = purchase_order.purchase_order_landed_costs_overall
                purchase_order_map["created_on"] = datetime.strftime(
                    purchase_order.created_on.astimezone(target_timezone), date_format) if purchase_order.created_on is not None else ""
                purchase_order_map["last_updated_on"] = datetime.strftime(
                    purchase_order.last_updated_on.astimezone(target_timezone), date_format) if purchase_order.last_updated_on is not None else ""
                creator_map = {}
                creator_map["staff_id"] = str(
                    purchase_order.created_by.id) if purchase_order.created_by is not None else ""
                creator_map["staff_name"] = f'{purchase_order.created_by.first_name} {purchase_order.created_by.last_name}' if purchase_order.created_by is not None else ""
                creator_map["staff_position"] = purchase_order.created_by.staff_position.position_title if purchase_order.created_by is not None and purchase_order.created_by.staff_position is not None else ""
                purchase_order_map["created_by"] = creator_map
                creator_map = {}
                creator_map["staff_id"] = str(
                    purchase_order.last_updated_by.id) if purchase_order.last_updated_by is not None else ""
                creator_map["staff_name"] = f'{purchase_order.last_updated_by.first_name} {purchase_order.last_updated_by.last_name}' if purchase_order.last_updated_by is not None else ""
                creator_map["staff_position"] = purchase_order.last_updated_by.staff_position.position_title if purchase_order.last_updated_by is not None and purchase_order.last_updated_by.staff_position is not None else ""
                purchase_order_map["last_updated_by"] = creator_map
                #
                creator_map = {}
                creator_map["staff_id"] = str(
                    purchase_order.purchase_order_approved_by.id) if purchase_order.purchase_order_approved_by is not None else ""
                creator_map["staff_name"] = f'{purchase_order.purchase_order_approved_by.first_name} {purchase_order.purchase_order_approved_by.last_name}' if purchase_order.purchase_order_approved_by is not None else ""
                creator_map["staff_position"] = purchase_order.purchase_order_approved_by.staff_position.position_title if purchase_order.purchase_order_approved_by is not None and purchase_order.purchase_order_approved_by.staff_position is not None else ""
                purchase_order_map["purchase_order_approved_by"] = creator_map
                purchase_order_product_instances = purchase_order.purchase_order_product_instances.filter(
                    recycle_bin=False).order_by("-id")
                # print(len(purchase_order_product_instances))
                for product_purchase_instance in purchase_order_product_instances:
                    purchase_order_product_instance_map = {}
                    # print(product_purchase_instance.id)
                    landed_cost_product_purchase_instances_list = []
                    purchase_order_product_instance_map["product_purchase_instance_id"] = str(
                        product_purchase_instance.id)
                    purchase_order_product_instance_map["product_id"] = str(
                        product_purchase_instance.purchase_product.id) if product_purchase_instance.purchase_product is not None else ""
                    purchase_order_product_instance_map["purchase_order_number"] = purchase_order.purchase_order_number
                    purchase_order_product_instance_map["supplier_id"] = str(
                        product_purchase_instance.supplier.id) if product_purchase_instance.supplier is not None else ""
                    purchase_order_product_instance_map[
                        "purchase_value_per_unit"] = product_purchase_instance.purchase_value_per_unit
                    purchase_order_product_instance_map[
                        "cost_currency"] = product_purchase_instance.cost_currency
                    purchase_order_product_instance_map[
                        "exchange_rate"] = product_purchase_instance.exchange_rate
                    purchase_order_product_instance_map[
                        "purchase_value_overall"] = product_purchase_instance.purchase_value_overall
                    purchase_order_product_instance_map[
                        "purchase_amount_paid_to_supplier"] = product_purchase_instance.purchase_amount_paid_to_supplier
                    purchase_order_product_instance_map[
                        "supplier_payment_settled"] = "true" if product_purchase_instance.supplier_payment_settled == True else "false"
                    # purchase_order_product_instance_map[
                    #     "supplier_payment_settled"] = "true" if product_purchase_instance.supplier_payment_settled == True else "false"
                    purchase_order_product_instance_map[
                        "product_purchase_delivered"] = "true" if product_purchase_instance.product_purchase_delivered == True else "false"
                    purchase_order_product_instance_map[
                        "quantity_purchased"] = product_purchase_instance.quantity_purchased
                    purchase_order_product_instance_map[
                        "quantity_delivered"] = product_purchase_instance.quantity_delivered
                    # purchase_order_product_instance_map[
                    #     "quantity_delivered"] = product_purchase_instance.quantity_delivered
                    purchase_order_product_instance_map["created_on"] = datetime.strftime(
                        purchase_order.created_on, date_format) if product_purchase_instance.created_on is not None else ""
                    purchase_order_product_instance_map["last_updated_on"] = datetime.strftime(
                        product_purchase_instance.last_updated_on, date_format) if product_purchase_instance.last_updated_on is not None else ""
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        product_purchase_instance.created_by.id) if product_purchase_instance.created_by is not None else ""
                    creator_map["staff_name"] = f'{product_purchase_instance.created_by.first_name} {product_purchase_instance.created_by.last_name}' if product_purchase_instance.created_by is not None else ""
                    creator_map["staff_position"] = product_purchase_instance.created_by.staff_position.position_title if product_purchase_instance.created_by is not None and product_purchase_instance.created_by.staff_position is not None else ""
                    purchase_order_product_instance_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        product_purchase_instance.last_updated_by.id) if product_purchase_instance.last_updated_by is not None else ""
                    creator_map["staff_name"] = f'{product_purchase_instance.last_updated_by.first_name} {product_purchase_instance.last_updated_by.last_name}' if product_purchase_instance.last_updated_by is not None else ""
                    creator_map["staff_position"] = product_purchase_instance.last_updated_by.staff_position.position_title if product_purchase_instance.last_updated_by is not None and product_purchase_instance.last_updated_by.staff_position is not None else ""
                    purchase_order_product_instance_map["last_updated_by"] = creator_map
                    landed_cost_product_purchase_instances = product_purchase_instance.landed_cost_product_purchase_instances.all().order_by("-id")
                    for landed_cost_instance in landed_cost_product_purchase_instances:
                        # print(landed_cost_instance)
                        landed_cost_instance_map = {}
                        landed_cost_instance_map["landed_cost_id"] = str(
                            landed_cost_instance.landed_cost.id) if landed_cost_instance.landed_cost is not None else ""
                        landed_cost_instance_map["landed_cost_instance_id"] = str(
                            landed_cost_instance.id)
                        landed_cost_instance_map["cost_value"] = landed_cost_instance.cost_value
                        landed_cost_instance_map["exchange_rate"] = landed_cost_instance.exchange_rate
                        landed_cost_instance_map["cost_currency"] = landed_cost_instance.cost_currency
                        landed_cost_instance_map["cost_amount_paid"] = landed_cost_instance.cost_amount_paid
                        landed_cost_instance_map["cost_amount_due"] = landed_cost_instance.cost_amount_due
                        landed_cost_instance_map["cost_payment_settled"] = "true" if landed_cost_instance.cost_payment_settled == True else "false"
                        # print(landed_cost_instance_map)
                        landed_cost_product_purchase_instances_list.append(
                            landed_cost_instance_map)
                    purchase_order_product_instance_map[
                        "landed_cost_product_purchase_instances_list"] = landed_cost_product_purchase_instances_list
                    purchase_order_product_instances_list.append(
                        purchase_order_product_instance_map)
                    # print(landed_cost_product_purchase_instances_list)
                    landed_cost_product_purchase_instances_list = []
                # print(len(purchase_order_product_instances_list))
                purchase_order_map["purchase_order_product_instances_list"] = purchase_order_product_instances_list
                # print(
                #     purchase_order_map["purchase_order_product_instances_list"])
                purchase_order_product_instances_list = []
                purchase_order_list.append(purchase_order_map)
            company_profile_map["purchase_order_list"] = purchase_order_list
            # add suppliers
            for supplier in all_suppliers:
                if supplier.recycle_bin != True:
                    supplier_map = {}
                    supplied_products_list = []
                    supplier_map["supplier_id"] = str(supplier.id)
                    supplier_map["preferred_currency"] = company_profile.company_preferred_currency
                    supplier_map["supplier_name"] = supplier.supplier_name
                    supplier_map["supplier_phone"] = supplier.supplier_phone
                    supplier_map["supplier_email"] = supplier.supplier_email
                    supplier_map["supplier_address"] = supplier.supplier_address
                    supplier_map["supplier_description"] = supplier.supplier_description
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        supplier.created_by.id) if supplier.created_by is not None else ""
                    creator_map["staff_name"] = f'{supplier.created_by.first_name} {supplier.created_by.last_name}' if supplier.created_by is not None else ""
                    creator_map["staff_position"] = supplier.created_by.staff_position.position_title if supplier.created_by is not None and supplier.created_by.staff_position is not None else ""
                    supplier_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        supplier.last_updated_by.id) if supplier.last_updated_by is not None else ""
                    creator_map["staff_name"] = f'{supplier.last_updated_by.first_name} {supplier.last_updated_by.last_name}' if supplier.last_updated_by is not None else ""
                    creator_map["staff_position"] = supplier.last_updated_by.staff_position.position_title if supplier.last_updated_by is not None and supplier.last_updated_by.staff_position is not None else ""
                    supplier_map["last_updated_by"] = creator_map
                    supplier_map["created_on"] = datetime.strftime(
                        supplier.created_on.astimezone(target_timezone), date_format) if supplier.created_on is not None else ""
                    supplier_map["last_updated_on"] = datetime.strftime(
                        supplier.last_updated_on.astimezone(target_timezone), date_format) if supplier.last_updated_on is not None else ""
                    # supplied products
                    supplied_products = supplier.supplied_products.all()
                    for supplied_product in supplied_products:
                        supplied_product_map = {}
                        supplied_product_map["product_id"] = str(
                            supplied_product.id)
                        supplied_product_map["product_name"] = supplied_product.product_name
                        supplied_products_list.append(supplied_product_map)
                    supplier_map["supplied_products_list"] = supplied_products_list
                    # supllier payment details
                    supplier_payment_details = supplier.supplier_payment_details.all().order_by("-id")
                    supplier_payment_details_list = []
                    for supplier_payment_detail in supplier_payment_details:
                        supplier_payment_detail_map = {}
                        supplier_payment_detail_map["supplier_payment_detail_id"] = str(
                            supplier_payment_detail.id)
                        supplier_payment_detail_map["bank_institution_name"] = supplier_payment_detail.banking_institution_name
                        supplier_payment_detail_map["bank_account_name"] = supplier_payment_detail.bank_account_name
                        supplier_payment_detail_map["bank_account_number"] = supplier_payment_detail.bank_account_number
                        supplier_payment_detail_map["bank_branch_name"] = supplier_payment_detail.bank_branch_name
                        supplier_payment_detail_map["bank_branch_code"] = supplier_payment_detail.bank_branch_code
                        supplier_payment_detail_map["bank_swift_code"] = supplier_payment_detail.bank_swift_code
                        supplier_payment_detail_map["created_on"] = datetime.strftime(
                            supplier_payment_detail.created_on.astimezone(target_timezone), date_format) if supplier_payment_detail.created_on is not None else ""
                        supplier_payment_detail_map["last_updated_on"] = datetime.strftime(
                            supplier_payment_detail.last_updated_on.astimezone(target_timezone), date_format) if supplier_payment_detail.last_updated_on is not None else ""
                        supplier_payment_details_list.append(
                            supplier_payment_detail_map)
                    supplier_map["supplier_payment_details_list"] = supplier_payment_details_list
                    supplier_product_purchase_instances = supplier.supplier_product_purchase_instances.all().order_by("-id")
                    supplied_product_history_list = []
                    for supplied_product in supplier_product_purchase_instances:
                        if supplied_product.recycle_bin != True:
                            supplied_product_map = {}
                            supplied_product_map["purchase_order_number"] = supplied_product.purchase_order.purchase_order_number if supplied_product.purchase_order is not None else ""
                            # try:
                            #     supplied_product_map["purchase_requisition_number"] = supplied_product.purchase_requisition_instance.purchase_requisition.purchase_requisition_number
                            # except:
                            #     supplied_product_map["purchase_requisition_number"] = "Deleted"
                            supplied_product_map["quantity_delivered"] = supplied_product.quantity_delivered
                            supplied_product_map["purchase_value_per_unit"] = supplied_product.purchase_value_per_unit
                            supplied_product_map["purchase_value_overall"] = supplied_product.purchase_value_overall
                            supplied_product_map["purchase_amount_paid_to_supplier"] = supplied_product.purchase_amount_paid_to_supplier
                            supplied_product_map["supplier_payment_settled"] = "true" if supplied_product.supplier_payment_settled == True else "false"
                            supplied_product_map["product_purchase_delivered"] = "true" if supplied_product.product_purchase_delivered == True else "false"
                            try:
                                supplied_product_map["product_name"] = supplied_product.purchase_requisition_instance.product.product_name
                            except:
                                supplied_product_map["product_name"] = "Deleted product"
                            supplied_product_history_list.append(
                                supplied_product_map)
                    supplier_map["supplied_product_history_list"] = supplied_product_history_list
                    supplier_list.append(supplier_map)
            for category in all_categories:
                if category.recycle_bin != True:
                    category_map = {}
                    product_list = []
                    category_map["category_id"] = str(category.id)
                    category_map["category_name"] = category.category_name
                    category_map["category_description"] = category.category_description
                    category_products = category.category_products.all().order_by("-id")
                    for product in category_products:
                        if product.recycle_bin != True:
                            product_map = {}
                            product_image_catalogues_list = []
                            product_features_catalogues_list = []
                            product_components_list = []
                            product_brands_list = []
                            product_pricing_map = {}  # 0netoone
                            product_discount_map = {}  # onetoone
                            product_vat_map = {}  # onetoone
                            product_map["product_id"] = str(product.id)
                            product_map["product_name"] = product.product_name
                            product_map["stock_keeping_unit"] = product.stock_keeping_unit
                            product_map["unit_of_measurement"] = product.unit_of_measurement
                            product_map["product_description"] = product.product_description
                            # attaching product specific details
                            # attaching product images
                            product_image_catalogue = product.product_images.all().order_by("-id")
                            for product_image in product_image_catalogue:
                                product_image_catalogue_map = {}
                                product_image_catalogue_map["product_image_id"] = str(
                                    product_image.id)
                                product_image_catalogue_map["product_image_url"] = product_image.product_image.url
                                product_image_catalogue_map["image_attribute"] = product_image.image_attribute
                                product_image_catalogue_map["use_as_main_image"] = "true" if product_image.use_as_main_image == True else "false"
                                product_image_catalogues_list.append(
                                    product_image_catalogue_map)
                            product_map["product_image_catalogues_list"] = product_image_catalogues_list
                            # attach product features and attributes
                            product_features_catalogue = product.product_features.all().order_by("-id")
                            for product_feature in product_features_catalogue:
                                product_features_catalogue_map = {}
                                product_features_attributes_list = []
                                product_features_catalogue_map["product_feature_id"] = str(
                                    product_feature.id)
                                product_features_catalogue_map["product_feature_title"] = product_feature.product_feature_title
                                # append features attributes
                                product_features_attributes = product_feature.product_feature_attributes.all().order_by("-id")
                                for feature_attribute in product_features_attributes:
                                    product_features_attributes_map = {}
                                    product_features_attributes_map[
                                        "feature_attribute_id"] = str(feature_attribute.id)
                                    product_features_attributes_map[
                                        "feature_attribute_title"] = feature_attribute.feature_attribute_title
                                    product_features_attributes_map[
                                        "feature_attribute_description"] = feature_attribute.feature_attribute_description
                                    product_features_attributes_list.append(
                                        product_features_attributes_map)
                                product_features_catalogue_map["product_features_attributes_list"] = product_features_attributes_list
                                product_features_catalogues_list.append(
                                    product_features_catalogue_map)
                            product_map["product_features_catalogues_list"] = product_features_catalogues_list
                            # attach product components
                            product_components = product.product_components.all().order_by("-id")
                            for product_component in product_components:
                                product_component_map = {}
                                product_component_map["product_component_id"] = str(
                                    product_component.id)
                                product_component_map["component_name"] = product_component.component_name
                                product_component_map["component_quantity"] = product_component.component_quantity
                                product_components_list.append(
                                    product_component_map)
                            product_map["product_components_list"] = product_components_list
                            # attach product brands
                            product_brands = product.product_brands.all().order_by("-id")
                            for product_brand in product_brands:
                                product_brand_map = {}
                                product_brand_map["product_brand_id"] = str(
                                    product_brand.id)
                                product_brand_map["product_brand_name"] = product_brand.product_brand_name
                                product_brand_map["product_brand_description"] = product_brand.product_brand_description
                                product_brands_list.append(product_brand_map)
                            product_map["product_brands_list"] = product_brands_list
                            # attach product pricing
                            try:
                                product_pricing = ProductPricing.objects.get(
                                    product=product)
                                product_pricing_map["product_pricing_id"] = str(
                                    product_pricing.id)
                                product_pricing_map["product_net_price"] = product_pricing.product_net_price
                            except:
                                product_pricing_map["product_pricing_id"] = ""
                                product_pricing_map["product_net_price"] = ""
                            product_map["product_pricing_map"] = product_pricing_map
                            # attach product discount
                            try:
                                product_discount = ProductDiscount.objects.get(
                                    product=product)
                                product_discount_map["product_discount_id"] = str(
                                    product_discount.id)
                                product_discount_map["discount_type"] = product_discount.discount_type
                                product_discount_map["discount_value"] = product_discount.discount_value
                            except:
                                product_discount_map["product_discount_id"] = ""
                                product_discount_map["discount_type"] = ""
                                product_discount_map["discount_value"] = ""
                            product_map["product_discount_map"] = product_discount_map
                            # attach product vat
                            try:
                                product_vat = ProductVAT.objects.get(
                                    product=product)
                                product_vat_map["product_vat_id"] = str(
                                    product_vat.id)
                                product_vat_map["vat_percentage_value"] = product_vat.vat_percentage_value
                            except:
                                product_vat_map["product_vat_id"] = ""
                                product_vat_map["vat_percentage_value"] = ""
                            product_map["product_vat_map"] = product_vat_map
                            product_list.append(product_map)
                    category_map["product_list"] = product_list
                    category_list.append(category_map)
            for branch in all_branches:
                if branch.recycle_bin != True:
                    company_branch_map = {}
                    chart_of_account_list = []
                    expense_list = []
                    deposit_list = []
                    company_branch_map["branch_id"] = str(branch.id)
                    company_branch_map["branch_name"] = branch.branch_name
                    company_branch_map["is_main_branch"] = "true" if branch.main_branch == True else "false"
                    all_chart_of_accounts = branch.branch_chart_of_accounts.all().order_by("-id")
                    #
                    company_branch_staffs_list = []
                    branch_staffs = branch.company_branch_staffs.all().order_by('-id')
                    for staff in branch_staffs:
                        if staff.recycle_bin == False:
                            time_sheets_list = []
                            staff_leaves_list = []
                            education_qualifications_list = []
                            staff_training_records_list = []
                            staff_disciplinary_records_list = []
                            staff_deduction_schemes_list = []
                            staff_bonus_schemes_list = []
                            staff_map = {}
                            staff_map["staff_id"] = str(staff.id)
                            staff_map["email_address"] = staff.user.username
                            staff_map["staff_position"] = staff.staff_position.position_title if staff.staff_position is not None else ""
                            staff_map["staff_number"] = staff.staff_number
                            staff_map["first_name"] = staff.first_name
                            staff_map["last_name"] = staff.last_name
                            staff_map["date_of_birth"] = staff.date_of_birth if staff.date_of_birth is not None else ''
                            staff_map["country_name"] = staff.country_name
                            staff_map["identification_number"] = staff.identification_number
                            staff_map["phone_number"] = staff.phone_number
                            staff_map["staff_title"] = staff.staff_title
                            staff_map["employment_start_date"] = staff.employment_start_date if staff.employment_start_date is not None else ''
                            staff_map["employment_end_date"] = staff.employment_end_date if staff.employment_end_date is not None else ''
                            staff_map["emergency_contact_phone"] = staff.emergency_contact_phone
                            staff_map["company_branch_name"] = branch.branch_name
                            staff_map["company_department"] = staff.company_department.department_name if staff.company_department is not None else ""
                            staff_map["is_profile_set"] = "true" if staff.is_profile_set else "false"
                            staff_map["is_head_of_department"] = "true" if staff.is_head_of_department else "false"
                            staff_map["has_read_write_priviledges"] = "true" if staff.has_read_write_priviledges else "false"
                            staff_map["is_super_admin"] = "true" if staff.is_super_admin else "false"
                            staff_map["is_on_leave"] = "true" if staff.is_on_leave else "false"
                            staff_map["is_profile_active"] = "true" if staff.is_profile_active == True else "false"
                            # additional
                            staff_map["kra_pin"] = staff.kra_pin
                            staff_map["type_of_employment"] = staff.type_of_employment
                            staff_map["banking_institution_name"] = staff.banking_institution_name
                            staff_map["bank_account_name"] = staff.bank_account_name
                            staff_map["bank_account_number"] = staff.bank_account_number
                            # added bank details
                            staff_map["bank_branch_name"] = staff.bank_branch_name
                            staff_map["bank_branch_code"] = staff.bank_branch_code
                            staff_map["bank_swift_code"] = staff.bank_swift_code
                            # end
                            staff_map["nhif_number"] = staff.nhif_number
                            staff_map["nhif_additional_info"] = staff.nhif_additional_info
                            staff_map["nssf_number"] = staff.nssf_number
                            staff_map["nssf_additional_info"] = staff.nssf_additional_info
                            staff_map["staff_additional_info"] = staff.staff_additional_info
                            staff_map["personal_email"] = staff.personal_email
                            staff_map["basic_salary"] = staff.basic_salary
                            staff_map["currency"] = company_profile.company_preferred_currency
                            # end
                            time_sheets = staff.staff_time_sheets.all().order_by('-id')
                            for time_sheet in time_sheets:
                                if time_sheet.recycle_bin == False:
                                    time_sheet_map = {}
                                    time_sheet_map["time_sheet_id"] = str(
                                        time_sheet.id)
                                    time_sheet_map["check_in_time"] = datetime.strftime(
                                        time_sheet.check_in_time, date_format) if time_sheet.check_in_time is not None else ""
                                    time_sheet_map["check_out_time"] = datetime.strftime(
                                        time_sheet.check_out_time, date_format) if time_sheet.check_out_time is not None else ""
                                    time_sheet_map["created_on"] = datetime.strftime(
                                        time_sheet.created_on.astimezone(target_timezone), date_format) if time_sheet.created_on is not None else ""
                                    time_sheet_map["last_updated_on"] = datetime.strftime(
                                        time_sheet.last_updated_on.astimezone(target_timezone), date_format) if time_sheet.last_updated_on is not None else ""
                                    time_sheets_list.append(time_sheet_map)
                            staff_map["time_sheets_list"] = time_sheets_list
                            # adding extra data points
                            education_qualifications = staff.staff_education_qualifications.all().order_by('-id')
                            for education_qualification in education_qualifications:
                                education_qualification_map = {}
                                education_qualification_map["education_qualification_id"] = str(
                                    education_qualification.id)
                                education_qualification_map["qualification_title"] = education_qualification.qualification_title
                                education_qualification_map["accredition_category"] = education_qualification.accredition_category
                                education_qualification_map["accrediting_institution"] = education_qualification.accrediting_institution
                                education_qualification_map["year_of_accredition"] = education_qualification.year_of_accredition
                                education_qualification_map["created_on"] = datetime.strftime(
                                    education_qualification.created_on.astimezone(target_timezone), date_format) if education_qualification.created_on is not None else ""
                                education_qualification_map["last_updated_on"] = datetime.strftime(
                                    education_qualification.last_updated_on.astimezone(target_timezone), date_format) if education_qualification.last_updated_on is not None else ""
                                education_qualifications_list.append(
                                    education_qualification_map)
                            staff_map["education_qualifications_list"] = education_qualifications_list
                            staff_training_records = staff.staff_training_records.all().order_by('-id')
                            for staff_training_record in staff_training_records:
                                staff_training_record_map = {}
                                staff_training_record_map["training_record_id"] = str(
                                    staff_training_record.id)
                                staff_training_record_map["training_title"] = staff_training_record.training_title
                                staff_training_record_map["training_description"] = staff_training_record.training_description
                                staff_training_record_map["training_effective_from"] = datetime.strftime(
                                    staff_training_record.training_effective_from, date_format) if staff_training_record.training_effective_from is not None else ""
                                staff_training_record_map["training_effective_to"] = datetime.strftime(
                                    staff_training_record.training_effective_to, date_format) if staff_training_record.training_effective_to is not None else ""
                                staff_training_record_map["created_on"] = datetime.strftime(
                                    staff_training_record.created_on.astimezone(target_timezone), date_format) if staff_training_record.created_on is not None else ""
                                staff_training_record_map["last_updated_on"] = datetime.strftime(
                                    staff_training_record.last_updated_on.astimezone(target_timezone), date_format) if staff_training_record.last_updated_on is not None else ""
                                staff_training_records_list.append(
                                    staff_training_record_map)
                            staff_map["staff_training_records_list"] = staff_training_records_list
                            staff_disciplinary_records = staff.staff_disciplinary_records.all().order_by('-id')
                            for staff_disciplinary_record in staff_disciplinary_records:
                                staff_disciplinary_record_map = {}
                                staff_disciplinary_record_map["staff_disciplinary_record_id"] = str(
                                    staff_disciplinary_record.id)
                                staff_disciplinary_record_map[
                                    "disciplinary_incidence_title"] = staff_disciplinary_record.disciplinary_incidence_title
                                staff_disciplinary_record_map[
                                    "disciplinary_incidence_description"] = staff_disciplinary_record.disciplinary_incidence_description
                                staff_disciplinary_record_map[
                                    "disciplinary_verdict"] = staff_disciplinary_record.disciplinary_verdict
                                staff_disciplinary_record_map[
                                    "disciplinary_verdict_description"] = staff_disciplinary_record.disciplinary_verdict_description
                                staff_disciplinary_record_map[
                                    "created_on"] = datetime.strftime(
                                    staff_disciplinary_record.created_on.astimezone(target_timezone), date_format) if staff_disciplinary_record.created_on is not None else ""
                                staff_disciplinary_record_map[
                                    "last_updated_on"] = datetime.strftime(
                                    staff_disciplinary_record.last_updated_on.astimezone(target_timezone), date_format) if staff_disciplinary_record.last_updated_on is not None else ""
                                staff_disciplinary_records_list.append(
                                    staff_disciplinary_record_map)
                            staff_map["staff_disciplinary_records_list"] = staff_disciplinary_records_list
                            # end of extra data points
                            current_month_number = current_date.month
                            current_year = current_date.year
                            valid_leave_days = (current_month_number-1)*1.75
                            staff_leaves = staff.staff_leave_instances.all().order_by('-id')
                            for staff_leave in staff_leaves:
                                if staff_leave.recycle_bin == False:
                                    # compute available leave days
                                    if staff_leave.leave_hr_approval == True and staff_leave.leave_department_approval == True and (staff_leave.leave_type != "sick_leave" or staff_leave.leave_type != "maternity_leave" or staff_leave.leave_type != "paternity_leave" or staff_leave.leave_type != "medical_leave" or staff_leave.leave_type != "bereavement_leave"):
                                        valid_leave_days -= int(
                                            staff_leave.number_of_leave_days)
                                    #
                                    staff_leave_map = {}
                                    staff_leave_map["leave_id"] = str(
                                        staff_leave.id)
                                    staff_leave_map["leave_type"] = staff_leave.leave_type
                                    staff_leave_map["leave_description"] = staff_leave.leave_description
                                    staff_leave_map["leave_start_date"] = datetime.strftime(
                                        staff_leave.leave_start_date, '%d/%m/%Y') if staff_leave.leave_start_date is not None else ""
                                    staff_leave_map["leave_end_date"] = datetime.strftime(
                                        staff_leave.leave_end_date, '%d/%m/%Y') if staff_leave.leave_end_date is not None else ""
                                    # only count working days
                                    staff_leave_map["number_of_leave_days"] = staff_leave.number_of_leave_days
                                    staff_leave_map["leave_department_approval"] = staff_leave.leave_department_approval
                                    staff_leave_map["leave_hr_approval"] = staff_leave.leave_hr_approval
                                    staff_leave_map["leave_status"] = staff_leave.leave_status
                                    creator_map = {}
                                    creator_map["staff_id"] = str(
                                        staff_leave.created_by.id) if staff_leave.created_by is not None else ""
                                    creator_map["staff_name"] = f'{staff_leave.created_by.first_name} {staff_leave.created_by.last_name}' if staff_leave.created_by is not None else ""
                                    creator_map["staff_position"] = staff_leave.created_by.staff_position.position_title if staff_leave.created_by is not None else ""
                                    staff_leave_map["created_by"] = creator_map
                                    creator_map = {}
                                    creator_map["staff_id"] = str(
                                        staff_leave.last_updated_by.id) if staff_leave.last_updated_by is not None else ""
                                    creator_map["staff_name"] = f'{staff_leave.last_updated_by.first_name} {staff_leave.last_updated_by.last_name}' if staff_leave.last_updated_by is not None else ""
                                    creator_map["staff_position"] = staff_leave.last_updated_by.staff_position.position_title if staff_leave.last_updated_by is not None else ""
                                    staff_leave_map["last_updated_by"] = creator_map
                                    creator_map = {}
                                    #
                                    creator_map["staff_id"] = str(
                                        staff_leave.staff_reliever.id) if staff_leave.staff_reliever is not None else ""
                                    creator_map["staff_name"] = f'{staff_leave.staff_reliever.first_name} {staff_leave.staff_reliever.last_name}' if staff_leave.staff_reliever is not None else ""
                                    creator_map["staff_position"] = staff_leave.staff_reliever.staff_position.position_title if staff_leave.staff_reliever is not None else ""
                                    staff_leave_map["staff_reliever"] = creator_map
                                    #
                                    staff_leave_map["created_on"] = datetime.strftime(
                                        staff_leave.created_on.astimezone(target_timezone), date_format) if staff_leave.created_on is not None else ""
                                    staff_leave_map["last_updated_on"] = datetime.strftime(
                                        staff_leave.last_updated_on.astimezone(target_timezone), date_format) if staff_leave.last_updated_on is not None else ""
                                    # print(staff_leave_map)
                                    staff_leaves_list.append(staff_leave_map)
                            staff_map["staff_leaves_list"] = staff_leaves_list
                            staff_map["available_leave_days"] = str(
                                valid_leave_days) if valid_leave_days > 0 else "0"
                            staff_deduction_schemes = staff.staff_deduction_schemes.all().order_by('-id')
                            for staff_deduction_scheme in staff_deduction_schemes:
                                staff_deduction_scheme_map = {}
                                staff_deduction_scheme_map["staff_deduction_scheme_id"] = str(
                                    staff_deduction_scheme.id)
                                staff_deduction_scheme_map["deduction_id"] = str(
                                    staff_deduction_scheme.deduction.id)
                                staff_deduction_scheme_map["deduction_title"] = staff_deduction_scheme.deduction.deduction_title
                                staff_deduction_scheme_map["deduction_description"] = staff_deduction_scheme.deduction.deduction_description
                                staff_deduction_scheme_map["deduction_type"] = staff_deduction_scheme.deduction.deduction_type
                                staff_deduction_scheme_map["deduction_module"] = staff_deduction_scheme.deduction.deduction_module
                                staff_deduction_scheme_map["deduction_value"] = staff_deduction_scheme.deduction.deduction_value
                                if staff_deduction_scheme.deduction.date_effective_to >= current_date:
                                    staff_deduction_schemes_list.append(
                                        staff_deduction_scheme_map)  #
                            staff_map["staff_deduction_schemes_list"] = staff_deduction_schemes_list
                            staff_bonus_schemes = staff.staff_bonus_schemes.all().order_by('-id')
                            for staff_bonus_scheme in staff_bonus_schemes:
                                staff_bonus_scheme_map = {}
                                staff_bonus_scheme_map["staff_bonus_scheme_id"] = str(
                                    staff_bonus_scheme.id)
                                staff_bonus_scheme_map["bonus_id"] = str(
                                    staff_bonus_scheme.bonus.id)
                                staff_bonus_scheme_map["bonus_title"] = staff_bonus_scheme.bonus.bonus_title
                                staff_bonus_scheme_map["bonus_description"] = staff_bonus_scheme.bonus.bonus_description
                                staff_bonus_scheme_map["bonus_type"] = staff_bonus_scheme.bonus.bonus_type
                                staff_bonus_scheme_map["bonus_amount"] = staff_bonus_scheme.bonus.bonus_amount
                                if staff_bonus_scheme.bonus.date_effective_to >= current_date:
                                    staff_bonus_schemes_list.append(
                                        staff_bonus_scheme_map)
                            staff_map["staff_bonus_schemes_list"] = staff_bonus_schemes_list
                            staff_map["created_on"] = datetime.strftime(
                                staff.created_on.astimezone(target_timezone), date_format) if staff.created_on is not None else ""
                            staff_map["last_updated_on"] = datetime.strftime(
                                staff.last_updated_on.astimezone(target_timezone), date_format) if staff.last_updated_on is not None else ""
                            company_branch_staffs_list.append(staff_map)
                    company_branch_map["branch_staff_profiles"] = company_branch_staffs_list
                    # print(company_branch_map)
                    #
                    # customer orders
                    branch_customer_orders = branch.branch_customer_orders.all().order_by("-id")
                    customer_orders_list = []
                    for customer_order in branch_customer_orders:
                        if customer_order.recycle_bin != True:
                            customer_order_map = {}
                            customer_order_items_list = []
                            order_items_return_list = []
                            customer_order_payments_list = []
                            customer_order_map["customer_order_id"] = str(
                                customer_order.id)
                            customer_order_map["customer_order_number"] = customer_order.customer_order_number
                            customer_order_map["customer_order_type"] = customer_order.customer_order_type
                            customer_order_map["customer_order_description"] = customer_order.customer_order_description
                            customer_order_map["customer_order_total_gross_value"] = customer_order.customer_order_total_gross_value
                            customer_order_map["customer_order_total_discount"] = customer_order.customer_order_total_discount
                            customer_order_map["customer_order_total_net_value"] = customer_order.customer_order_total_net_value
                            customer_order_map["customer_order_approved"] = "true" if customer_order.customer_order_approved == True else "false"
                            customer_order_map["customer_order_fulfilled_for_transit"] = "true" if customer_order.customer_order_fulfilled_for_transit == True else "false"
                            customer_order_map["customer_ordered_delivered_to_destination"] = "true" if customer_order.customer_ordered_delivered_to_destination == True else "false"
                            customer_order_map["customer_order_picked_by_customer"] = "true" if customer_order.customer_order_picked_by_customer == True else "false"
                            customer_order_map["customer_order_cancelled_by_customer"] = "true" if customer_order.customer_order_cancelled_by_customer == True else "false"
                            customer_order_map["customer_order_cancelled_by_sales_team"] = "true" if customer_order.customer_order_cancelled_by_sales_team == True else "false"
                            customer_order_map["customer_order_total_amount_paid"] = customer_order.customer_order_total_amount_paid
                            customer_order_map["expected_delivery_date"] = customer_order.expected_delivery_date if customer_order.expected_delivery_date is not None else ""
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                customer_order.sales_person.id) if customer_order.sales_person is not None else ""
                            creator_map["staff_name"] = f'{customer_order.sales_person.first_name} {customer_order.sales_person.last_name}' if customer_order.sales_person is not None else ""
                            creator_map["staff_position"] = customer_order.sales_person.staff_position.position_title if customer_order.sales_person.staff_position is not None else ""
                            customer_order_map["sales_person"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                customer_order.created_by.id) if customer_order.created_by is not None else ""
                            creator_map["staff_name"] = f'{customer_order.created_by.first_name} {customer_order.created_by.last_name}' if customer_order.created_by is not None else ""
                            creator_map["staff_position"] = customer_order.created_by.staff_position.position_title if customer_order.created_by.staff_position is not None else ""
                            customer_order_map["created_by"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                customer_order.last_updated_by.id) if customer_order.last_updated_by is not None else ""
                            creator_map["staff_name"] = f'{customer_order.last_updated_by.first_name} {customer_order.last_updated_by.last_name}' if customer_order.last_updated_by is not None else ""
                            creator_map["staff_position"] = customer_order.last_updated_by.staff_position.position_title if customer_order.last_updated_by.staff_position is not None else ""
                            customer_order_map["last_updated_by"] = creator_map
                            customer_map = {}
                            customer_map["customer_profile_id"] = str(
                                customer_order.customer_profile.id) if customer_order.customer_profile is not None else ""
                            customer_map["customer_name"] = f"{customer_order.customer_profile.customer_first_name} {customer_order.customer_profile.customer_last_name}" if customer_order.customer_profile is not None else ""
                            customer_map["company_name"] = customer_order.customer_profile.company_name if customer_order.customer_profile is not None else ""
                            customer_map["customer_type"] = customer_order.customer_profile.customer_type if customer_order.customer_profile is not None else ""
                            customer_map["email_address"] = customer_order.customer_profile.email_address if customer_order.customer_profile is not None else ""
                            customer_map["phone_number"] = customer_order.customer_profile.phone_number if customer_order.customer_profile is not None else ""
                            customer_order_map["customer_map"] = customer_map
                            customer_order_map["created_on"] = datetime.strftime(
                                customer_order.created_on.astimezone(target_timezone), date_format) if customer_order.created_on is not None else ""
                            customer_order_map["last_updated_on"] = datetime.strftime(
                                customer_order.last_updated_on.astimezone(target_timezone), date_format) if customer_order.last_updated_on is not None else ""
                            customer_order_items = customer_order.customer_order_items.all().order_by("-id")
                            for customer_order_item in customer_order_items:
                                customer_order_item_map = {}
                                customer_order_item_map["customer_order_item_id"] = str(
                                    customer_order_item.id)
                                customer_order_item_map["product_id"] = str(
                                    customer_order_item.product.id)
                                customer_order_item_map["product_name"] = customer_order_item.product.product_name
                                customer_order_item_map["quantity"] = customer_order_item.quantity
                                customer_order_item_map["price_per_item"] = customer_order_item.price_per_item
                                customer_order_item_map["discount_per_item"] = customer_order_item.discount_per_item
                                customer_order_item_map["gross_subtotal"] = customer_order_item.gross_subtotal
                                customer_order_item_map["total_discount"] = customer_order_item.total_discount
                                customer_order_item_map["net_subtotal"] = customer_order_item.net_subtotal
                                customer_order_item_map["sales_item_order_fulfilled"] = "true" if customer_order_item.sales_item_order_fulfilled == True else "false"
                                customer_order_items_list.append(
                                    customer_order_item_map)
                            customer_order_map["customer_order_items_list"] = customer_order_items_list
                            # attach sales order to customer_order
                            try:
                                sales_order = SalesOrder.objects.get(
                                    customer_order=customer_order)
                                sales_order_map = {}
                                sales_order_items_list = []
                                sales_order_map["sales_order_id"] = str(
                                    sales_order.id)
                                sales_order_map["sales_order_number"] = sales_order.sales_order_number
                                sales_order_map["sale_outlet_id"] = str(
                                    sales_order.sale_outlet.id) if sales_order.sale_outlet is not None else ""
                                sales_order_map["sale_outlet_name"] = sales_order.sale_outlet.sale_outlet_name if sales_order.sale_outlet is not None else ""
                                sales_order_map["warehouse_id"] = str(
                                    sales_order.warehouse.id) if sales_order.warehouse is not None else ""
                                sales_order_map["warehouse_name"] = sales_order.warehouse.warehouse_name if sales_order.warehouse is not None else ""
                                sales_order_map["sales_order_description"] = sales_order.sales_order_description
                                sales_order_map["sales_order_approved"] = "true" if sales_order.sales_order_approved == True else "false"
                                sales_order_map["sales_order_fulfilled"] = "true" if sales_order.sales_order_fulfilled == True else "false"
                                creator_map = {}
                                creator_map["staff_id"] = str(
                                    sales_order.created_by.id) if sales_order.created_by is not None else ""
                                creator_map["staff_name"] = f'{sales_order.created_by.first_name} {sales_order.created_by.last_name}' if sales_order.created_by is not None else ""
                                creator_map["staff_position"] = sales_order.created_by.staff_position.position_title if sales_order.created_by.staff_position is not None else ""
                                sales_order_map["created_by"] = creator_map
                                creator_map = {}
                                creator_map["staff_id"] = str(
                                    sales_order.last_updated_by.id) if sales_order.last_updated_by is not None else ""
                                creator_map["staff_name"] = f'{sales_order.last_updated_by.first_name} {sales_order.last_updated_by.last_name}' if sales_order.last_updated_by is not None else ""
                                creator_map["staff_position"] = sales_order.last_updated_by.staff_position.position_title if sales_order.last_updated_by.staff_position is not None else ""
                                sales_order_map["last_updated_by"] = creator_map
                                sales_order_map["created_on"] = datetime.strftime(
                                    sales_order.created_on.astimezone(target_timezone), date_format) if sales_order.created_on is not None else ""
                                sales_order_map["last_updated_on"] = datetime.strftime(
                                    sales_order.last_updated_on.astimezone(target_timezone), date_format) if sales_order.last_updated_on is not None else ""
                                # attach sales order items
                                sales_order_sales_items = sales_order.sales_order_sales_items.all().order_by("-id")
                                for sales_order_item in sales_order_sales_items:
                                    sales_order_item_map = {}
                                    sales_order_item_map["sales_order_item_id"] = str(
                                        sales_order_item.id)
                                    sales_order_item_map["inventory_id"] = str(
                                        sales_order_item.inventory.id) if sales_order_item.inventory is not None else ""
                                    sales_order_item_map["quantity"] = sales_order_item.quantity
                                    sales_order_item_map["sales_item_order_fulfilled"] = "true" if sales_order_item.sales_item_order_fulfilled == True else "false"
                                    sales_order_items_list.append(
                                        sales_order_item_map)
                                sales_order_map["sales_order_items_list"] = sales_order_items_list
                                customer_order_map["sales_order_map"] = sales_order_map

                            except:
                                sales_order_map = {}
                                sales_order_map["sales_order_id"] = ""
                                sales_order_map["sales_order_number"] = ""
                                sales_order_map["sale_outlet_id"] = ""
                                sales_order_map["sale_outlet_name"] = ""
                                sales_order_map["warehouse_id"] = ""
                                sales_order_map["warehouse_name"] = ""
                                sales_order_map["sales_order_description"] = ""
                                sales_order_map["sales_order_approved"] = ""
                                sales_order_map["sales_order_fulfilled"] = ""
                                creator_map = {}
                                creator_map["staff_id"] = ""
                                creator_map["staff_name"] = ""
                                creator_map["staff_position"] = ""
                                sales_order_map["created_by"] = creator_map
                                creator_map = {}
                                creator_map["staff_id"] = ""
                                creator_map["staff_name"] = ""
                                creator_map["staff_position"] = ""
                                sales_order_map["last_updated_by"] = creator_map
                                sales_order_map["created_on"] = ""
                                sales_order_map["last_updated_on"] = ""
                                sales_order_map["sales_order_items_list"] = []
                                customer_order_map["sales_order_map"] = sales_order_map
                            # add customer order invoice
                            try:
                                customer_order_invoice = CustomerOrderInvoice.objects.get(
                                    customer_order=customer_order)
                                customer_order_invoice_map = {}
                                customer_order_invoice_map["customer_order_invoice_id"] = str(
                                    customer_order_invoice.id)
                                customer_order_invoice_map["customer_order_number"] = customer_order_invoice.customer_order.customer_order_number
                                customer_order_invoice_map["customer_order_invoice_number"] = customer_order_invoice.invoice_number
                                customer_order_invoice_map["customer_order_invoice_amount_due"] = customer_order_invoice.invoice_amount_due
                                customer_order_invoice_map["customer_order_invoice_amount_paid"] = customer_order_invoice.invoice_amount_paid
                                customer_order_invoice_map["customer_order_invoice_currency"] = customer_order_invoice.invoice_currency
                                customer_order_invoice_map["customer_order_invoice_settled"] = "true" if customer_order_invoice.invoice_settled == True else "false"
                                customer_order_invoice_map["created_on"] = datetime.strftime(
                                    customer_order_invoice.created_on.astimezone(target_timezone), date_format) if customer_order_invoice.created_on is not None else ""
                                customer_order_invoice_map["last_updated_on"] = datetime.strftime(
                                    customer_order_invoice.last_updated_on.astimezone(target_timezone), date_format) if customer_order_invoice.last_updated_on is not None else ""
                                creator_map = {}
                                creator_map["staff_id"] = str(
                                    customer_order_invoice.created_by.id) if customer_order_invoice.created_by is not None else ""
                                creator_map["staff_name"] = f'{customer_order_invoice.created_by.first_name} {customer_order_invoice.created_by.last_name}' if customer_order_invoice.created_by is not None else ""
                                creator_map["staff_position"] = customer_order_invoice.created_by.staff_position.position_title if customer_order_invoice.created_by.staff_position is not None else ""
                                customer_order_invoice_map["created_by"] = creator_map
                                creator_map = {}
                                creator_map["staff_id"] = str(
                                    customer_order_invoice.last_updated_by.id) if customer_order_invoice.last_updated_by is not None else ""
                                creator_map["staff_name"] = f'{customer_order_invoice.last_updated_by.first_name} {customer_order_invoice.last_updated_by.last_name}' if customer_order_invoice.last_updated_by is not None else ""
                                creator_map["staff_position"] = customer_order_invoice.last_updated_by.staff_position.position_title if customer_order_invoice.last_updated_by.staff_position is not None else ""
                                customer_order_invoice_map["last_updated_by"] = creator_map
                                customer_order_map["customer_order_invoice"] = customer_order_invoice_map
                            except:  # Exception as e:
                                # print(e)
                                customer_order_invoice_map = {}
                                customer_order_invoice_map["customer_order_invoice_id"] = ""
                                customer_order_invoice_map["customer_order_number"] = ""
                                customer_order_invoice_map["customer_order_invoice_number"] = ""
                                customer_order_invoice_map["customer_order_invoice_amount_due"] = ""
                                customer_order_invoice_map["customer_order_invoice_amount_paid"] = ""
                                customer_order_invoice_map["customer_order_invoice_currency"] = ""
                                customer_order_invoice_map["customer_order_invoice_settled"] = ""
                                customer_order_invoice_map["created_on"] = ""
                                customer_order_invoice_map["last_updated_on"] = ""
                                creator_map = {}
                                creator_map["staff_id"] = ""
                                creator_map["staff_name"] = ""
                                creator_map["staff_position"] = ""
                                customer_order_invoice_map["created_by"] = creator_map
                                creator_map = {}
                                creator_map["staff_id"] = ""
                                creator_map["staff_name"] = ""
                                creator_map["staff_position"] = ""
                                customer_order_invoice_map["last_updated_by"] = creator_map
                                customer_order_map["customer_order_invoice"] = customer_order_invoice_map

                            # attach order item returns
                            customer_order_items_return = customer_order.customer_order_items_return.all().order_by("-id")
                            for order_item_return in customer_order_items_return:
                                if order_item_return.recycle_bin != True:
                                    order_item_return_map = {}
                                    return_items_list = []
                                    order_item_return_map["order_item_return_id"] = str(
                                        order_item_return.id)
                                    order_item_return_map["refund_requested"] = "true" if order_item_return.refund_requested == True else "false"
                                    order_item_return_map["date_of_return"] = order_item_return.date_of_return if order_item_return.date_of_return is not None else ""
                                    order_item_return_map["created_on"] = datetime.strftime(
                                        order_item_return.created_on.astimezone(target_timezone), date_format) if order_item_return.created_on is not None else ""
                                    order_item_return_map["last_updated_on"] = datetime.strftime(
                                        order_item_return.last_updated_on.astimezone(target_timezone), date_format) if order_item_return.last_updated_on is not None else ""
                                    order_items_return = order_item_return.order_items_return
                                    for item_return in order_items_return:
                                        return_item_map = {}
                                        return_item_map["item_return_id"] = str(
                                            item_return.id)
                                        return_item_map["customer_order_item_id"] = str(
                                            item_return.ordered_item_returned.id) if item_return.ordered_item_returned is not None else ""
                                        return_item_map["reason_for_return"] = item_return.reason_for_return
                                        return_items_list.append(
                                            return_item_map)
                                    order_item_return_map["return_items_list"] = return_items_list
                                    order_items_return_list.append(
                                        order_item_return_map)
                            customer_order_map["order_items_return_list"] = order_items_return_list
                            # attach customer order payments
                            customer_order_payments = customer_order.customer_order_payments.all().order_by("-id")
                            for order_payment in customer_order_payments:
                                if order_payment.recycle_bin != True:
                                    customer_order_payment_map = {}
                                    refunds_list = []
                                    customer_order_payment_map["customer_order_payment_id"] = str(
                                        order_payment.id)
                                    customer_order_payment_map["payment_number"] = order_payment.payment_number
                                    customer_order_payment_map["payment_amount"] = order_payment.payment_amount
                                    customer_order_payment_map["payment_method"] = order_payment.payment_method
                                    customer_order_payment_map["payer_account_number"] = order_payment.payer_account_number
                                    customer_order_payment_map["account_paid_to"] = order_payment.account_paid_to.account_number if order_payment.account_paid_to is not None else ""
                                    customer_order_payment_map["currency"] = order_payment.account_paid_to.account_currency if order_payment.account_paid_to is not None else ""
                                    creator_map = {}
                                    creator_map["staff_id"] = str(
                                        order_payment.created_by.id) if order_payment.created_by is not None else ""
                                    creator_map["staff_name"] = f'{order_payment.created_by.first_name} {order_payment.created_by.last_name}' if order_payment.created_by is not None else ""
                                    creator_map["staff_position"] = order_payment.created_by.staff_position.position_title if order_payment.created_by.staff_position is not None else ""
                                    customer_order_payment_map["created_by"] = creator_map
                                    creator_map = {}
                                    creator_map["staff_id"] = str(
                                        order_payment.last_updated_by.id) if order_payment.last_updated_by is not None else ""
                                    creator_map["staff_name"] = f'{order_payment.last_updated_by.first_name} {order_payment.last_updated_by.last_name}' if order_payment.last_updated_by is not None else ""
                                    creator_map["staff_position"] = order_payment.last_updated_by.staff_position.position_title if order_payment.last_updated_by.staff_position is not None else ""
                                    customer_order_payment_map["last_updated_by"] = creator_map
                                    customer_order_payment_map["created_on"] = datetime.strftime(
                                        order_payment.created_on.astimezone(target_timezone), date_format) if order_payment.created_on is not None else ""
                                    customer_order_payment_map["last_updated_on"] = datetime.strftime(
                                        order_payment.last_updated_on.astimezone(target_timezone), date_format) if order_payment.last_updated_on is not None else ""
                                    # attach refunds
                                    payment_refunds = order_payment.payment_refunds.all().order_by("-id")
                                    for refund in payment_refunds:
                                        if refund.recycle_bin != True:
                                            refund_map = {}
                                            refund_map["refund_id"] = str(
                                                refund.id)
                                            refund_map["order_item_return_id"] = str(
                                                refund.order_item_return.id) if refund.order_item_return is not None else ""
                                            refund_map["refund_amount"] = refund.refund_amount
                                            refund_map["refund_approved"] = "true" if refund.refund_approved == True else "false"
                                            refund_map["refund_fullfilled"] = "true" if refund.refund_fullfilled == True else "false"
                                            creator_map = {}
                                            creator_map["staff_id"] = str(
                                                refund.created_by.id) if refund.created_by is not None else ""
                                            creator_map["staff_name"] = f'{refund.created_by.first_name} {refund.created_by.last_name}' if refund.created_by is not None else ""
                                            creator_map["staff_position"] = refund.created_by.staff_position.position_title if refund.created_by.staff_position is not None else ""
                                            refund_map["created_by"] = creator_map
                                            creator_map = {}
                                            creator_map["staff_id"] = str(
                                                refund.last_updated_by.id) if refund.last_updated_by is not None else ""
                                            creator_map["staff_name"] = f'{refund.last_updated_by.first_name} {refund.last_updated_by.last_name}' if refund.last_updated_by is not None else ""
                                            creator_map["staff_position"] = refund.last_updated_by.staff_position.position_title if refund.last_updated_by.staff_position is not None else ""
                                            refund_map["last_updated_by"] = creator_map
                                            refund_map["created_on"] = datetime.strftime(
                                                refund.created_on.astimezone(target_timezone), date_format) if refund.created_on is not None else ""
                                            refund_map["last_updated_on"] = datetime.strftime(
                                                refund.last_updated_on.astimezone(target_timezone), date_format) if refund.last_updated_on is not None else ""
                                            refunds_list.append(refund_map)
                                    customer_order_payment_map["refunds_list"] = refunds_list
                                    customer_order_payments_list.append(
                                        customer_order_payment_map)
                            customer_order_map["customer_order_payments_list"] = customer_order_payments_list
                            customer_orders_list.append(customer_order_map)
                    company_branch_map["customer_orders_list"] = customer_orders_list
                    # end of customer orders
                    for account in all_chart_of_accounts:
                        if account.recycle_bin != True:
                            chart_of_account_map = {}
                            chart_of_account_map["account_id"] = str(
                                account.id)
                            chart_of_account_map["account_name"] = account.account_name
                            chart_of_account_map["account_number"] = account.account_number
                            chart_of_account_map["account_descriptions"] = account.account_descriptions
                            chart_of_account_map["banking_institution_name"] = account.banking_institution_name
                            chart_of_account_map["bank_branch_name"] = account.bank_branch_name
                            chart_of_account_map["bank_branch_code"] = account.bank_branch_code
                            chart_of_account_map["bank_swift_code"] = account.bank_swift_code
                            chart_of_account_map["bank_sort_code"] = account.bank_sort_code
                            chart_of_account_map["is_mpesa_account"] = "true" if account.is_mpesa_account == True else "false"
                            # chart_of_account_map["running_balance"] = account.running_balance
                            chart_of_account_map["account_currency"] = account.account_currency
                            chart_of_account_map["running_balance"] = account.running_balance
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                account.created_by.id) if account.created_by is not None else ""
                            creator_map["staff_name"] = f'{account.created_by.first_name} {account.created_by.last_name}' if account.created_by is not None else ""
                            creator_map["staff_position"] = account.created_by.staff_position.position_title if account.created_by.staff_position is not None else ""
                            chart_of_account_map["created_by"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                account.last_updated_by.id) if account.last_updated_by is not None else ""
                            creator_map["staff_name"] = f'{account.last_updated_by.first_name} {account.last_updated_by.last_name}' if account.last_updated_by is not None else ""
                            creator_map["staff_position"] = account.last_updated_by.staff_position.position_title if account.last_updated_by.staff_position is not None else ""
                            chart_of_account_map["last_updated_by"] = creator_map
                            chart_of_account_map["created_on"] = datetime.strftime(
                                account.created_on.astimezone(target_timezone), date_format) if account.created_on is not None else ""
                            chart_of_account_map["last_updated_on"] = datetime.strftime(
                                account.last_updated_on.astimezone(target_timezone), date_format) if account.last_updated_on is not None else ""
                            account_transactions = account.account_transactions.all().order_by("-id")
                            account_transactions_list = []
                            for account_transaction in account_transactions:
                                account_transactions_map = {}
                                account_transactions_map["account_transaction_id"] = str(
                                    account_transaction.id)
                                account_transactions_map["transaction_amount"] = account_transaction.transaction_amount
                                account_transactions_list.append(
                                    account_transactions_map)
                            chart_of_account_map["account_transactions_list"] = account_transactions_list
                            chart_of_account_list.append(chart_of_account_map)
                    company_branch_map["chart_of_account_list"] = chart_of_account_list
                    all_expenses = branch.branch_expenses.all().order_by("-id")
                    for expense in all_expenses:
                        expense_map = {}
                        expense_map["expense_id"] = str(expense.id)
                        expense_map["expense_number"] = expense.expense_number
                        expense_map["expense_title"] = expense.expense_title
                        expense_map["expense_description"] = expense.expense_description
                        expense_map["expense_type"] = expense.expense_type
                        expense_map["payroll_sheet_id"] = str(
                            expense.payroll_sheet.id) if expense.payroll_sheet is not None else ""
                        # expense_map["purchase_order_id"] = str(
                        #     expense.purchase_order.id) if expense.purchase_order is not None else ""
                        product_purchase_expenses = expense.product_purchase_instance.all()
                        purchase_expense_list = []
                        for purchase_expense in product_purchase_expenses:
                            if purchase_expense.recycle_bin != True:
                                purchase_expense_map = {}
                                purchase_expense_map["purchase_expense_id"] = str(
                                    purchase_expense.id)
                                purchase_expense_map["product_purchase_instance_id"] = str(
                                    purchase_expense.id)
                                purchase_expense_map["purchase_value_per_unit"] = purchase_expense.purchase_value_per_unit
                                purchase_expense_map["purchase_value_overall"] = purchase_expense.purchase_value_overall
                                purchase_expense_map["purchase_amount_paid_to_supplier"] = purchase_expense.purchase_amount_paid_to_supplier
                                purchase_expense_map["supplier_payment_settled"] = "true" if purchase_expense.supplier_payment_settled == True else "false"
                                purchase_expense_map["supplier_id"] = str(
                                    purchase_expense.supplier.id)
                                purchase_expense_map["purchase_order_id"] = str(
                                    purchase_expense.purchase_order.id)
                                purchase_expense_map["purchase_order_number"] = purchase_expense.purchase_order.purchase_order_number
                                purchase_expense_list.append(
                                    purchase_expense_map)
                        expense_map["purchase_expense_list"] = purchase_expense_list

                        expense_map["refund_id"] = str(
                            expense.refund.id) if expense.refund is not None else ""
                        expense_map["expense_amount"] = expense.expense_amount
                        try:
                            expense_map["expense_transaction_id"] = str(
                                Transaction.objects.get(expense=expense).id)
                        except:
                            expense_map["expense_transaction_id"] = ""
                        # expense_map["expense_transaction_id"] = str(
                        #     expense.expense_transaction.id) if expense.expense_transaction is not None else ""
                        expense_map["expense_settled"] = "true" if expense.expense_settled == True else "false"
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            expense.created_by.id) if expense.created_by is not None else ""
                        creator_map["staff_name"] = f'{expense.created_by.first_name} {expense.created_by.last_name}' if expense.created_by is not None else ""
                        creator_map["staff_position"] = expense.created_by.staff_position.position_title if expense.created_by.staff_position is not None else ""
                        expense_map["created_by"] = creator_map
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            expense.last_updated_by.id) if expense.last_updated_by is not None else ""
                        creator_map["staff_name"] = f'{expense.last_updated_by.first_name} {expense.last_updated_by.last_name}' if expense.last_updated_by is not None else ""
                        creator_map["staff_position"] = expense.last_updated_by.staff_position.position_title if expense.last_updated_by.staff_position is not None else ""
                        expense_map["last_updated_by"] = creator_map
                        # expense approved
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            expense.last_updated_by.id) if expense.expense_approved_by is not None else ""
                        creator_map["staff_name"] = f'{expense.expense_approved_by.first_name} {expense.expense_approved_by.last_name}' if expense.expense_approved_by is not None else ""
                        creator_map["staff_position"] = expense.expense_approved_by.staff_position.position_title if expense.expense_approved_by.staff_position is not None else ""
                        expense_map["expense_approved_by"] = creator_map
                        #
                        expense_map["created_on"] = datetime.strftime(
                            expense.created_on.astimezone(target_timezone), date_format) if expense.created_on is not None else ""
                        expense_map["last_updated_on"] = datetime.strftime(
                            expense.last_updated_on.astimezone(target_timezone), date_format) if expense.last_updated_on is not None else ""
                        expense_list.append(expense_map)
                    company_branch_map["expense_list"] = expense_list
                    all_deposits = branch.branch_deposits.all().order_by("-id")
                    for deposit in all_deposits:
                        deposit_map = {}
                        deposit_map["deposit_id"] = str(deposit.id)
                        deposit_map["deposit_number"] = deposit.deposit_number
                        deposit_map["deposit_source"] = deposit.deposit_source
                        deposit_map["deposit_amount"] = deposit.deposit_amount
                        deposit_map["order_payment_reference"] = deposit.order_payment_reference
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            deposit.created_by.id) if deposit.created_by is not None else ""
                        creator_map["staff_name"] = f'{deposit.created_by.first_name} {deposit.created_by.last_name}' if deposit.created_by is not None else ""
                        creator_map["staff_position"] = deposit.created_by.staff_position.position_title if deposit.created_by.staff_position is not None else ""
                        deposit_map["created_by"] = creator_map
                        creator_map = {}
                        creator_map["staff_id"] = str(
                            deposit.last_updated_by.id) if deposit.last_updated_by is not None else ""
                        creator_map["staff_name"] = f'{deposit.last_updated_by.first_name} {deposit.last_updated_by.last_name}' if deposit.last_updated_by is not None else ""
                        creator_map["staff_position"] = deposit.last_updated_by.staff_position.position_title if deposit.last_updated_by.staff_position is not None else ""
                        deposit_map["last_updated_by"] = creator_map
                        deposit_map["created_on"] = datetime.strftime(
                            deposit.created_on.astimezone(target_timezone), date_format) if deposit.created_on is not None else ""
                        deposit_map["last_updated_on"] = datetime.strftime(
                            deposit.last_updated_on.astimezone(target_timezone), date_format) if deposit.last_updated_on is not None else ""
                        deposit_list.append(deposit_map)
                    company_branch_map["deposit_list"] = deposit_list
                    # payroll sheets
                    payroll_sheets_list = []
                    payroll_sheets = branch.branch_payroll_sheets.all().order_by('-id')
                    for payroll_sheet in payroll_sheets:
                        if payroll_sheet.recycle_bin == False:
                            payroll_sheet_map = {}
                            payroll_sheet_map["payroll_sheet_id"] = str(
                                payroll_sheet.id)
                            payroll_sheet_map["payroll_sheet_title"] = payroll_sheet.payroll_sheet_title
                            payroll_sheet_map["payroll_sheet_number"] = payroll_sheet.payroll_sheet_number
                            payroll_sheet_map["payroll_sheet_description"] = payroll_sheet.payroll_sheet_description
                            payroll_sheet_map["payroll_sheet_for_the_month_of"] = payroll_sheet.payroll_sheet_for_the_month_of
                            payroll_sheet_map["payroll_sheet_for_the_year"] = payroll_sheet.payroll_sheet_for_the_year
                            payroll_sheet_map["payroll_sheet_value"] = payroll_sheet.payroll_sheet_value
                            # added
                            payroll_sheet_map["payroll_sheet_total_net_pay_value"] = payroll_sheet.payroll_sheet_total_net_pay_value
                            payroll_sheet_map["payroll_sheet_total_bonus_value"] = payroll_sheet.payroll_sheet_total_bonus_value
                            payroll_sheet_map["payroll_sheet_total_deduction_value"] = payroll_sheet.payroll_sheet_total_deduction_value
                            payroll_sheet_map["payroll_sheet_total_commission_value"] = payroll_sheet.payroll_sheet_total_commission_value
                            payroll_sheet_map["payroll_sheet_approved_by_system_administrator"] = "true" if payroll_sheet.payroll_sheet_approved_by_system_administrator == True else "false"
                            payroll_sheet_map["is_terminal_dues"] = "true" if payroll_sheet.is_terminal_dues == True else "false"
                            payroll_sheet_map["currency"] = company_profile.company_preferred_currency
                            # end added
                            payroll_sheet_map["payroll_sheet_approved_by_finance"] = "true" if payroll_sheet.payroll_sheet_approved_by_finance == True else "false"
                            payroll_sheet_map["payroll_sheet_payment_settled"] = "true" if payroll_sheet.payroll_sheet_payment_settled == True else "false"
                            staff_map = {}
                            staff_map["staff_id"] = str(
                                payroll_sheet.created_by.id) if payroll_sheet.created_by is not None else ""
                            staff_map["staff_name"] = f'{payroll_sheet.created_by.first_name} {payroll_sheet.created_by.last_name}' if payroll_sheet.created_by is not None else ""
                            staff_map["staff_position"] = payroll_sheet.created_by.staff_position.position_title if payroll_sheet.created_by.staff_position is not None else ""
                            payroll_sheet_map["created_by"] = staff_map
                            staff_map = {}
                            staff_map["staff_id"] = str(
                                payroll_sheet.last_updated_by.id) if payroll_sheet.last_updated_by is not None else ""
                            staff_map["staff_name"] = f'{payroll_sheet.last_updated_by.first_name} {payroll_sheet.last_updated_by.last_name}' if payroll_sheet.last_updated_by is not None else ""
                            staff_map["staff_position"] = payroll_sheet.last_updated_by.staff_position.position_title if payroll_sheet.last_updated_by.staff_position is not None else ""
                            payroll_sheet_map["last_updated_by"] = staff_map
                            payroll_sheet_map["created_on"] = datetime.strftime(
                                payroll_sheet.created_on.astimezone(target_timezone), date_format) if payroll_sheet.created_on is not None else ""
                            payroll_sheet_map["last_updated_on"] = datetime.strftime(
                                payroll_sheet.last_updated_on.astimezone(target_timezone), date_format) if payroll_sheet.last_updated_on is not None else ""
                            payroll_instances_list = []
                            payroll_instances = payroll_sheet.staff_payroll_items.all().order_by('-id')
                            for payroll_instance in payroll_instances:
                                if payroll_instance.recycle_bin == False:
                                    payroll_instance_map = {}
                                    payroll_instance_map["payroll_instance_id"] = str(
                                        payroll_instance.id)
                                    payroll_instance_map["staff_id"] = str(
                                        payroll_instance.staff_profile.id)
                                    deduction_instances = payroll_instance.deduction_instance.all().order_by('-id')
                                    deduction_instances_list = []
                                    for deduction_instance in deduction_instances:
                                        if deduction_instance.recycle_bin == False:
                                            deduction_instance_map = {}
                                            deduction_instance_map["deduction_instance_id"] = str(
                                                deduction_instance.id)
                                            deduction_instance_map["deduction_id"] = str(
                                                deduction_instance.deduction.id) if deduction_instance.deduction is not None else ""
                                            deduction_instance_map["deduction_title"] = deduction_instance.deduction.deduction_title
                                            deduction_instance_map["deduction_instance_value"] = deduction_instance.deduction_instance_value
                                            staff_map = {}
                                            staff_map["staff_id"] = str(
                                                deduction_instance.created_by.id) if deduction_instance.created_by is not None else ""
                                            staff_map["staff_name"] = f'{deduction_instance.created_by.first_name} {deduction_instance.created_by.last_name}' if deduction_instance.created_by is not None else ""
                                            staff_map["staff_position"] = deduction_instance.created_by.staff_position.position_title if deduction_instance.created_by.staff_position is not None else ""
                                            deduction_instance_map["created_by"] = staff_map
                                            staff_map = {}
                                            staff_map["staff_id"] = str(
                                                deduction_instance.last_updated_by.id) if deduction_instance.last_updated_by is not None else ""
                                            staff_map["staff_name"] = f'{deduction_instance.last_updated_by.first_name} {deduction_instance.last_updated_by.last_name}' if deduction_instance.last_updated_by is not None else ""
                                            staff_map["staff_position"] = deduction_instance.last_updated_by.staff_position.position_title if deduction_instance.last_updated_by.staff_position is not None else ""
                                            deduction_instance_map["last_updated_by"] = staff_map
                                            deduction_instance_map["created_on"] = datetime.strftime(
                                                deduction_instance.created_on.astimezone(target_timezone), date_format) if deduction_instance.created_on is not None else ""
                                            deduction_instance_map["last_updated_on"] = datetime.strftime(
                                                deduction_instance.last_updated_on.astimezone(target_timezone), date_format) if deduction_instance.last_updated_on is not None else ""
                                            deduction_instances_list.append(
                                                deduction_instance_map)
                                    payroll_instance_map["deduction_instances_list"] = deduction_instances_list
                                    payroll_instance_map["gross_salary"] = payroll_instance.gross_salary
                                    bonus_instances = payroll_instance.bonus_instance.all().order_by('-id')
                                    bonus_instances_list = []
                                    for bonus_instance in bonus_instances:
                                        if bonus_instance.recycle_bin == False:
                                            bonus_instance_map = {}
                                            bonus_instance_map["bonus_instance_id"] = str(
                                                bonus_instance.id)
                                            bonus_instance_map["bonus_id"] = str(
                                                bonus_instance.bonus.id) if bonus_instance.bonus is not None else ""
                                            bonus_instance_map["bonus_instance_value"] = bonus_instance.bonus_instance_value
                                            bonus_instance_map["bonus_title"] = bonus_instance.bonus.bonus_title
                                            staff_map = {}
                                            staff_map["staff_id"] = str(
                                                bonus_instance.created_by.id) if bonus_instance.created_by is not None else ""
                                            staff_map["staff_name"] = f'{bonus_instance.created_by.first_name} {bonus_instance.created_by.last_name}' if bonus_instance.created_by is not None else ""
                                            staff_map["staff_position"] = bonus_instance.created_by.staff_position.position_title if bonus_instance.created_by.staff_position is not None else ""
                                            bonus_instance_map["created_by"] = staff_map
                                            staff_map = {}
                                            staff_map["staff_id"] = str(
                                                bonus_instance.last_updated_by.id) if bonus_instance.last_updated_by is not None else ""
                                            staff_map["staff_name"] = f'{bonus_instance.last_updated_by.first_name} {bonus_instance.last_updated_by.last_name}' if bonus_instance.last_updated_by is not None else ""
                                            staff_map["staff_position"] = bonus_instance.last_updated_by.staff_position.position_title if bonus_instance.last_updated_by.staff_position is not None else ""
                                            bonus_instance_map["last_updated_by"] = staff_map
                                            bonus_instance_map["created_on"] = datetime.strftime(
                                                bonus_instance.created_on.astimezone(target_timezone), date_format) if deduction_instance.created_on is not None else ""
                                            bonus_instance_map["last_updated_on"] = datetime.strftime(
                                                bonus_instance.last_updated_on.astimezone(target_timezone), date_format) if bonus_instance.last_updated_on is not None else ""
                                            bonus_instances_list.append(
                                                bonus_instance_map)
                                    payroll_instance_map["bonus_instances_list"] = bonus_instances_list
                                    payroll_instance_map["net_salary"] = payroll_instance.net_salary
                                    #
                                    payroll_instance_commissions = payroll_instance.staff_payroll_instance_commissions.all()
                                    payroll_instance_commissions_list = []
                                    for commission_sheet_instance in payroll_instance_commissions:
                                        if commission_sheet_instance.recycle_bin == False:
                                            commission_sheet_instance_map = {}
                                            commission_sheet_instance_map["commission_sheet_instance_id"] = str(
                                                commission_sheet_instance.id)
                                            commission_sheet_instance_map["customer_order_id"] = str(
                                                commission_sheet_instance.customer_order.id) if commission_sheet_instance.customer_order is not None else ""
                                            commission_sheet_instance_map[
                                                "commission_value"] = commission_sheet_instance.commission_value
                                            commission_sheet_instance_map[
                                                "commission_sheet_id"] = str(commission_sheet_instance.commission_sheet.id) if commission_sheet_instance.commission_sheet is not None else ""
                                            commission_sheet_instance_map[
                                                "commission_sheet_number"] = commission_sheet_instance.commission_sheet.commission_sheet_number if commission_sheet_instance.commission_sheet is not None else ""
                                            commission_sheet_instance_map[
                                                "commission_sheet_title"] = commission_sheet_instance.commission_sheet.commission_sheet_title if commission_sheet_instance.commission_sheet is not None else ""
                                            payroll_instance_commissions_list.append(
                                                commission_sheet_instance_map)
                                    payroll_instance_map["payroll_instance_commissions_list"] = payroll_instance_commissions_list
                                    payroll_instance_map["commissions_total"] = payroll_instance.commissions_total
                                    payroll_instance_map["is_prorated"] = "true" if payroll_instance.is_prorated == True else "false"
                                    payroll_instance_map["pro_rate_factor"] = payroll_instance.pro_rate_factor
                                    #
                                    staff_map = {}
                                    staff_map["staff_id"] = str(
                                        payroll_instance.created_by.id) if payroll_instance.created_by is not None else ""
                                    staff_map["staff_name"] = f'{payroll_instance.created_by.first_name} {payroll_instance.created_by.last_name}' if payroll_instance.created_by is not None else ""
                                    staff_map["staff_position"] = payroll_instance.created_by.staff_position.position_title if payroll_instance.created_by.staff_position is not None else ""
                                    payroll_instance_map["created_by"] = staff_map
                                    staff_map = {}
                                    staff_map["staff_id"] = str(
                                        payroll_instance.last_updated_by.id) if payroll_instance.last_updated_by is not None else ""
                                    staff_map["staff_name"] = f'{payroll_instance.last_updated_by.first_name} {payroll_instance.last_updated_by.last_name}' if payroll_instance.last_updated_by is not None else ""
                                    staff_map["staff_position"] = payroll_instance.last_updated_by.staff_position.position_title if payroll_instance.last_updated_by.staff_position is not None else ""
                                    payroll_instance_map["last_updated_by"] = staff_map
                                    payroll_instance_map["created_on"] = datetime.strftime(
                                        payroll_instance.created_on.astimezone(target_timezone), date_format) if payroll_instance.created_on is not None else ""
                                    payroll_instance_map["last_updated_on"] = datetime.strftime(
                                        payroll_instance.last_updated_on.astimezone(target_timezone), date_format) if payroll_instance.last_updated_on is not None else ""
                                    payroll_instances_list.append(
                                        payroll_instance_map)
                            # print(payroll_instances_list)
                            # payroll_sheet_map["payroll_instances_list"] = payroll_instances_list
                            # payroll_sheets_list.append(payroll_sheet_map)
                            payroll_sheet_map["payroll_instances_list"] = payroll_instances_list
                            payroll_sheets_list.append(payroll_sheet_map)
                    company_branch_map["payroll_sheets_list"] = payroll_sheets_list
                    # end payroll sheets
                    company_branches_list.append(company_branch_map)
            company_profile_map["company_branches_list"] = company_branches_list
            payload["company_profile"] = company_profile_map
            payload["active_staff_profile_data"] = active_staff_profile_data
            payload["transaction_list"] = transaction_list
            payload["staff_positions_list"] = staff_positions_list
            payload["deductions_list"] = deductions_list
            payload["bonuses_list"] = bonuses_list
            payload["company_departments_list"] = company_departments_list
            # print(transaction_list)
            payload["supplier_list"] = supplier_list
            payload["category_list"] = category_list
            # payload["deposit_list"] = deposit_list
            # payload["chart_of_account_list"] = chart_of_account_list
            payload["loan_portfolio_list"] = loan_portfolio_list
            return Response({"message": "true", "payload": payload}, status=200)
        else:
            return Response({"message": "false", "payload": payload}, status=401)
    except StaffProfile.DoesNotExist:
        return Response({"message": "Staff profile not found for active user", "payload": payload}, status=404)
    except Exception as e:
        logger.exception("finance_and_accounting_dashboard failed")
        return Response({"message": "false", "payload": payload}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_account(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        is_mpesa_account = request.data["is_mpesa_account"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.account.add"):
            if is_mpesa_account == "true":
                account_name = request.data["account_name"]
                account_number = request.data["account_number"]
                running_balance = request.data["running_balance"]
                account_descriptions = request.data["account_descriptions"]
                account_serializer = ChartOfAccountSerializer(
                    data={'company_branch': staff_profile.company_branch.id, 'account_name': account_name, 'account_number': account_number, 'running_balance': running_balance, 'account_descriptions': account_descriptions, 'is_mpesa_account': True, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
                if account_serializer.is_valid():
                    account_serializer.save()
                    return Response({"message": "Company M-pesa account added successfully", }, status=200)
                else:
                    return Response({"message": "Unable to add M-pesa account", }, status=406)
            else:
                account_name = request.data["account_name"]
                account_number = request.data["account_number"]
                running_balance = request.data["running_balance"]
                account_descriptions = request.data["account_descriptions"]
                banking_institution_name = request.data["banking_institution_name"]
                bank_branch_name = request.data["bank_branch_name"]
                bank_branch_code = request.data["bank_branch_code"]
                bank_swift_code = request.data["bank_swift_code"]
                bank_sort_code = request.data["bank_sort_code"]
                account_currency = request.data["account_currency"]
                account_serializer = ChartOfAccountSerializer(
                    data={'company_branch': staff_profile.company_branch.id, 'account_name': account_name, 'account_number': account_number, 'running_balance': running_balance, 'account_descriptions': account_descriptions, 'banking_institution_name': banking_institution_name, 'bank_branch_name': bank_branch_name, 'bank_branch_code': bank_branch_code, 'bank_swift_code': bank_swift_code, 'bank_sort_code': bank_sort_code, 'account_currency': account_currency, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
                if account_serializer.is_valid():
                    account_serializer.save()
                    return Response({"message": "Company bank account added successfully", }, status=200)
                else:
                    print(account_serializer.errors)
                    return Response({"message": "Unable to add bank account", }, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:  # Exception as e:
        # print(e)
        return Response({"message": "Error adding company financial account", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def get_expense_creation_items(request):
    active_user = request.user
    payroll_sheets_list = []
    purchase_orders_list = []
    refund_instances_list = []
    landed_cost_instances_list = []
    payload = {}
    try:
        company_serial_number = request.data["serial_number"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        department_name = (
            staff_profile.company_department.department_name
            if staff_profile.company_department is not None
            else None
        )
        if user_has_permission(staff_profile, "finance_and_accounting.expense.add"):
            if staff_profile.company_branch is not None:
                payroll_sheets = staff_profile.company_branch.branch_payroll_sheets.filter(
                    payroll_sheet_payment_settled=False, payroll_sheet_approved_by_finance=False).order_by("-id")  # payroll sheet approved should be set True
            else:
                payroll_sheets = []
            # purchase_orders = PurchaseOrder.objects.all().order_by("-id")
            for payroll_sheet in payroll_sheets:
                sheet_map = {}
                sheet_map["payroll_sheet_id"] = str(payroll_sheet.id)
                sheet_map["payroll_sheet_number"] = payroll_sheet.payroll_sheet_number
                sheet_map["payroll_sheet_title"] = payroll_sheet.payroll_sheet_title
                sheet_map["payroll_sheet_value"] = payroll_sheet.payroll_sheet_value
                payroll_sheets_list.append(sheet_map)
            # for purchase_order in purchase_orders:
            #     order_map = {}
            #     order_map["purchase_order_id"] = str(purchase_order.id)
            #     order_map["purchase_order_number"] = purchase_order.purchase_order_number
            #     order_map["purchase_value_overall"] = purchase_order.purchase_value_overall
            #     purchase_orders_list.append(order_map)
            # payload["purchase_orders_list"] = purchase_orders_list
            product_purchase_instances = ProductPurchaseInstance.objects.filter(
                supplier_payment_settled=False,).order_by("-id")
            for purchase_instance in product_purchase_instances:
                purchase_order_instance = purchase_instance.purchase_order
                if purchase_order_instance is None or purchase_order_instance.recycle_bin is True:
                    continue
                if purchase_instance.supplier is None:
                    continue
                purchase_map = {}
                purchase_map["purchase_instance_id"] = str(
                    purchase_instance.id)
                purchase_map["product_id"] = str(
                    purchase_instance.purchase_product.id) if purchase_instance.purchase_product is not None else ""
                purchase_map["product_name"] = purchase_instance.purchase_product.product_name if purchase_instance.purchase_product is not None else ""
                purchase_map["unit_of_measurement"] = purchase_instance.purchase_product.unit_of_measurement if purchase_instance.purchase_product is not None else ""
                purchase_map["purchase_order_id"] = str(
                    purchase_order_instance.id)
                purchase_map["purchase_order_number"] = purchase_order_instance.purchase_order_number
                purchase_map["supplier_id"] = str(
                    purchase_instance.supplier.id)
                purchase_map["supplier_name"] = purchase_instance.supplier.supplier_name
                purchase_map["purchase_value_per_unit"] = purchase_instance.purchase_value_per_unit
                purchase_map["purchase_value_overall"] = purchase_instance.purchase_value_overall
                purchase_map["purchase_amount_paid_to_supplier"] = purchase_instance.purchase_amount_paid_to_supplier
                #
                purchase_map[
                    "quantity_purchased"] = purchase_instance.quantity_purchased
                purchase_map[
                    "cost_currency"] = purchase_instance.cost_currency
                purchase_map[
                    "exchange_rate"] = purchase_instance.exchange_rate
                purchase_map[
                    "supplier_payment_settled"] = "true" if purchase_instance.supplier_payment_settled == True else "false"

                #
                purchase_orders_list.append(purchase_map)
            landed_cost_instances = LandedCostInstance.objects.filter(
                cost_payment_settled=False)
            for landed_cost_instance in landed_cost_instances:
                if landed_cost_instance.product_purchase_instance is not None:
                    purchase_order_instance = landed_cost_instance.product_purchase_instance.purchase_order
                    if purchase_order_instance is not None and purchase_order_instance.recycle_bin is False:
                        landed_cost_map = {}
                        landed_cost_map["landed_cost_instance_id"] = str(
                            landed_cost_instance.id)
                        prod_name = landed_cost_instance.product_purchase_instance.purchase_product.product_name if landed_cost_instance.product_purchase_instance.purchase_product is not None else ""
                        landed_cost_map[
                            "landed_cost_name"] = f'{landed_cost_instance.landed_cost.name_of_expense} ({prod_name})' if landed_cost_instance.landed_cost is not None else ""
                        landed_cost_map["description_of_calculation"] = landed_cost_instance.landed_cost.description_of_calculation if landed_cost_instance.landed_cost is not None else ""
                        landed_cost_map["purchase_order_id"] = str(
                            purchase_order_instance.id)  # if landed_cost_instance.product_purchase_instance.count() > 0 else ""
                        # if landed_cost_instance.product_purchase_instance.count(
                        landed_cost_map["purchase_order_number"] = purchase_order_instance.purchase_order_number
                        # ) > 0 else ""
                        landed_cost_map["cost_value"] = landed_cost_instance.cost_value
                        landed_cost_map["cost_currency"] = landed_cost_instance.cost_currency
                        landed_cost_map["exchange_rate"] = landed_cost_instance.exchange_rate
                        landed_cost_map["cost_amount_paid"] = landed_cost_instance.cost_amount_paid
                        landed_cost_map["cost_amount_due"] = landed_cost_instance.cost_amount_due
                        landed_cost_map["reference"] = landed_cost_instance.reference
                        landed_cost_map["cost_payment_settled"] = "true" if landed_cost_instance.cost_payment_settled == True else "false"
                        landed_cost_instances_list.append(landed_cost_map)
            payload["payroll_sheets_list"] = payroll_sheets_list
            payload["purchase_orders_list"] = purchase_orders_list
            payload["landed_cost_instances_list"] = landed_cost_instances_list
            # print(purchase_orders_list)
            return Response({"message": "true", "payload": payload}, status=200)
        else:
            return Response({"message": "false", "payload": payload}, status=401)

    except Exception as e:
        print(e)
        return Response({"message": "false", "payload": payload}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_landed_cost_expense(request):
    active_user = request.user
    expense_creation_successful = False
    created_expense = None
    transaction_creation_successful = False
    created_transaction = None
    landed_cost_update_successful = False
    active_landed_cost = None
    active_account = None
    journal_entry_creation_successful = False
    created_journal_entry = None
    credit_entry_creation_successful = False
    created_credit_entry = None
    debit_entry_creation_successful = False
    created_debit_entry = None
    amount_to_charge = 0.0
    try:
        company_serial_number = request.data["serial_number"]
        expense_title = request.data["expense_title"]
        expense_amount = request.data["expense_amount"]
        account_drawn_from_id = request.data["account_drawn_from_id"]
        expense_description = request.data["expense_description"]
        expense_type = request.data["expense_type"]
        transaction_reference = request.data["transaction_reference"]
        landed_cost_instance_id = request.data["landed_cost_instance_id"]
        exchange_rate = request.data["exchange_rate"]
        amount_to_charge = float(expense_amount)*float(exchange_rate)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        landed_cost_instance = LandedCostInstance.objects.get(
            id=int(landed_cost_instance_id))

        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.expense.add"):
            account_drawn_from_instance = ChartOfAccount.objects.get(
                id=int(account_drawn_from_id))
            transaction_currency = account_drawn_from_instance.account_currency
            expense_serializer = ExpenseSerializer(
                data={'company_branch': staff_profile.company_branch.id, 'expense_title': expense_title, 'expense_description': expense_description, 'expense_type': expense_type, 'payroll_sheet': None, 'product_purchase_instance': [], 'landed_cost_instance': landed_cost_instance.id, 'refund': None, 'expense_amount': f'{amount_to_charge}', 'expense_approved': True, 'expense_settled': True, 'expense_approved_by': staff_profile.id, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            # transaction amount and currency should be the same as the amount charged from the account drawn
            if expense_serializer.is_valid() and float(account_drawn_from_instance.running_balance) >= amount_to_charge:
                new_expense = expense_serializer.save()
                expense_creation_successful = True
                created_expense = new_expense
                transaction_serializer = TransactionSerializer(data={'transaction_mode': 'outflow', 'transaction_amount': f'{amount_to_charge}', 'account': int(
                    account_drawn_from_id), 'expense': new_expense.id, 'transaction_reference': transaction_reference, 'transaction_currency': transaction_currency, 'exchange_rate': '1.00'})
                if transaction_serializer.is_valid():
                    created_transaction = transaction_serializer.save()
                    transaction_creation_successful = True
                    account_drawn_from_instance.running_balance = f'{(float(account_drawn_from_instance.running_balance.replace(",", ""))*float(exchange_rate))-amount_to_charge}'
                    account_drawn_from_instance.save()
                    active_account = account_drawn_from_instance
                    # update landed cost instance values
                    landed_cost_instance.cost_amount_paid = f'{float(landed_cost_instance.cost_amount_paid)+float(expense_amount)}'
                    landed_cost_instance.cost_amount_due = f'{float(landed_cost_instance.cost_value)-float(landed_cost_instance.cost_amount_paid)}'
                    if float(landed_cost_instance.cost_value)-float(landed_cost_instance.cost_amount_paid) <= 0:
                        landed_cost_instance.cost_payment_settled = True
                    landed_cost_instance.save()
                    landed_cost_update_successful = True
                    active_landed_cost = landed_cost_instance
                    # create journal entries
                    journal_account_debit, created = JournalAccountDebit.objects.get_or_create(
                        account_name="accounts_payable")
                    journal_account_credit = None
                    if account_drawn_from_instance.is_mpesa_account == True:
                        journal_account_credit, created = JournalAccountCredit.objects.get_or_create(
                            account_name="m_pesa")
                    else:
                        journal_account_credit, created = JournalAccountCredit.objects.get_or_create(
                            account_name="bank")
                    journal_entry_serializer = Journal_EntrySerializer(
                        data={'company_branch': staff_profile.company_branch.id, 'journal_tag': 'Inventory landed cost expense', 'journal_reference': new_expense.expense_number, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
                    if journal_entry_serializer.is_valid():
                        new_journal_entry = journal_entry_serializer.save()
                        journal_entry_creation_successful = True
                        created_journal_entry = new_journal_entry
                        # create debit and credit entry
                        debit_entry_serializer = DebitEntrySerializer(
                            data={'journal_entry': new_journal_entry.id, 'journal_account_debit': journal_account_debit.id, 'debit_amount': f'{amount_to_charge}'})
                        if debit_entry_serializer.is_valid():
                            created_debit_entry = debit_entry_serializer.save()
                            debit_entry_creation_successful = True
                        else:
                            # created_debit_entry.delete()
                            created_journal_entry.delete()
                            landed_cost_instance.cost_amount_paid = f'{float(landed_cost_instance.cost_amount_paid)-float(expense_amount)}'
                            landed_cost_instance.cost_amount_due = f'{float(landed_cost_instance.cost_value)-float(landed_cost_instance.cost_amount_paid)}'
                            landed_cost_instance.save()
                            account_drawn_from_instance.running_balance = f'{(float(account_drawn_from_instance.running_balance.replace(",", ""))*float(exchange_rate))+amount_to_charge}'
                            account_drawn_from_instance.save()
                            created_transaction.delete()
                            created_expense.delete()
                            return Response({"message": "Error creating expense, try again", }, status=406)

                        credit_entry_serializer = CreditEntrySerializer(
                            data={'journal_entry': new_journal_entry.id, 'journal_account_credit': journal_account_credit.id, 'credit_amount': f'{amount_to_charge}'})
                        if credit_entry_serializer.is_valid():
                            created_credit_entry = credit_entry_serializer.save()
                            credit_entry_creation_successful = True
                        else:
                            created_debit_entry.delete()
                            created_journal_entry.delete()
                            landed_cost_instance.cost_amount_paid = f'{float(landed_cost_instance.cost_amount_paid)-float(expense_amount)}'
                            landed_cost_instance.cost_amount_due = f'{float(landed_cost_instance.cost_value)-float(landed_cost_instance.cost_amount_paid)}'
                            landed_cost_instance.save()
                            account_drawn_from_instance.running_balance = f'{(float(account_drawn_from_instance.running_balance.replace(",", ""))*float(exchange_rate))+amount_to_charge}'
                            account_drawn_from_instance.save()
                            created_transaction.delete()
                            created_expense.delete()
                            return Response({"message": "Error creating expense, try again", }, status=406)
                    else:
                        # created_debit_entry.delete()
                        # created_journal_entry.delete()
                        landed_cost_instance.cost_amount_paid = f'{float(landed_cost_instance.cost_amount_paid)-float(expense_amount)}'
                        landed_cost_instance.cost_amount_due = f'{float(landed_cost_instance.cost_value)-float(landed_cost_instance.cost_amount_paid)}'
                        landed_cost_instance.save()
                        account_drawn_from_instance.running_balance = f'{(float(account_drawn_from_instance.running_balance.replace(",", ""))*float(exchange_rate))+amount_to_charge}'
                        account_drawn_from_instance.save()
                        created_transaction.delete()
                        created_expense.delete()
                        return Response({"message": "Error creating expense, try again", }, status=406)
                else:
                    # (transaction_serializer.errors)
                    # delete expense
                    created_expense.delete()
                    return Response({"message": "Error creating expense, try again", }, status=406)
                # response successful
                return Response({"message": "Expense created successfully", }, status=200)
            else:
                return Response({"message": "Error creating expense or insufficient account balance", }, status=406)
    except Exception as e:
        if expense_creation_successful == True:
            created_expense.delete()
        if transaction_creation_successful == True:
            created_transaction.delete()
        if landed_cost_update_successful == True:
            active_landed_cost.cost_amount_paid = f'{float(landed_cost_instance.cost_amount_paid)-float(expense_amount)}'
            active_landed_cost.cost_amount_due = f'{float(landed_cost_instance.cost_value)-float(landed_cost_instance.cost_amount_paid)}'
            active_landed_cost.save()
        if active_account is not None:
            account_drawn_from_instance.running_balance = f'{(float(account_drawn_from_instance.running_balance.replace(",", ""))*float(exchange_rate))+amount_to_charge}'
            account_drawn_from_instance.save()
        if journal_entry_creation_successful == True:
            created_journal_entry.delete()
        if credit_entry_creation_successful == True:
            created_credit_entry.delete()
        if debit_entry_creation_successful == True:
            created_debit_entry.delete()
        print(e)
        return Response({"message": "Error creating expense", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_expense(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        expense_title = request.data["expense_title"]
        account_drawn_from_id = request.data["account_drawn_from_id"]
        expense_description = request.data["expense_description"]
        expense_type = request.data["expense_type"]
        transaction_reference = request.data["transaction_reference"]
        payroll_sheet_id = int(
            request.data["payroll_sheet"]) if expense_type == "salary_expense" else None
        # purchase_order_id = int(request.data["purchase_order"]) if expense_type == "purchase_expense" else None
        expense_amount = request.data["expense_amount"]
        # amount_to_charge = 0.0
        purchase_order_instance_list = request.data.get(
            'purchase_order_instance_list', [])
        purchase_order_instance_list = json.loads(purchase_order_instance_list)
        ids_list_int = []

        refund_id = int(
            request.data["refund"]) if expense_type == "refund_expense" else None

        expense_approved = True if request.data["expense_approved"] == "true" else False
        expense_settled = True if request.data["expense_settled"] == "true" else False
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        expense_approved_by = staff_profile.id if expense_approved == True else None
        if user_has_permission(staff_profile, "finance_and_accounting.expense.add"):
            petty_cash_fund = None
            petty_cash_fund_id = request.data.get("petty_cash_fund_id")
            if petty_cash_fund_id:
                petty_cash_fund = PettyCashFund.objects.filter(
                    id=int(petty_cash_fund_id),
                    recycle_bin=False,
                    company_branch__company_profile=company_profile,
                ).select_related("petty_cash_account", "company_branch", "bank_account").first()
                if not petty_cash_fund:
                    return Response({"message": "Petty cash fund not found."}, status=404)
                if not petty_cash_fund.petty_cash_account_id:
                    return Response({
                        "message": "Petty cash fund has no petty cash GL account configured.",
                    }, status=400)
                account_drawn_from_instance = petty_cash_fund.petty_cash_account
                account_drawn_from_id = str(account_drawn_from_instance.id)
            else:
                account_drawn_from_instance = ChartOfAccount.objects.get(
                    id=int(account_drawn_from_id))
            # determine exchange factor
            exchange_factor = 1.00
            if len(purchase_order_instance_list) > 0:
                if purchase_order_instance_list[0]["cost_currency"] != account_drawn_from_instance.account_currency:
                    exchange_factor = float(
                        purchase_order_instance_list[0]["exchange_rate"])
            charge_amount = float(expense_amount.replace(",", "")) * exchange_factor
            if petty_cash_fund:
                sync_petty_cash_running_balance(petty_cash_fund)
                account_drawn_from_instance.refresh_from_db()
                if float(petty_cash_fund.current_balance) < charge_amount:
                    return Response({
                        "message": (
                            f"Insufficient petty cash fund balance "
                            f"({petty_cash_fund.current_balance} available on {petty_cash_fund.fund_name})."
                        ),
                    }, status=406)
                balance_ok = True
            else:
                balance_ok = float(account_drawn_from_instance.running_balance.replace(",", "")) >= charge_amount

            if balance_ok:
                for order_id in purchase_order_instance_list:
                    product_purchase_instance = ProductPurchaseInstance.objects.get(
                        id=int(order_id["purchase_instance_id"]))
                    # important, come back here and change
                    product_purchase_instance.purchase_amount_paid_to_supplier = f'{float(product_purchase_instance.purchase_amount_paid_to_supplier.replace(",", "")) + float(expense_amount.replace(",", ""))}'
                    # print(product_purchase_instance.purchase_amount_paid_to_supplier)
                    if float(product_purchase_instance.purchase_amount_paid_to_supplier.replace(",", "")) >= float(product_purchase_instance.purchase_value_overall.replace(",", "")):
                        product_purchase_instance.supplier_payment_settled = True
                    product_purchase_instance.save()
                    ids_list_int.append(int(order_id["purchase_instance_id"]))
                expense_serializer = ExpenseSerializer(
                    data={'company_branch': staff_profile.company_branch.id, 'expense_title': expense_title, 'expense_description': expense_description, 'expense_type': expense_type, 'payroll_sheet': payroll_sheet_id, 'product_purchase_instance': ids_list_int, 'refund': refund_id, 'expense_amount': f'{float(expense_amount)*exchange_factor}', 'expense_approved': expense_approved, 'expense_settled': expense_settled, 'expense_approved_by': expense_approved_by, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
                if expense_serializer.is_valid():
                    new_expense = expense_serializer.save()
                    # transaction_currency = "kes" if len(
                    #     purchase_order_instance_list) == 0 else purchase_order_instance_list[0]["cost_currency"]
                    transaction_currency = account_drawn_from_instance.account_currency
                    # exchange_rate = "1.00" if len(
                    #     purchase_order_instance_list) == 0 else purchase_order_instance_list[0]["exchange_rate"]
                    transaction_serializer = TransactionSerializer(data={'transaction_mode': 'outflow', 'transaction_amount': f'{float(expense_amount)*exchange_factor}', 'account': int(
                        account_drawn_from_id), 'expense': new_expense.id, 'transaction_reference': transaction_reference, 'transaction_currency': transaction_currency, 'exchange_rate': '1.00'})
                    if transaction_serializer.is_valid():
                        transaction_serializer.save()
                    else:
                        # (transaction_serializer.errors)
                        pass
                    if petty_cash_fund:
                        from decimal import Decimal
                        petty_cash_fund.current_balance = Decimal(str(float(petty_cash_fund.current_balance) - charge_amount))
                        petty_cash_fund.save(update_fields=["current_balance", "last_updated_on"])
                        sync_petty_cash_running_balance(petty_cash_fund)
                    else:
                        account_drawn_from_instance.running_balance = f'{float(account_drawn_from_instance.running_balance.replace(",", ""))-charge_amount}'
                        account_drawn_from_instance.save()
                    if expense_type == "salary_expense":
                        payroll_sheet = PayrollSheet.objects.get(
                            id=payroll_sheet_id)
                        payroll_sheet.payroll_sheet_payment_settled = True
                        payroll_sheet.save()
                        try:
                            from finance_and_accounting.employee_advance import recover_advances_for_payroll_payment
                            recover_advances_for_payroll_payment(
                                payroll_sheet=payroll_sheet,
                                staff=staff_profile,
                                credit_account=account_drawn_from_instance,
                            )
                        except Exception:
                            pass
                        # send notification
                        list_of_staff_ids = []
                        # get finance department staff
                        list_of_staff_ids.append(
                            payroll_sheet.created_by.id)
                        notification_title = f"Payroll sheet {payroll_sheet.payroll_sheet_number} Payment Settled."
                        notification_body = f"The payments for payroll sheet {payroll_sheet.payroll_sheet_number} has been approved and settled by the finance department."
                        create_notifications(notification_title,
                                             notification_body, list_of_staff_ids)
                    gl_post = post_expense_gl(
                        staff_profile.company_branch,
                        staff_profile,
                        new_expense,
                        expense_type,
                        account_drawn_from_instance,
                    )
                    if not gl_post.get("posted"):
                        journal_account_debit = None
                        if expense_type == "purchase_expense":
                            journal_account_debit, created = JournalAccountDebit.objects.get_or_create(
                                account_name="accounts_payable")
                        if expense_type == "salary_expense":
                            journal_account_debit, created = JournalAccountDebit.objects.get_or_create(
                                account_name="salary_and_wages_expense")
                        if expense_type == "loan_repayment_expense":
                            journal_account_debit, created = JournalAccountDebit.objects.get_or_create(
                                account_name="loans_payable")
                        if expense_type == "utility_expense":
                            journal_account_debit, created = JournalAccountDebit.objects.get_or_create(
                                account_name="utility_expense")
                        if expense_type == "rent_expense":
                            journal_account_debit, created = JournalAccountDebit.objects.get_or_create(
                                account_name="rent_expense")
                        if expense_type == "operations_expense":
                            journal_account_debit, created = JournalAccountDebit.objects.get_or_create(
                                account_name="operations_expense")
                        if expense_type == "refund_expense":
                            journal_account_debit, created = JournalAccountDebit.objects.get_or_create(
                                account_name="refund_expense")
                        if expense_type == "tax_and_license_expense":
                            journal_account_debit, created = JournalAccountDebit.objects.get_or_create(
                                account_name="tax_and_license_expense")
                        if expense_type == "other":
                            journal_account_debit, created = JournalAccountDebit.objects.get_or_create(
                                account_name="miscellaneous_expense")
                        journal_account_credit = None
                        if account_drawn_from_instance.is_mpesa_account == True:
                            journal_account_credit, created = JournalAccountCredit.objects.get_or_create(
                                account_name="m_pesa")
                        else:
                            journal_account_credit, created = JournalAccountCredit.objects.get_or_create(
                                account_name="bank")
                        if journal_account_debit and journal_account_credit:
                            journal_entry_serializer = Journal_EntrySerializer(
                                data={'company_branch': staff_profile.company_branch.id, 'journal_tag': 'Payment for Expense', 'journal_reference': new_expense.expense_number, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
                            if journal_entry_serializer.is_valid():
                                new_journal_entry = journal_entry_serializer.save()
                                debit_entry_serializer = DebitEntrySerializer(
                                    data={'journal_entry': new_journal_entry.id, 'journal_account_debit': journal_account_debit.id, 'debit_amount': new_expense.expense_amount})
                                if debit_entry_serializer.is_valid():
                                    debit_entry_serializer.save()
                                credit_entry_serializer = CreditEntrySerializer(
                                    data={'journal_entry': new_journal_entry.id, 'journal_account_credit': journal_account_credit.id, 'credit_amount': new_expense.expense_amount})
                                if credit_entry_serializer.is_valid():
                                    credit_entry_serializer.save()
                    message = "Expense created successfully"
                    if gl_post.get("posted"):
                        message += " and posted to the general ledger."
                    elif not gl_post.get("skipped"):
                        message += (
                            f". GL posting pending — "
                            f"{gl_post.get('error', 'configure Account Mappings or run Setup Standard COA')}."
                        )
                    return Response({"message": message, "gl_posting": gl_post}, status=200)
                else:
                    # print(expense_serializer.errors)
                    return Response({"message": "Unable to create expense", }, status=406)
            else:
                return Response({"message": f"Insufficient running balance on account number {account_drawn_from_instance.account_name} ({account_drawn_from_instance.account_number})", }, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "Error creating expense", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_deposit(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        deposit_source = request.data["deposit_source"]
        deposit_amount = request.data["deposit_amount"]
        recipient_account_id = request.data["recipient_account_id"]
        transaction_reference = request.data["transaction_reference"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.deposit.add"):
            deposit_serializer = DepositSerializer(
                data={'company_branch': staff_profile.company_branch.id, 'deposit_source': deposit_source, 'deposit_amount': deposit_amount, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            if deposit_serializer.is_valid():
                new_deposit = deposit_serializer.save()
                recipient_account_instance = ChartOfAccount.objects.get(
                    id=int(recipient_account_id))
                transaction_serializer = TransactionSerializer(data={'transaction_mode': 'inflow', 'transaction_amount': deposit_amount, 'account': int(
                    recipient_account_id), 'deposit': new_deposit.id, 'transaction_reference': transaction_reference, 'transaction_currency': recipient_account_instance.account_currency})
                if transaction_serializer.is_valid():
                    new_transaction = transaction_serializer.save()
                    recipient_account_instance.running_balance = f'{float(recipient_account_instance.running_balance.replace(",", ""))+float(deposit_amount.replace(",", ""))}'
                    recipient_account_instance.save()
                    # create journal entry
                    journal_account_debit = None

                    if recipient_account_instance.is_mpesa_account == True:
                        journal_account_debit, created = JournalAccountDebit.objects.get_or_create(
                            account_name="m_pesa")
                        # print("executed well")
                    else:
                        journal_account_debit, created = JournalAccountDebit.objects.get_or_create(
                            account_name="bank")

                    journal_account_credit = None
                    if deposit_source == "sales_revenue":
                        journal_account_credit, created = JournalAccountCredit.objects.get_or_create(
                            account_name="sales_revenue")
                    if deposit_source == "loans":
                        journal_account_credit, created = JournalAccountCredit.objects.get_or_create(
                            account_name="loans_payable")
                    if deposit_source == "vehicle_and_equipment_lease_revenue":
                        journal_account_credit, created = JournalAccountCredit.objects.get_or_create(
                            account_name="vehicle_and_equipment_lease_revenue")
                    if deposit_source == "other":
                        journal_account_credit, created = JournalAccountCredit.objects.get_or_create(
                            account_name="miscellaneous_income")
                    journal_entry_serializer = Journal_EntrySerializer(
                        data={'company_branch': staff_profile.company_branch.id, 'transaction': new_transaction.id, 'journal_reference': new_deposit.deposit_number, 'journal_tag': 'Cash Deposit', 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
                    if journal_entry_serializer.is_valid():
                        new_journal_entry = journal_entry_serializer.save()
                        journal_account_debit_id = journal_account_debit.id if journal_account_debit is not None else None
                        debit_entry_serializer = DebitEntrySerializer(
                            data={'journal_entry': new_journal_entry.id, 'journal_account_debit': journal_account_debit_id, 'debit_amount': new_deposit.deposit_amount})
                        if debit_entry_serializer.is_valid():
                            debit_entry_serializer.save()
                        journal_account_credit_id = journal_account_credit.id if journal_account_credit is not None else None
                        credit_entry_serializer = CreditEntrySerializer(
                            data={'journal_entry': new_journal_entry.id, 'journal_account_credit': journal_account_credit_id, 'credit_amount': new_deposit.deposit_amount})
                        if credit_entry_serializer.is_valid():
                            credit_entry_serializer.save()
                return Response({"message": "Account deposit created successfully", }, status=200)
            else:
                # print( deposit_serializer.errors)
                return Response({"message": "Unable to create account deposit", }, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "Error creating account deposit", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_loan_portfolio(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        loan_title = request.data["loan_title"]
        loan_type = request.data["loan_type"]
        lender_name = request.data["lender_name"]
        lender_phone = request.data["lender_phone"]
        lender_email = request.data["lender_email"]
        loan_amount = request.data["loan_amount"]
        interest_rate = request.data["interest_rate"]
        repayment_period = request.data["repayment_period"]
        total_repayment_amount = request.data["total_repayment_amount"]
        principal_paid = request.data["principal_paid"]
        loan_currency = request.data["loan_currency"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.loan_portfolio.add"):
            loan_serializer = LoanPortfolioSerializer(
                data={'company_profile': company_profile.id, 'loan_currency': loan_currency, 'loan_title': loan_title, 'loan_type': loan_type, 'lender_name': lender_name, 'lender_phone': lender_phone, 'lender_email': lender_email, 'loan_amount': loan_amount, 'interest_rate': interest_rate, 'repayment_period': repayment_period, 'total_repayment_amount': total_repayment_amount, 'principal_paid': principal_paid, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            if loan_serializer.is_valid():
                loan_serializer.save()
                return Response({"message": "Loan portfolio added successfully", }, status=200)
            else:
                return Response({"message": "Unable to create loan portfolio", }, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:  # Exception as e:
        # print(e)
        return Response({"message": "Error creating loan portfolio", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_order_payment(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        customer_order_id = request.data["customer_order_id"]
        # print(customer_order_id)
        account_paid_to_id = request.data["account_paid_to_id"]
        payment_amount = request.data["payment_amount"].replace(",", "")
        payment_method = request.data["payment_method"]
        payer_account_number = request.data["payer_account_number"]
        order_payment_reference = request.data["order_payment_reference"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.customer_order_finance.edit"):
            customer_order_payment_serializer = CustomerOrderPaymentSerializer(
                data={'customer_order': int(customer_order_id), 'account_paid_to': int(account_paid_to_id), 'payment_amount': payment_amount, 'payment_method': payment_method, 'payer_account_number': payer_account_number, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            if customer_order_payment_serializer.is_valid():
                new_order_payment = customer_order_payment_serializer.save()
                customer_order_instance = CustomerOrder.objects.get(
                    id=int(customer_order_id))
                customer_order_instance.customer_order_total_amount_paid = float(
                    customer_order_instance.customer_order_total_amount_paid) + float(payment_amount)
                customer_order_instance.save()
                # recorded payment changes collection metrics — refresh CRM performance now
                try:
                    from megawatt_api.crm_webhook import (
                        account_manager_staff_ids_for_order, notify_crm_staff_performance)
                    notify_crm_staff_performance(
                        account_manager_staff_ids_for_order(customer_order_instance))
                except Exception as perf_error:
                    print(perf_error)
                # update invoice
                customer_order_invoice = customer_order_instance.customer_order_invoice
                customer_order_invoice.invoice_amount_paid = float(
                    customer_order_invoice.invoice_amount_paid) + float(payment_amount)
                if float(customer_order_invoice.invoice_amount_paid) >= float(customer_order_invoice.invoice_amount_due):
                    customer_order_invoice.invoice_settled = True
                customer_order_invoice.last_updated_by = staff_profile
                customer_order_invoice.save()

                # create transactions
                deposit_serializer = DepositSerializer(
                    data={'company_branch': staff_profile.company_branch.id, 'deposit_source': 'sales_revenue', 'deposit_amount': payment_amount, 'order_payment_reference': order_payment_reference, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
                if deposit_serializer.is_valid():
                    new_deposit = deposit_serializer.save()
                    # create transaction
                    transaction_serializer = TransactionSerializer(data={'transaction_mode': 'inflow', 'transaction_amount': payment_amount, 'account': int(
                        account_paid_to_id), 'deposit': new_deposit.id, 'transaction_reference': order_payment_reference, 'customer_order_payment': new_order_payment.id})
                    if transaction_serializer.is_valid():
                        new_transaction = transaction_serializer.save()
                        gl_post = post_customer_payment(
                            staff_profile.company_branch,
                            staff_profile,
                            new_order_payment,
                            customer_order_invoice,
                        )
                        recipient_account_instance = ChartOfAccount.objects.get(
                            id=int(account_paid_to_id))
                        recipient_account_instance.running_balance = float(
                            recipient_account_instance.running_balance.replace(",", "")) + float(payment_amount)
                        recipient_account_instance.save()
                        message = "Order payment added successfully"
                        if gl_post.get("posted"):
                            message += " and posted to the general ledger."
                        elif not gl_post.get("skipped"):
                            message += (
                                f". GL posting pending — "
                                f"{gl_post.get('error', 'configure Account Mappings or run Setup Standard COA')}."
                            )
                        return Response({"message": message, "gl_posting": gl_post}, status=200)
                return Response({"message": "Order payment added successfully", }, status=200)
            else:
                return Response({"message": "Unable to add order payment", "errors": customer_order_payment_serializer.errors}, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except Exception as e:
        import traceback
        traceback.print_exc()
        return Response({"message": f"Error creating order payment: {type(e).__name__}: {e}"}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def approve_customer_order(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        customer_order_id = request.data["customer_order_id"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.customer_order_finance.approve"):
            customer_order_instance = CustomerOrder.objects.get(
                id=int(customer_order_id))

            # Credit limit enforcement for credit customers
            customer = customer_order_instance.customer_profile
            if customer is not None:
                credit_limit = float(customer.customer_credit_limit or 0)
                if credit_limit > 0:
                    outstanding = 0.0
                    existing_orders = CustomerOrder.objects.filter(
                        customer_profile=customer,
                        customer_order_approved=True,
                        recycle_bin=False,
                    ).exclude(id=customer_order_instance.id)
                    for order in existing_orders:
                        net = float(order.customer_order_total_net_value or 0)
                        paid = float(order.customer_order_total_amount_paid or 0)
                        outstanding += max(0.0, net - paid)
                    order_value = float(customer_order_instance.customer_order_total_net_value or 0)
                    if outstanding + order_value > credit_limit:
                        return Response({
                            "message": (
                                f"Credit limit exceeded. Limit: {credit_limit:.2f}, "
                                f"Outstanding: {outstanding:.2f}, Order: {order_value:.2f}"
                            ),
                        }, status=406)

            customer_order_instance.customer_order_approved = True
            customer_order_instance.save()
            # send notification to the staff that created the customer order
            list_of_staff_ids = []
            # get finance department staff
            if customer_order_instance.created_by is not None:
                list_of_staff_ids.append(
                    customer_order_instance.created_by.id)
            notification_title = f"Customer Order {customer_order_instance.customer_order_number} Approved"
            notification_body = f"The customer order {customer_order_instance.customer_order_number} has been approved by the finance department. You can therefore proceed to initiate the order fullfillment process."
            if list_of_staff_ids:
                create_notifications(notification_title,
                                     notification_body, list_of_staff_ids)
            # notify the warehouse team so fulfillment can begin
            try:
                warehouse_staff = StaffProfile.objects.filter(
                    company_department__department_name="warehouse_management",
                    company_branch__company_profile=company_profile,
                    recycle_bin=False,
                    is_profile_active=True,
                )
                warehouse_staff_ids = [staff.id for staff in warehouse_staff]
                if warehouse_staff_ids:
                    warehouse_title = (
                        f"Approved Order {customer_order_instance.customer_order_number} "
                        f"— Fulfillment Required"
                    )
                    warehouse_body = (
                        f"Customer order {customer_order_instance.customer_order_number} has been "
                        f"approved by finance and is ready for fulfillment. Please prepare the stock "
                        f"and await the stock requisition."
                    )
                    create_notifications(warehouse_title,
                                         warehouse_body, warehouse_staff_ids)
            except Exception as warehouse_notify_error:
                print(warehouse_notify_error)
            # Approval changes net sales — refresh the staff's CRM performance now
            try:
                from megawatt_api.crm_webhook import (
                    account_manager_staff_ids_for_order, notify_crm_staff_performance)
                notify_crm_staff_performance(
                    account_manager_staff_ids_for_order(customer_order_instance))
            except Exception as perf_error:
                print(perf_error)
            return Response({"message": "Customer order approved successfully", }, status=200)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "Error approving customer order", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def cancel_customer_order(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        customer_order_id = request.data["customer_order_id"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.customer_order_finance.approve"):
            customer_order_instance = CustomerOrder.objects.get(
                id=int(customer_order_id))
            customer_order_instance.customer_order_approved = False
            customer_order_instance.save()
            # send notification to the staff that created the customer order
            list_of_staff_ids = []
            # get finance department staff
            list_of_staff_ids.append(
                customer_order_instance.created_by.id)
            notification_title = f"Customer Order {customer_order_instance.customer_order_number} Cancelled"
            notification_body = f"The customer order {customer_order_instance.customer_order_number} has been cancelled by the finance department. You are hereby required to halt any process of fullfilling the order."
            create_notifications(notification_title,
                                 notification_body, list_of_staff_ids)
            return Response({"message": "Customer order approval cancelled", }, status=200)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:
        return Response({"message": "Error cancelling customer order approval", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_account(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        is_mpesa_account = request.data["is_mpesa_account"]
        chart_of_account_id = request.data["chart_of_account_id"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.account.edit"):
            if is_mpesa_account == "true":
                account_name = request.data["account_name"]
                account_number = request.data["account_number"]
                running_balance = request.data["running_balance"]
                account_descriptions = request.data["account_descriptions"]
                account_instance = ChartOfAccount.objects.get(
                    id=int(chart_of_account_id))
                account_serializer = ChartOfAccountSerializer(instance=account_instance,
                                                              data={'company_branch': staff_profile.company_branch.id, 'account_name': account_name, 'account_number': account_number, 'running_balance': running_balance, 'account_descriptions': account_descriptions, 'is_mpesa_account': True, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
                if account_serializer.is_valid():
                    account_serializer.save()
                    return Response({"message": "Company M-pesa account edited successfully", }, status=200)
                else:
                    return Response({"message": "Unable to edit M-pesa account", }, status=406)
            else:
                account_name = request.data["account_name"]
                account_number = request.data["account_number"]
                running_balance = request.data["running_balance"]
                account_descriptions = request.data["account_descriptions"]
                banking_institution_name = request.data["banking_institution_name"]
                bank_branch_name = request.data["bank_branch_name"]
                bank_branch_code = request.data["bank_branch_code"]
                bank_swift_code = request.data["bank_swift_code"]
                bank_sort_code = request.data["bank_sort_code"]
                account_currency = request.data["account_currency"]
                account_instance = ChartOfAccount.objects.get(
                    id=int(chart_of_account_id))
                account_serializer = ChartOfAccountSerializer(instance=account_instance,
                                                              data={'company_branch': staff_profile.company_branch.id, 'account_name': account_name, 'account_number': account_number, 'running_balance': running_balance, 'account_descriptions': account_descriptions, 'banking_institution_name': banking_institution_name, 'bank_branch_name': bank_branch_name, 'bank_branch_code': bank_branch_code, 'bank_swift_code': bank_swift_code, 'bank_sort_code': bank_sort_code, 'account_currency': account_currency, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
                if account_serializer.is_valid():
                    account_serializer.save()
                    return Response({"message": "Company bank account edited successfully", }, status=200)
                else:
                    # print(account_serializer.errors)
                    return Response({"message": "Unable to edit bank account", }, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:  # Exception as e:
        # print(e)
        return Response({"message": "Error editing company financial account", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_account(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        is_mpesa_account = request.data["is_mpesa_account"]
        chart_of_account_id = request.data["chart_of_account_id"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.account.delete"):
            if is_mpesa_account == "true":
                account_instance = ChartOfAccount.objects.get(
                    id=int(chart_of_account_id))
                if account_instance.recycle_bin != True:
                    account_instance.last_updated_by = staff_profile
                    account_instance.recycle_bin = True
                    account_instance.save()
                    return Response({"message": "Company M-Pesa account deleted successfully", }, status=200)
                else:
                    account_instance.delete()
                    return Response({"message": "Company M-Pesa account permanently deleted successfully", }, status=200)
            else:
                account_instance = ChartOfAccount.objects.get(
                    id=int(chart_of_account_id))
                if account_instance.recycle_bin != True:
                    account_instance.last_updated_by = staff_profile
                    account_instance.recycle_bin = True
                    account_instance.save()
                    return Response({"message": "Company bank account deleted successfully", }, status=200)
                else:
                    account_instance.delete()
                    return Response({"message": "Company bank account permanently deleted successfully", }, status=200)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:  # Exception as e:
        # print(e)
        return Response({"message": "Error deleting company financial account", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_asset(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        asset_id = request.data["asset_id"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.asset.delete"):
            asset_instance = Asset.objects.get(id=int(asset_id))
            if asset_instance.recycle_bin != True:
                asset_instance.recycle_bin = True
                asset_instance.save()
                return Response({"message": "Asset deleted successfully", }, status=200)
            else:
                asset_instance.delete()
                return Response({"message": "Asset instance permanently deleted successfully", }, status=200)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:  # Exception as e:
        # print(e)
        return Response({"message": "Error deleting asset", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_dividend_payment(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        dividend_id = request.data["dividend_id"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.dividend.delete"):
            dividend_instance = Dividend.objects.get(id=int(dividend_id))
            if dividend_instance.recycle_bin != True:
                dividend_instance.recycle_bin = True
                dividend_instance.save()
                dividend_instance.account.running_balance = f'{float(dividend_instance.account.running_balance.replace(",",""))+float(dividend_instance.dividend_amount_paid.replace(",",""))}'
                dividend_instance.account.save()
                dividend_transaction = dividend_instance.dividend_transaction
                dividend_transaction.recycle_bin = False
                dividend_transaction.save()
                # delete jounal entries
                transaction_journal_entries = dividend_transaction.transaction_journal_entries.all()
                for journal_entry in transaction_journal_entries:
                    journal_entry.delete()

                return Response({"message": "Dividend deleted successfully", }, status=200)
            else:
                dividend_instance.delete()
                return Response({"message": "Dividend instance permanently deleted successfully", }, status=200)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "Error deleting asset", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_loan_portfolio(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        loan_title = request.data["loan_title"]
        loan_type = request.data["loan_type"]
        lender_name = request.data["lender_name"]
        lender_phone = request.data["lender_phone"]
        lender_email = request.data["lender_email"]
        loan_amount = request.data["loan_amount"]
        interest_rate = request.data["interest_rate"]
        repayment_period = request.data["repayment_period"]
        total_repayment_amount = request.data["total_repayment_amount"]
        principal_paid = request.data["principal_paid"]
        loan_portfolio_id = request.data["loan_portfolio_id"]
        loan_currency = request.data["loan_currency"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.loan_portfolio.edit"):
            loan_portfolio_instance = LoanPortfolio.objects.get(
                id=int(loan_portfolio_id))
            loan_serializer = LoanPortfolioSerializer(instance=loan_portfolio_instance,
                                                      data={'company_profile': company_profile.id, 'loan_currency': loan_currency, 'loan_title': loan_title, 'loan_type': loan_type, 'lender_name': lender_name, 'lender_phone': lender_phone, 'lender_email': lender_email, 'loan_amount': loan_amount, 'interest_rate': interest_rate, 'repayment_period': repayment_period, 'total_repayment_amount': total_repayment_amount, 'principal_paid': principal_paid, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            if loan_serializer.is_valid():
                loan_serializer.save()
                return Response({"message": "Loan portfolio edited successfully", }, status=200)
            else:
                return Response({"message": "Unable to edit loan portfolio", }, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:  # Exception as e:
        # print(e)
        return Response({"message": "Error editing loan portfolio", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_loan_portfolio(request):
    # to be updated
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        loan_portfolio_id = request.data["loan_portfolio_id"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.loan_portfolio.delete"):
            loan_portfolio_instance = LoanPortfolio.objects.get(
                id=int(loan_portfolio_id))
            if loan_portfolio_instance.recycle_bin != True:
                loan_portfolio_instance.recycle_bin = True
                loan_portfolio_instance.save()
                return Response({"message": "Loan instance deleted successfully", }, status=200)
            else:
                loan_portfolio_instance.delete()
                return Response({"message": "Loan instance permanently deleted successfully", }, status=200)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:  # Exception as e:
        # print(e)
        return Response({"message": "Error deleting loan instance", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def approve_purchase_order(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        purchase_order_id = request.data["purchase_order_id"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.purchase_order_finance.approve"):
            purchase_order_instance = PurchaseOrder.objects.get(
                id=int(purchase_order_id))
            purchase_order_instance.purchase_order_approved = True
            purchase_order_instance.purchase_order_approved_by = staff_profile
            purchase_order_instance.save()
            # send notification to the staff that created the customer order
            list_of_staff_ids = []
            # get finance department staff
            list_of_staff_ids.append(
                purchase_order_instance.created_by.id)
            notification_title = f"Purchase Order {purchase_order_instance.purchase_order_number} Approved"
            notification_body = f"The purchase order {purchase_order_instance.purchase_order_number} has been approved by the finance department. You can therefore proceed to initiate the order fullfillment process."
            create_notifications(notification_title,
                                 notification_body, list_of_staff_ids)
            return Response({"message": "Purchase order approved successfully", }, status=200)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:
        return Response({"message": "Error approving purchase order", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def cancel_purchase_order_approval(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        purchase_order_id = request.data["purchase_order_id"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.purchase_order_finance.approve"):
            purchase_order_instance = PurchaseOrder.objects.get(
                id=int(purchase_order_id))
            purchase_order_instance.purchase_order_approved = False
            purchase_order_instance.purchase_order_approved_by = None
            purchase_order_instance.save()
            # send notification to the staff that created the customer order
            list_of_staff_ids = []
            # get finance department staff
            list_of_staff_ids.append(
                purchase_order_instance.created_by.id)
            notification_title = f"Purchase Order {purchase_order_instance.purchase_order_number} Approval Cancelled"
            notification_body = f"The purchase order {purchase_order_instance.purchase_order_number} has been cancelled by the finance department."
            create_notifications(notification_title,
                                 notification_body, list_of_staff_ids)
            return Response({"message": "Purchase order cancelled successfully", }, status=200)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:
        return Response({"message": "Error cancelling purchase order", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_deposit(request):  # to be continued
    active_user = request.user
    payload = {}
    try:
        company_serial_number = request.data["serial_number"]
        deposit_id = int(request.data["deposit_id"])
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.deposit.delete"):
            deposit_instance = Deposit.objects.get(id=deposit_id)
            deposit_instance.recycle_bin = True
            deposit_instance.save()
            deposit_transaction = deposit_instance.deposit_transaction
            deposit_transaction.recycle_bin = True
            deposit_transaction.save()
            deposit_transaction.account.running_balance = f'{float(deposit_transaction.account.running_balance.replace(",",""))-float(deposit_transaction.transaction_amount.replace(",",""))}'

            if deposit_instance.deposit_source == "sales_revenue":
                customer_order_payment = deposit_transaction.customer_order_payment
                # print(customer_order_payment)
                customer_order = customer_order_payment.customer_order
                customer_order.customer_order_total_amount_paid = f'{float(customer_order.customer_order_total_amount_paid.replace(",",""))-float(deposit_transaction.transaction_amount.replace(",",""))}'
                customer_order.save()
                customer_order_invoice = customer_order.customer_order_invoice
                customer_order_invoice.invoice_amount_paid = f'{float(customer_order_invoice.invoice_amount_paid.replace(",",""))-float(deposit_transaction.transaction_amount.replace(",",""))}'
                customer_order_invoice.invoice_amount_due = f'{float(customer_order_invoice.invoice_amount_due.replace(",",""))+float(deposit_transaction.transaction_amount.replace(",",""))}'
                customer_order_invoice.save()
                customer_order_payment.delete()
                deposit_transaction.account.save()
            # delete jounal entries
            transaction_journal_entries = deposit_transaction.transaction_journal_entries.all()
            for journal_entry in transaction_journal_entries:
                journal_entry.delete()
            return Response({"message": "Deposit instance deleted successfully", }, status=200)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "Error deleting deposit instance", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_expense(request):  # to be continued
    active_user = request.user
    payload = {}
    try:
        company_serial_number = request.data["serial_number"]
        expense_id = int(request.data["expense_id"])
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.expense.delete"):
            expense_instance = Expense.objects.get(id=expense_id)
            expense_instance.recycle_bin = True
            expense_instance.save()
            expense_transaction = expense_instance.expense_transaction
            expense_transaction.recycle_bin = True
            expense_transaction.save()
            expense_transaction.account.running_balance = f'{float(expense_transaction.account.running_balance.replace(",",""))+float(expense_transaction.transaction_amount.replace(",",""))}'
            expense_transaction.account.save()
            if expense_instance.payroll_sheet is not None:
                expense_instance.payroll_sheet.payroll_sheet_payment_settled = False
                expense_instance.payroll_sheet.save()
            if expense_instance.product_purchase_instance.exists():
                for purchase_expense in expense_instance.product_purchase_instance.all():
                    purchase_expense.purchase_amount_paid_to_supplier = f'{float(purchase_expense.purchase_amount_paid_to_supplier.replace(",",""))-float(expense_transaction.transaction_amount.replace(",",""))}'
                    if float(purchase_expense.purchase_amount_paid_to_supplier) < float(purchase_expense.purchase_value_overall):
                        purchase_expense.supplier_payment_settled = False
                    purchase_expense.save()
            if expense_instance.landed_cost_instance is not None:
                expense_instance.landed_cost_instance.cost_amount_paid = f'{float(expense_instance.landed_cost_instance.cost_amount_paid.replace(",",""))-float(expense_transaction.transaction_amount.replace(",",""))}'
                expense_instance.landed_cost_instance.cost_amount_due = f'{float(expense_instance.landed_cost_instance.cost_amount_due.replace(",",""))+float(expense_transaction.transaction_amount.replace(",",""))}'
                if float(expense_instance.landed_cost_instance.cost_amount_paid) < float(expense_instance.landed_cost_instance.cost_value.replace(",", "")):
                    expense_instance.landed_cost_instance.cost_payment_settled = False
                expense_instance.landed_cost_instance.save()
            # delete jounal entries
            transaction_journal_entries = expense_transaction.transaction_journal_entries.all()
            for journal_entry in transaction_journal_entries:
                journal_entry.delete()
            return Response({"message": "Expense instance deleted successfully", }, status=200)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "Error deleting expense instance", }, status=500)


# @api_view(['POST'])
# @authentication_classes([TokenAuthentication])
# @permission_classes([IsAuthenticated])
# def delete_dividend_payment(request):
#     # to be updated
#     active_user = request.user
#     try:
#         company_serial_number = request.data["serial_number"]
#         dividend_id = request.data["dividend_id"]
#         company_profile = CompanyProfile.objects.get(
#             company_serial_number=company_serial_number)
#         staff_profile = StaffProfile.objects.get(user=active_user)
#         if staff_profile.company_department.department_name == "finance_and_accounting" and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
#             dividend_instance = Dividend.objects.get(
#                 id=int(dividend_id))
#             if dividend_instance.recycle_bin != True:
#                 dividend_instance.recycle_bin = True
#                 dividend_instance.save()
#                 account = dividend_instance.account
#                 account.running_balance = f'{float(account.running_balance.replace(",","")) + float(dividend_instance.divident_amount_paid.replace(",",""))}'
#                 account.save()
#                 # delete all related transactions and journal entries
#                 return Response({"message": "Loan instance deleted successfully", }, status=200)
#             else:
#                 dividend_instance.delete()
#                 return Response({"message": "Loan instance permanently deleted successfully", }, status=200)
#         else:
#             return Response({"message": "You are unauthorised to perform this action", }, status=401)
#     except:  # Exception as e:
#         # print(e)
#         return Response({"message": "Error deleting loan instance", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def finance_edit_payroll_sheet(request):
    payroll_sheet_id_to_edit = request.data["payroll_sheet_id_to_edit"]
    payroll_sheet_action = request.data["payroll_sheet_action"]
    payload = {}
    try:
        active_user = request.user
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        payroll_sheet_to_edit = PayrollSheet.objects.get(
            id=int(payroll_sheet_id_to_edit))
        gl_post = {}
        if payroll_sheet_action == "approve":
            payroll_sheet_to_edit.payroll_sheet_approved_by_finance = True
            payroll_sheet_to_edit.save()
            gl_post = post_payroll_accrual(
                staff_profile.company_branch,
                staff_profile,
                payroll_sheet_to_edit,
            )
            list_of_staff_ids = []
            list_of_staff_ids.append(
                payroll_sheet_to_edit.created_by.id)
            notification_title = f"Payroll sheet {payroll_sheet_to_edit.payroll_sheet_number} Approved."
            notification_body = f"The payroll sheet {payroll_sheet_to_edit.payroll_sheet_number} has been approved by the finance department. You can therefore proceed to send payslips to relevant staff."
            create_notifications(notification_title,
                                 notification_body, list_of_staff_ids)
            message = "Payroll sheet approved successfully"
            if gl_post.get("posted"):
                message += " and accrued to the general ledger."
            elif not gl_post.get("skipped"):
                message += (
                    f". GL accrual pending — "
                    f"{gl_post.get('error', 'configure Account Mappings or run Setup Standard COA')}."
                )
            return Response({"message": message, "gl_posting": gl_post}, status=200)
        else:
            payroll_sheet_to_edit.payroll_sheet_approved_by_finance = False
            payroll_sheet_to_edit.save()
            list_of_staff_ids = []
            # get finance department staff
            list_of_staff_ids.append(
                payroll_sheet_to_edit.created_by.id)
            notification_title = f"Cancelled Payroll sheet {payroll_sheet_to_edit.payroll_sheet_number} Approval."
            notification_body = f"The approval of the payroll sheet {payroll_sheet_to_edit.payroll_sheet_number} has been cancelled by the finance department."
            create_notifications(notification_title,
                                 notification_body, list_of_staff_ids)
            return Response({"message": "Payroll sheet edited successfully", }, status=200)
    except:
        return Response({"message": "Error editing payroll sheet", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_customer_order_invoice(request):
    active_user = request.user
    new_invoice_map = {}
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    try:
        company_serial_number = request.data["serial_number"]
        customer_order_id = request.data["customer_order_id"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.customer_order_finance.edit"):
            customer_order_instance = CustomerOrder.objects.get(
                id=int(customer_order_id))
            invoice_amount_due = customer_order_instance.customer_order_total_net_value
            new_invoice_serializer = CustomerOrderInvoiceSerializer(
                data={'customer_order': customer_order_instance.id, 'invoice_amount_due': invoice_amount_due, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            if new_invoice_serializer.is_valid():
                new_invoice = new_invoice_serializer.save()
                new_invoice_map["customer_order_invoice_id"] = str(
                    new_invoice.id)
                new_invoice_map["customer_order_number"] = new_invoice.customer_order.customer_order_number
                new_invoice_map["customer_order_invoice_number"] = new_invoice.invoice_number
                new_invoice_map["customer_order_invoice_amount_due"] = new_invoice.invoice_amount_due
                new_invoice_map["customer_order_invoice_amount_paid"] = new_invoice.invoice_amount_paid
                new_invoice_map["customer_order_invoice_currency"] = new_invoice.invoice_currency
                new_invoice_map["customer_order_invoice_settled"] = "true" if new_invoice.invoice_settled == True else "false"
                new_invoice_map["created_on"] = datetime.strftime(
                    new_invoice.created_on.astimezone(target_timezone), date_format) if new_invoice.created_on is not None else ""
                new_invoice_map["last_updated_on"] = datetime.strftime(
                    new_invoice.last_updated_on.astimezone(target_timezone), date_format) if new_invoice.last_updated_on is not None else ""
                creator_map = {}
                creator_map["staff_id"] = str(
                    new_invoice.created_by.id) if new_invoice.created_by is not None else ""
                creator_map["staff_name"] = f'{new_invoice.created_by.first_name} {new_invoice.created_by.last_name}' if new_invoice.created_by is not None else ""
                creator_map["staff_position"] = new_invoice.created_by.staff_position.position_title if new_invoice.created_by.staff_position is not None else ""
                new_invoice_map["created_by"] = creator_map
                creator_map = {}
                creator_map["staff_id"] = str(
                    new_invoice.last_updated_by.id) if new_invoice.last_updated_by is not None else ""
                creator_map["staff_name"] = f'{new_invoice.last_updated_by.first_name} {new_invoice.last_updated_by.last_name}' if new_invoice.last_updated_by is not None else ""
                creator_map["staff_position"] = new_invoice.last_updated_by.staff_position.position_title if new_invoice.last_updated_by.staff_position is not None else ""
                new_invoice_map["last_updated_by"] = creator_map
                gl_post = post_sales_invoice(
                    staff_profile.company_branch,
                    staff_profile,
                    new_invoice,
                )
                new_invoice_map["gl_posting"] = gl_post
                if gl_post.get("posted"):
                    new_invoice_map["message"] = (
                        f"Invoice for order {customer_order_instance.customer_order_number} "
                        f"created and posted to the general ledger."
                    )
                elif gl_post.get("skipped"):
                    new_invoice_map["message"] = (
                        f"Invoice for order {customer_order_instance.customer_order_number} created successfully."
                    )
                else:
                    new_invoice_map["message"] = (
                        f"Invoice for order {customer_order_instance.customer_order_number} created. "
                        f"GL posting pending — {gl_post.get('error', 'configure Account Mappings or run Setup Standard COA')}."
                    )
                return JsonResponse(new_invoice_map, status=200)
            else:
                return Response({"message": "Error creating invoice", }, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "You are unauthorised to perform this action", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_asset(request):
    date_format = '%d/%m/%Y'
    try:
        active_user = request.user
        company_serial_number = request.data["serial_number"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.asset.add"):
            asset_name = request.data["asset_name"]
            asset_category = request.data["asset_category"]
            asset_serial_number = request.data["asset_serial_number"]
            purchase_date = datetime.strptime(
                request.data["purchase_date"], date_format).strftime("%Y-%m-%d") if len(request.data["purchase_date"]) > 0 else None
            purchase_cost = request.data["purchase_cost"]
            vendor_name = request.data["vendor_name"]
            invoice_number = request.data["invoice_number"]
            useful_life_years = request.data["useful_life_years"]
            residual_value = request.data["residual_value"]
            depreciation_method = request.data["depreciation_method"]
            depreciation_rate = request.data["depreciation_rate"]
            status = request.data["status"]
            asset_serializer = AssetSerializer(data={'asset_name': asset_name, 'asset_category': asset_category, 'serial_number': asset_serial_number, 'purchase_date': purchase_date, 'purchase_cost': purchase_cost, 'vendor_name': vendor_name,
                                               'invoice_number': invoice_number, 'useful_life_years': useful_life_years, 'residual_value': residual_value, 'depreciation_method': depreciation_method, 'depreciation_rate': depreciation_rate, 'status': status, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            if asset_serializer.is_valid():
                asset_serializer.save()
                return Response({"message": "Company asset added successfully", }, status=200)
            else:
                print(asset_serializer.errors)
                return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "Error adding company asset", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_asset(request):
    date_format = '%d/%m/%Y'
    payload = {}
    try:
        active_user = request.user
        company_serial_number = request.data["serial_number"]
        asset_id = request.data["asset_id"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        asset_instance = Asset.objects.get(id=int(asset_id))
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.asset.edit"):
            asset_name = request.data["asset_name"]
            asset_category = request.data["asset_category"]
            asset_serial_number = request.data["asset_serial_number"]
            purchase_date = datetime.strptime(
                request.data["purchase_date"], date_format).strftime("%Y-%m-%d") if len(request.data["purchase_date"]) > 0 else None
            purchase_cost = request.data["purchase_cost"]
            vendor_name = request.data["vendor_name"]
            invoice_number = request.data["invoice_number"]
            useful_life_years = request.data["useful_life_years"]
            residual_value = request.data["residual_value"]
            depreciation_method = request.data["depreciation_method"]
            depreciation_rate = request.data["depreciation_rate"]
            status = request.data["status"]
            asset_serializer = AssetSerializer(instance=asset_instance, data={'asset_name': asset_name, 'asset_category': asset_category, 'serial_number': asset_serial_number, 'purchase_date': purchase_date, 'purchase_cost': purchase_cost, 'vendor_name': vendor_name,
                                               'invoice_number': invoice_number, 'useful_life_years': useful_life_years, 'residual_value': residual_value, 'depreciation_method': depreciation_method, 'depreciation_rate': depreciation_rate, 'status': status, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            if asset_serializer.is_valid():
                asset_serializer.save()
                return Response({"message": "Company asset edited successfully", }, status=200)
            else:
                print(asset_serializer.errors)
                return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "Error editing company asset", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def generate_profit_and_loss_statement(request):
    active_user = request.user
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    payload = {}
    try:
        company_serial_number = request.data["serial_number"]
        financial_year = request.data["financial_year"]
        current_year = int(financial_year)
        # previous_year = current_year-1
        # next_year = current_year+1
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.financial_reports.view"):
            payload = get_financial_year_net_income_values(current_year)
            return Response({"message": "true", "payload": payload}, status=200)
        else:
            return Response({"message": "false", "payload": payload}, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "false", "payload": payload}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_dividend_payment(request):
    active_user = request.user
    payload = {}
    try:
        company_serial_number = request.data["serial_number"]
        dividend_title = request.data["dividend_title"]
        dividend_id = request.data["dividend_id"]
        financial_year = request.data["financial_year"]
        dividend_instance = Dividend.objects.get(id=int(dividend_id))
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        dividend_comment = request.data["dividend_comment"]
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.dividend.edit"):
            dividend_serializer = DividendSerializer(instance=dividend_instance,
                                                     data={'dividend_title': dividend_title, 'financial_year': financial_year, 'dividend_comment': dividend_comment, 'last_updated_by': staff_profile.id})
            if dividend_serializer.is_valid():
                new_dividend = dividend_serializer.save()
                return Response({"message": "Dividend payment edited successfully", }, status=200)
            else:
                # print( deposit_serializer.errors)
                return Response({"message": "Unable to edit dividend payment", }, status=406)
    except Exception as e:
        print(e)
        return Response({"message": "Error editing dividend payment", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_dividend_payment(request):
    active_user = request.user
    try:
        company_serial_number = request.data["serial_number"]
        dividend_title = request.data["dividend_title"]
        dividend_amount_paid = request.data["dividend_amount_paid"]
        account_id = request.data["account_id"]
        dividend_comment = request.data["dividend_comment"]
        financial_year = request.data["financial_year"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.dividend.add"):
            dividend_serializer = DividendSerializer(
                data={'dividend_title': dividend_title, 'dividend_amount_paid': dividend_amount_paid, 'financial_year': financial_year, 'account': int(account_id), 'dividend_comment': dividend_comment, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            if dividend_serializer.is_valid():
                new_dividend = dividend_serializer.save()
                payment_account_instance = ChartOfAccount.objects.get(
                    id=int(account_id))
                transaction_serializer = TransactionSerializer(data={'transaction_mode': 'outflow', 'transaction_amount': dividend_amount_paid, 'dividend': new_dividend.id, 'account': int(
                    account_id), 'transaction_currency': payment_account_instance.account_currency, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
                if transaction_serializer.is_valid():
                    new_transaction = transaction_serializer.save()
                    payment_account_instance.running_balance = f'{float(payment_account_instance.running_balance.replace(",", ""))-float(dividend_amount_paid.replace(",", ""))}'
                    payment_account_instance.save()
                    # create journal entry
                    journal_account_credit = None

                    if payment_account_instance.is_mpesa_account == True:
                        journal_account_credit, created = JournalAccountCredit.objects.get_or_create(
                            account_name="m_pesa")
                        # print("executed well")
                    else:
                        journal_account_credit, created = JournalAccountCredit.objects.get_or_create(
                            account_name="bank")

                    journal_account_debit, created = JournalAccountDebit.objects.get_or_create(
                        account_name="retained_earnings")
                    # print("error here")
                    journal_entry_serializer = Journal_EntrySerializer(
                        data={'company_branch': staff_profile.company_branch.id, 'transaction': new_transaction.id, 'journal_reference': dividend_title, 'journal_tag': 'Dividend payment', 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
                    if journal_entry_serializer.is_valid():
                        new_journal_entry = journal_entry_serializer.save()
                        journal_account_debit_id = journal_account_debit.id if journal_account_debit is not None else None
                        debit_entry_serializer = DebitEntrySerializer(
                            data={'journal_entry': new_journal_entry.id, 'journal_account_debit': journal_account_debit_id, 'debit_amount': dividend_amount_paid})
                        if debit_entry_serializer.is_valid():
                            debit_entry_serializer.save()
                        journal_account_credit_id = journal_account_credit.id if journal_account_credit is not None else None
                        credit_entry_serializer = CreditEntrySerializer(
                            data={'journal_entry': new_journal_entry.id, 'journal_account_credit': journal_account_credit_id, 'credit_amount': dividend_amount_paid})
                        if credit_entry_serializer.is_valid():
                            credit_entry_serializer.save()
                return Response({"message": "Dividend payment created successfully", }, status=200)
            else:
                # print( deposit_serializer.errors)
                return Response({"message": "Unable to create dividend payment", }, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "Error creating dividend payment", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def generate_balance_sheet(request):
    active_user = request.user
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    payload = {}
    try:
        company_serial_number = request.data["serial_number"]
        financial_year = request.data["financial_year"]
        current_year = int(financial_year)
        previous_year = current_year-1
        next_year = current_year+1
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.financial_reports.view"):
            cash_and_cash_equivalents = 0.0
            all_accounts = ChartOfAccount.objects.filter(recycle_bin=False)
            for account in all_accounts:
                cash_and_cash_equivalents += float(
                    account.running_balance.replace(",", ""))
            account_receivables = 0.0
            all_customer_orders = CustomerOrder.objects.filter(
                recycle_bin=False, customer_order_approved=True,)
            for customer_order in all_customer_orders:
                order_net_value = float(
                    customer_order.customer_order_total_net_value.replace(",", ""))
                order_amount_paid = float(
                    customer_order.customer_order_total_amount_paid.replace(",", ""))
                if order_amount_paid < order_net_value:
                    account_receivables += (order_net_value -
                                            order_amount_paid)
            inventory_value = calculate_closing_inventory_value(
                current_year)
            asset_value = 0.0
            all_assets = Asset.objects.filter(recycle_bin=False,)
            for asset in all_assets:
                if asset.status != "disposed":
                    if datetime.now().year <= asset.purchase_date.year+int(asset.useful_life_years):
                        asset_current_value = calculate_single_asset_value_current(
                            current_year, asset)
                        asset_value += asset_current_value
            # liabilities
            # non_current liabilities
            loan_portfolio = LoanPortfolio.objects.filter(recycle_bin=False)
            total_loan_amount_due = 0.0
            for loan in loan_portfolio:
                if float(loan.principal_paid.replace(",", "")) >= float(loan.total_repayment_amount.replace(",", "")):
                    total_loan_amount_due += float(loan.total_repayment_amount(
                        ",", "")) - float(loan.principal_paid.replace(",", ""))
            # acccounts payable
            accounts_payable = 0.0
            all_purchase_orders = PurchaseOrder.objects.filter(
                recycle_bin=False)
            for purchase_order in all_purchase_orders:
                purchase_order_product_instances = purchase_order.purchase_order_product_instances.filter(
                    recycle_bin=False)
                for product_purchase in purchase_order_product_instances:
                    if product_purchase.supplier_payment_settled != True:
                        accounts_payable += (float(product_purchase.purchase_value_overall.replace(",", "")) - float(
                            product_purchase.purchase_amount_paid_to_supplier.replace(",", "")))*float(product_purchase.exchange_rate.replace(",", ""))
            # calculate income tax payable
            # gross sales
            current_year_gross_sales = CustomerOrder.objects.filter(
                recycle_bin=False, customer_order_approved=True, created_on__year=current_year)
            gross_sales = 0.00
            vehicle_and_equipment_lease_revenue = 0.00
            for sale in current_year_gross_sales:
                gross_sales += float(
                    sale.customer_order_total_net_value.replace(",", ""))
            # vehicle and equipment lease
            current_year_vehicle_and_equipment_lease_revenue = Deposit.objects.filter(
                recycle_bin=False, deposit_source="vehicle_and_equipment_lease_revenue", created_on__year=current_year)
            for vehicle_and_equipment_lease in current_year_vehicle_and_equipment_lease_revenue:
                vehicle_and_equipment_lease_revenue += float(
                    vehicle_and_equipment_lease.deposit_amount.replace(",", ""))
            # opening_inventory_value = calculate_product_cost_of_opening_inventory(
            #     previous_year,)
            # purchase_value_for_current_year = calculate_purchase_order_value_for_the_year(
            #     current_year)
            # closing_inventory_value = calculate_closing_inventory_value(
            #     current_year)
            # cost_of_goods_sold = opening_inventory_value + \
            #     purchase_value_for_current_year-closing_inventory_value
            all_expenses_for_financial_year = Expense.objects.filter(
                recycle_bin=False, created_on__year=current_year)
            total_expenses = 0.0
            for expense in all_expenses_for_financial_year:
                total_expenses += float(
                    expense.expense_transaction.transaction_amount.replace(",", ""))*float(
                    expense.expense_transaction.exchange_rate.replace(",", ""))
            # asset wear and tear allowances
            asset_wear_and_tear_allowance = (1-0.3)*asset_value

            # owners equity
            share_capital = 0.0
            c = CurrencyRates()
            all_deposits = Deposit.objects.filter(recycle_bin=False)
            for deposit in all_deposits:
                if deposit.deposit_source == "share_capital":
                    share_capital += float(deposit.deposit_transaction.transaction_amount.replace(",", "")) if deposit.deposit_transaction.transaction_currency == "kes" else float(
                        deposit.deposit_transaction.transaction_amount.replace(",", ""))*c.get_rate(f'{deposit.deposit_transaction.transaction_currency.upper()}', 'KES')
            # retained_earnings
            retained_earnings_begining = RetainedEarningFinancialYearOpening.objects.get(
                financial_year=str(current_year))
            financial_year_dividends_paid = Dividend.objects.filter(
                recycle_bin=False, financial_year=str(current_year))
            total_dividends_paid = 0.0
            for dividend in financial_year_dividends_paid:
                total_dividends_paid += float(
                    dividend.dividend_amount_paid.replace(",", ""))
            # net income
            net_income = 0.0
            net_income_values_map = get_financial_year_net_income_values(
                current_year)
            net_income = float(net_income_values_map["gross_sales"])+float(
                net_income_values_map["vehicle_and_equipment_lease_revenue"])-((float(net_income_values_map["purchase_value_for_current_year"])-(float(net_income_values_map["closing_inventory_value"])+float(net_income_values_map["opening_inventory_value"])))+float(net_income_values_map["financial_year_operational_expenses"])+float(net_income_values_map["financial_year_interest_expenses"])+float(net_income_values_map["financial_year_tax_and_licence_expenses"])+float(net_income_values_map["financial_year_salary_and_remuneration_expenses"])+float(net_income_values_map["depreciation_and_armotization_cost"]))
            retained_earnings_end_of_year = float(
                retained_earnings_begining.opening_quantity.replace(",", ""))+net_income-total_dividends_paid
            allowable_expenses, non_allowable_expenses = get_expenses_in_types(
                current_year)
            income_taxes_payable = (
                gross_sales+float(
                    net_income_values_map["vehicle_and_equipment_lease_revenue"])-allowable_expenses-asset_wear_and_tear_allowance+non_allowable_expenses+calculate_asset_depreciation(current_year))*0.3
            payload["cash_and_cash_equivalents"] = str(
                cash_and_cash_equivalents)
            payload["account_receivables"] = str(
                account_receivables)
            payload["inventory_value"] = str(
                inventory_value)
            payload["asset_value"] = str(
                asset_value)
            payload["loan_amount_due"] = str(
                total_loan_amount_due)
            payload["accounts_payable"] = str(
                accounts_payable)
            payload["income_taxes_payable"] = str(
                income_taxes_payable)
            payload["retained_earnings_end_of_year"] = str(
                retained_earnings_end_of_year)
            payload["share_capital"] = str(
                share_capital)
            return Response({"message": "true", "payload": payload}, status=200)
        else:
            return Response({"message": "false", "payload": payload}, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "false", "payload": payload}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def generate_cash_flow_statement(request):
    active_user = request.user
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    payload = {}
    try:
        company_serial_number = request.data["serial_number"]
        financial_year = request.data["financial_year"]
        current_year = int(financial_year)
        previous_year = current_year-1
        next_year = current_year+1
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = _resolve_staff_for_finance(active_user)
        if not staff_profile:
            return _finance_staff_missing_response(payload)
        if user_has_permission(staff_profile, "finance_and_accounting.financial_reports.view"):
            # cash flows from operating activities
            cash_sale_of_goods_and_services = 0.00
            # gross sales
            current_year_sales_payment = CustomerOrderPayment.objects.filter(
                recycle_bin=False, created_on__year=current_year)
            gross_sales = 0.00
            vehicle_and_equipment_lease_revenue = 0.00
            for sale in current_year_sales_payment:
                gross_sales += float(
                    sale.payment_amount.replace(",", ""))
            # vehicle and equipment lease
            current_year_vehicle_and_equipment_lease_revenue = Deposit.objects.filter(
                recycle_bin=False, deposit_source="vehicle_and_equipment_lease_revenue", created_on__year=current_year)
            for vehicle_and_equipment_lease in current_year_vehicle_and_equipment_lease_revenue:
                vehicle_and_equipment_lease_revenue += float(
                    vehicle_and_equipment_lease.deposit_amount.replace(",", ""))
            cash_sale_of_goods_and_services = gross_sales + \
                vehicle_and_equipment_lease_revenue
            # cash outflows from investment activities
            all_expenses_for_financial_year = Expense.objects.filter(
                recycle_bin=False, created_on__year=current_year)
            cash_payment_for_inventory_supply_expenses = 0.00
            salaries_and_wages_paid = 0.00
            capital_expenditure = 0.00
            loan_repayments = 0.00
            taxes_and_licences_payment = 0.00
            operating_expenses = 0.00
            for expense in all_expenses_for_financial_year:
                if expense.expense_type == "purchase_expense":
                    cash_payment_for_inventory_supply_expenses += float(
                        expense.expense_transaction.transaction_amount.replace(",", ""))*float(
                        expense.expense_transaction.exchange_rate.replace(",", ""))
                elif expense.expense_type == "salary_expense":
                    salaries_and_wages_paid += float(
                        expense.expense_transaction.transaction_amount.replace(",", ""))*float(
                        expense.expense_transaction.exchange_rate.replace(",", ""))
                elif expense.expense_type == "capital_expenditure":
                    capital_expenditure += float(
                        expense.expense_transaction.transaction_amount.replace(",", ""))*float(
                        expense.expense_transaction.exchange_rate.replace(",", ""))
                elif expense.expense_type == "loan_repayment_expense":
                    loan_repayments += float(
                        expense.expense_transaction.transaction_amount.replace(",", ""))*float(
                        expense.expense_transaction.exchange_rate.replace(",", ""))
                elif expense.expense_type == "tax_and_license_expense":
                    taxes_and_licences_payment += float(
                        expense.expense_transaction.transaction_amount.replace(",", ""))*float(
                        expense.expense_transaction.exchange_rate.replace(",", ""))
                else:
                    operating_expenses += float(
                        expense.expense_transaction.transaction_amount.replace(",", ""))*float(
                        expense.expense_transaction.exchange_rate.replace(",", ""))
            financial_year_dividends_paid = Dividend.objects.filter(
                recycle_bin=False, financial_year=str(current_year))
            total_dividends_paid = 0.0
            for dividend in financial_year_dividends_paid:
                total_dividends_paid += float(
                    dividend.dividend_amount_paid.replace(",", ""))
            proceeds_from_loans = 0.00
            all_loan_deposits = Deposit.objects.filter(
                recycle_bin=False, deposit_source="loans", created_on__year=current_year)
            for loan in all_loan_deposits:
                proceeds_from_loans += float(
                    loan.deposit_amount.replace(",", ""))
            cfo = {}
            cfi = {}
            cff = {}
            cfo["cash_sale_of_goods_and_services"] = str(
                cash_sale_of_goods_and_services)
            cfo["cash_payment_for_inventory_supply_expenses"] = str(
                cash_payment_for_inventory_supply_expenses)
            cfo["salaries_and_wages_paid"] = str(
                salaries_and_wages_paid)
            cfo["operating_expenses"] = str(
                operating_expenses)
            cfo["taxes_and_licences_payment"] = str(
                taxes_and_licences_payment)
            cfi["capital_expenditure"] = str(capital_expenditure)
            cff["loan_repayments"] = str(loan_repayments)
            cff["total_dividends_paid"] = str(total_dividends_paid)
            cff["proceeds_from_loans"] = str(proceeds_from_loans)
            payload["cfo"] = cfo
            payload["cfi"] = cfi
            payload["cff"] = cff
            return Response({"message": "true", "payload": payload}, status=200)
        else:
            return Response({"message": "false", "payload": payload}, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "false", "payload": payload}, status=500)
