from megawatt_agents.models import AgentAccountManager
from procurement.models import PurchaseOrder, Supplier
from procurement.serializers import productPurchaseInstanceSerializer, purchaseOrderSerializer
from system_administration.models import CompanyDepartment
from access_control.permissions import user_has_permission
from system_administration.serializers import UserSerializer
from system_administration.utils import create_folder_if_not_exists, create_notifications, generate_random_string, get_hod_technical_sales_ids, get_price_per_unit_for_customer_type, get_product_discount_per_unit, get_product_vat_per_unit, get_staff_profile_data, send_email_signup
from warehouse_management.models import Category, Product
from warehouse_management.requisition_helpers import enrich_purchase_requisition_map
from warehouse_management.stock_availability import attach_branch_stock_fields, validate_line_items_stock
from warehouse_management.serializers import StockRequisitionInstanceSerializer, StockRequisitionSerializer
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 FileResponse, Http404, JsonResponse
from django.contrib.auth import authenticate, login, logout
import os
import pytz
from django.db.models import Q, Prefetch
import logging

logger = logging.getLogger(__name__)

def _empty_account_manager_map():
    return {"staff_id": "", "staff_name": ""}


def _attach_empty_account_manager(customer_profile_map):
    customer_profile_map["customer_account_manager"] = _empty_account_manager_map()
    return customer_profile_map


def _paginated_company_customers(company_profile, start_index=0, last_index=0):
    qs = company_profile.company_customers.filter(recycle_bin=False).order_by("-id")
    if last_index != 0:
        return list(qs[start_index:last_index])
    return list(qs[start_index:])



def _sum_char_field_values(queryset, field_name):
    total = 0.0
    for val in queryset.values_list(field_name, flat=True):
        try:
            total += float(val or 0)
        except (TypeError, ValueError):
            continue
    return round(total, 2)


def _sales_quotations_qs(staff_profile):
    if staff_profile.is_head_of_department:
        return SalesQuotation.objects.filter(recycle_bin=False)
    return staff_profile.sales_quotation_created_by.filter(recycle_bin=False)


def _customer_orders_qs(staff_profile):
    if staff_profile.is_head_of_department:
        return CustomerOrder.objects.filter(recycle_bin=False, agent_profile=None)
    return staff_profile.customer_offline_order_created_by.filter(
        recycle_bin=False, agent_profile=None)


def _build_sales_pipeline_summary(staff_profile, customer_profiles_list):
    quotations_qs = _sales_quotations_qs(staff_profile)
    orders_qs = _customer_orders_qs(staff_profile)

    draft_quotes_qs = quotations_qs.filter(
        sales_quotation_approved=False,
        quotation_price_change_request_active=False,
    )
    negotiation_qs = quotations_qs.filter(
        sales_quotation_approved=False,
        quotation_price_change_request_active=True,
    )
    approved_quotes_qs = quotations_qs.filter(sales_quotation_approved=True)

    cancelled_orders_qs = orders_qs.filter(
        Q(customer_order_cancelled_by_customer=True)
        | Q(customer_order_cancelled_by_sales_team=True)
    )
    active_orders_qs = orders_qs.exclude(
        Q(customer_order_cancelled_by_customer=True)
        | Q(customer_order_cancelled_by_sales_team=True)
    )
    pending_orders_qs = active_orders_qs.filter(customer_order_approved=False)
    processing_orders_qs = active_orders_qs.filter(
        customer_order_approved=True,
        customer_ordered_delivered_to_destination=False,
        customer_order_picked_by_customer=False,
    )
    closed_won_qs = active_orders_qs.filter(
        Q(customer_ordered_delivered_to_destination=True)
        | Q(customer_order_picked_by_customer=True)
    )

    draft_value = _sum_char_field_values(draft_quotes_qs, "quotation_net_value")
    negotiation_value = _sum_char_field_values(negotiation_qs, "quotation_net_value")
    approved_value = _sum_char_field_values(approved_quotes_qs, "quotation_net_value")
    pending_value = _sum_char_field_values(pending_orders_qs, "customer_order_total_net_value")
    processing_value = _sum_char_field_values(processing_orders_qs, "customer_order_total_net_value")
    closed_value = _sum_char_field_values(closed_won_qs, "customer_order_total_net_value")
    cancelled_value = _sum_char_field_values(cancelled_orders_qs, "customer_order_total_net_value")

    prospects_count = len(customer_profiles_list)
    open_deals_count = (
        draft_quotes_qs.count()
        + negotiation_qs.count()
        + approved_quotes_qs.count()
        + pending_orders_qs.count()
        + processing_orders_qs.count()
    )
    total_pipeline_value = round(
        draft_value + negotiation_value + approved_value + pending_value + processing_value, 2)
    closed_won_value = closed_value
    conversion_rate = round(
        (closed_won_qs.count() / open_deals_count * 100) if open_deals_count else 0, 1)

    stages = [
        {
            "id": "prospects",
            "label": "Prospects",
            "count": prospects_count,
            "value": 0,
            "color": "#7367F0",
        },
        {
            "id": "draft_quotes",
            "label": "Draft Quotes",
            "count": draft_quotes_qs.count(),
            "value": draft_value,
            "color": "#FF9F43",
        },
        {
            "id": "negotiation",
            "label": "Negotiation",
            "count": negotiation_qs.count(),
            "value": negotiation_value,
            "color": "#00CFE8",
        },
        {
            "id": "approved_quotes",
            "label": "Approved Quotes",
            "count": approved_quotes_qs.count(),
            "value": approved_value,
            "color": "#808390",
        },
        {
            "id": "pending_orders",
            "label": "Pending Orders",
            "count": pending_orders_qs.count(),
            "value": pending_value,
            "color": "#C2185B",
        },
        {
            "id": "processing",
            "label": "Fulfillment",
            "count": processing_orders_qs.count(),
            "value": processing_value,
            "color": "#28C76F",
        },
        {
            "id": "closed_won",
            "label": "Closed Won",
            "count": closed_won_qs.count(),
            "value": closed_value,
            "color": "#2E7D32",
        },
        {
            "id": "cancelled",
            "label": "Cancelled",
            "count": cancelled_orders_qs.count(),
            "value": cancelled_value,
            "color": "#EA5455",
        },
    ]

    customer_type_counts = {}
    for customer in customer_profiles_list:
        ctype = customer.get("customer_type") or "unknown"
        customer_type_counts[ctype] = customer_type_counts.get(ctype, 0) + 1
    customer_types = [
        {"customer_type": ctype, "count": count}
        for ctype, count in sorted(customer_type_counts.items(), key=lambda item: item[1], reverse=True)
    ]

    monthly_map = {}
    for quotation in quotations_qs.order_by("-created_on")[:120]:
        if quotation.created_on is None:
            continue
        month_key = quotation.created_on.strftime("%Y-%m")
        bucket = monthly_map.setdefault(month_key, {"quotations": 0, "orders": 0, "value": 0.0})
        bucket["quotations"] += 1
        try:
            bucket["value"] += float(quotation.quotation_net_value or 0)
        except (TypeError, ValueError):
            pass
    for order in orders_qs.order_by("-created_on")[:120]:
        if order.created_on is None:
            continue
        month_key = order.created_on.strftime("%Y-%m")
        bucket = monthly_map.setdefault(month_key, {"quotations": 0, "orders": 0, "value": 0.0})
        bucket["orders"] += 1
        try:
            bucket["value"] += float(order.customer_order_total_net_value or 0)
        except (TypeError, ValueError):
            pass

    monthly_trend = []
    for month_key in sorted(monthly_map.keys())[-6:]:
        month_data = monthly_map[month_key]
        monthly_trend.append({
            "month": month_key,
            "label": datetime.strptime(month_key, "%Y-%m").strftime("%b %Y"),
            "quotations": month_data["quotations"],
            "orders": month_data["orders"],
            "value": round(month_data["value"], 2),
        })

    def _stage_for_quotation(quotation):
        if quotation.quotation_price_change_request_active and not quotation.sales_quotation_approved:
            return "negotiation"
        if quotation.sales_quotation_approved:
            return "approved_quotes"
        return "draft_quotes"

    def _stage_for_order(order):
        if order.customer_order_cancelled_by_customer or order.customer_order_cancelled_by_sales_team:
            return "cancelled"
        if order.customer_ordered_delivered_to_destination or order.customer_order_picked_by_customer:
            return "closed_won"
        if order.customer_order_approved:
            return "processing"
        return "pending_orders"

    recent_deals = []
    for quotation in quotations_qs.select_related("customer_profile").order_by("-created_on")[:12]:
        customer = quotation.customer_profile
        customer_name = ""
        if customer is not None:
            customer_name = f"{customer.customer_first_name} {customer.customer_last_name}".strip()
        try:
            deal_value = float(quotation.quotation_net_value or 0)
        except (TypeError, ValueError):
            deal_value = 0.0
        recent_deals.append({
            "id": str(quotation.id),
            "type": "quotation",
            "number": quotation.sales_quotation_number,
            "customer": customer_name or "—",
            "value": deal_value,
            "stage": _stage_for_quotation(quotation),
            "created_on": quotation.created_on.isoformat() if quotation.created_on else "",
        })
    for order in orders_qs.select_related("customer_profile").order_by("-created_on")[:12]:
        customer = order.customer_profile
        customer_name = ""
        if customer is not None:
            customer_name = f"{customer.customer_first_name} {customer.customer_last_name}".strip()
        try:
            deal_value = float(order.customer_order_total_net_value or 0)
        except (TypeError, ValueError):
            deal_value = 0.0
        recent_deals.append({
            "id": str(order.id),
            "type": "order",
            "number": order.customer_order_number,
            "customer": customer_name or "—",
            "value": float(order.customer_order_total_net_value or 0),
            "stage": _stage_for_order(order),
            "created_on": order.created_on.isoformat() if order.created_on else "",
        })
    recent_deals.sort(key=lambda deal: deal.get("created_on") or "", reverse=True)
    recent_deals = recent_deals[:10]

    pipeline_deals_by_stage = {stage["id"]: [] for stage in stages}
    for quotation in quotations_qs.select_related("customer_profile").order_by("-created_on")[:80]:
        stage_id = _stage_for_quotation(quotation)
        if len(pipeline_deals_by_stage.get(stage_id, [])) >= 4:
            continue
        customer = quotation.customer_profile
        customer_name = ""
        if customer is not None:
            customer_name = f"{customer.customer_first_name} {customer.customer_last_name}".strip()
        try:
            deal_value = float(quotation.quotation_net_value or 0)
        except (TypeError, ValueError):
            deal_value = 0.0
        pipeline_deals_by_stage.setdefault(stage_id, []).append({
            "id": str(quotation.id),
            "type": "quotation",
            "number": quotation.sales_quotation_number,
            "customer": customer_name or "—",
            "value": deal_value,
            "stage": stage_id,
            "created_on": quotation.created_on.isoformat() if quotation.created_on else "",
        })
    for order in orders_qs.select_related("customer_profile").order_by("-created_on")[:80]:
        stage_id = _stage_for_order(order)
        if len(pipeline_deals_by_stage.get(stage_id, [])) >= 4:
            continue
        customer = order.customer_profile
        customer_name = ""
        if customer is not None:
            customer_name = f"{customer.customer_first_name} {customer.customer_last_name}".strip()
        try:
            deal_value = float(order.customer_order_total_net_value or 0)
        except (TypeError, ValueError):
            deal_value = 0.0
        pipeline_deals_by_stage.setdefault(stage_id, []).append({
            "id": str(order.id),
            "type": "order",
            "number": order.customer_order_number,
            "customer": customer_name or "—",
            "value": deal_value,
            "stage": stage_id,
            "created_on": order.created_on.isoformat() if order.created_on else "",
        })

    return {
        "prospects_count": prospects_count,
        "total_pipeline_value": total_pipeline_value,
        "closed_won_value": closed_won_value,
        "open_deals_count": open_deals_count,
        "conversion_rate": conversion_rate,
        "stages": stages,
        "recent_deals": recent_deals,
        "monthly_trend": monthly_trend,
        "customer_types": customer_types,
        "deals_by_stage": pipeline_deals_by_stage,
    }


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def sales_dashboard_home(request):
    # target_timezone = pytz.timezone('Africa/Nairobi')
    # date_format = '%d/%m/%Y, %H:%M'
    company_serial_number = request.data.get("serial_number", "")
    active_user = request.user
    payload = {}
    company_profile_map = {}
    customer_profile_map = {}
    customer_profiles_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 = StaffProfile.objects.get(user=active_user)
        department_name = staff_profile.company_department.department_name if staff_profile.company_department else ""
        if user_has_permission(staff_profile, "sales_and_marketing.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_customer_profiles = []
            all_agent_customers = 0
            all_agent_profiles = AgentAccountManager.objects.filter(
                staff_profile=staff_profile).filter(agent_profile__isnull=False, agent_profile__recycle_bin=False)
            for agent in all_agent_profiles:
                all_agent_customers += agent.agent_profile.agent_managing_customer_profile.filter(
                    recycle_bin=False).count()
            all_customer_profiles = list(
                company_profile.company_customers.filter(recycle_bin=False).order_by("-id")
            )
            for customer in all_customer_profiles:
                customer_profile_map = {}
                customer_profile_map["customer_profile_id"] = str(
                    customer.id)
                customer_profile_map["customer_type"] = str(
                    customer.customer_type)
                customer_profiles_list.append(customer_profile_map)
            company_purchase_orders = company_profile.company_purchase_orders.filter(
                recycle_bin=False).count()
            all_suppliers = Supplier.objects.filter(
                recycle_bin=False).count()
            all_categories = Category.objects.filter(
                recycle_bin=False).count()
            all_products = Product.objects.filter(
                recycle_bin=False).count()
            all_sale_quotations = SalesQuotation.objects.filter(
                recycle_bin=False).count() if staff_profile.is_head_of_department == True else staff_profile.sales_quotation_created_by.filter(
                recycle_bin=False).count()
            all_customer_orders = CustomerOrder.objects.filter(
                recycle_bin=False, agent_profile=None).count() if staff_profile.is_head_of_department == True else staff_profile.customer_offline_order_created_by.filter(
                recycle_bin=False, agent_profile=None).count()
            all_agent_orders = CustomerOrder.objects.filter(
                recycle_bin=False, agent_profile__isnull=False).count() if staff_profile.is_head_of_department == True else staff_profile.customer_offline_order_created_by.filter(
                recycle_bin=False, agent_profile__isnull=False).count()
            payload["customer_profiles_list"] = customer_profiles_list
            payload["company_profile"] = company_profile_map
            payload["company_purchase_orders"] = f'{company_purchase_orders}'
            payload["all_suppliers"] = f'{all_suppliers}'
            payload["all_categories"] = f'{all_categories}'
            payload["all_products"] = f'{all_products}'
            payload["all_sale_quotations"] = f'{all_sale_quotations}'
            payload["all_customer_orders"] = f'{all_customer_orders}'
            payload["all_agent_orders"] = f'{all_agent_orders}'
            payload["all_agent_profiles"] = f'{all_agent_profiles.count()}'
            payload["all_agent_customers"] = f'{all_agent_customers}'
            payload["active_staff_profile_data"] = active_staff_profile_data
            payload["pipeline"] = _build_sales_pipeline_summary(
                staff_profile, customer_profiles_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("sales_dashboard_home failed")
        return Response({"message": "false", "payload": payload}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def sales_customer_search(request):
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    company_serial_number = request.data["serial_number"]
    search_term = request.data["search_term"]
    active_user = request.user
    payload = {}
    creator_map = {}
    customer_profile_map = {}
    customer_profiles_list = []
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        # if staff_profile.company_department.department_name == "sales" and company_profile:
        all_customer_profiles = company_profile.company_customers.filter(Q(customer_first_name__icontains=search_term) | Q(customer_last_name__icontains=search_term) | Q(company_name__icontains=search_term) | Q(phone_number__icontains=search_term),
                                                                         recycle_bin=False).order_by(
            "-id")
        for customer_profile in all_customer_profiles:
            customer_profile_map = {}
            customer_shipping_address_list = []
            customer_documents = customer_profile.customer_documents.all().order_by("-id")
            kra_pin_certificate_path = ""
            certificate_of_registration_path = ""
            if customer_documents is not None:
                for customer_doc in customer_documents:
                    if customer_doc.document_type == "pin_certificate":
                        kra_pin_certificate_path = customer_doc.saved_document_path
                        break
                for customer_doc in customer_documents:
                    if customer_doc.document_type == "certificate_of_registration":
                        certificate_of_registration_path = customer_doc.saved_document_path
                        break
            customer_profile_map["customer_profile_id"] = str(
                customer_profile.id)
            customer_profile_map["customer_first_name"] = customer_profile.customer_first_name
            customer_profile_map["customer_last_name"] = customer_profile.customer_last_name
            customer_profile_map["email_address"] = customer_profile.email_address
            customer_profile_map["phone_number"] = customer_profile.phone_number
            customer_profile_map["customer_title"] = customer_profile.customer_title
            customer_profile_map["company_name"] = customer_profile.company_name
            customer_profile_map["customer_type"] = customer_profile.customer_type
            customer_profile_map["kra_pin"] = customer_profile.kra_pin
            customer_profile_map["kra_pin_certificate_path"] = kra_pin_certificate_path
            customer_profile_map["certificate_of_registration_number"] = customer_profile.certificate_of_registration_number
            customer_profile_map["certificate_of_registration_path"] = certificate_of_registration_path
            customer_profile_map["is_profile_set"] = "true" if customer_profile.is_profile_set == True else "false"
            customer_profile_map["created_on"] = datetime.strftime(
                customer_profile.created_on.astimezone(target_timezone), date_format) if customer_profile.created_on is not None else ""
            customer_profile_map["last_updated_on"] = datetime.strftime(
                customer_profile.last_updated_on.astimezone(target_timezone), date_format) if customer_profile.last_updated_on is not None else ""
            _attach_empty_account_manager(customer_profile_map)
            customer_profiles_list.append(customer_profile_map)
        payload["customer_profiles_list"] = customer_profiles_list
        return Response({"message": "true", "payload": payload}, status=200)
        # else:
        #     return Response({"message": "false", "payload": payload}, status=401)
    except:
        return Response({"message": "false", "payload": payload}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def sales_customer_profiles(request):
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    company_serial_number = request.data["serial_number"]
    page_index = request.data.get("pageIndex", "1")
    active_user = request.user
    payload = {}
    creator_map = {}
    customer_profile_map = {}
    customer_profiles_list = []
    start_index = 0
    last_index = 0
    try:
        if page_index == "1":
            start_index = 0
            last_index = 20
        elif page_index == "2":
            start_index = 20
            last_index = 40
        elif page_index == "3":
            start_index = 40
            last_index = 60
        elif page_index == "4":
            start_index = 60
            last_index = 80
        else:
            start_index = 80
            last_index = 0
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        if user_has_permission(staff_profile, "sales_and_marketing.customer.view"):
            all_customer_profiles = []
            all_customer_profiles = _paginated_company_customers(company_profile, start_index, last_index)
            for customer_profile in all_customer_profiles:
                customer_profile_map = {}
                customer_shipping_address_list = []
                customer_documents = customer_profile.customer_documents.all().order_by("-id")
                kra_pin_certificate_path = ""
                certificate_of_registration_path = ""
                if customer_documents is not None:
                    for customer_doc in customer_documents:
                        if customer_doc.document_type == "pin_certificate":
                            kra_pin_certificate_path = customer_doc.saved_document_path
                            break
                    for customer_doc in customer_documents:
                        if customer_doc.document_type == "certificate_of_registration":
                            certificate_of_registration_path = customer_doc.saved_document_path
                            break
                customer_profile_map["customer_profile_id"] = str(
                    customer_profile.id)
                customer_profile_map["customer_first_name"] = customer_profile.customer_first_name
                customer_profile_map["customer_last_name"] = customer_profile.customer_last_name
                customer_profile_map["email_address"] = customer_profile.email_address
                customer_profile_map["phone_number"] = customer_profile.phone_number
                customer_profile_map["customer_title"] = customer_profile.customer_title
                customer_profile_map["company_name"] = customer_profile.company_name
                customer_profile_map["customer_type"] = customer_profile.customer_type
                customer_profile_map["kra_pin"] = customer_profile.kra_pin
                customer_profile_map["kra_pin_certificate_path"] = kra_pin_certificate_path
                customer_profile_map["certificate_of_registration_number"] = customer_profile.certificate_of_registration_number
                customer_profile_map["certificate_of_registration_path"] = certificate_of_registration_path
                customer_profile_map["is_profile_set"] = "true" if customer_profile.is_profile_set == True else "false"
                customer_profile_map["created_on"] = datetime.strftime(
                    customer_profile.created_on.astimezone(target_timezone), date_format) if customer_profile.created_on is not None else ""
                customer_profile_map["last_updated_on"] = datetime.strftime(
                    customer_profile.last_updated_on.astimezone(target_timezone), date_format) if customer_profile.last_updated_on is not None else ""
                _attach_empty_account_manager(customer_profile_map)
                customer_profiles_list.append(customer_profile_map)
            payload["customer_profiles_list"] = customer_profiles_list
            return Response({"message": "true", "payload": payload}, status=200)
        else:
            return Response({"message": "false", "payload": payload}, status=401)
    except:
        return Response({"message": "false", "payload": payload}, status=500)


def _sales_product_pricing_map(product):
    try:
        product_pricing = product.product_pricing
    except ProductPricing.DoesNotExist:
        product_pricing = None
    if product_pricing is None:
        return {
            "product_pricing_id": "",
            "product_net_price": "",
            "product_net_price_technician": "",
            "product_net_price_reseller": "",
            "product_net_price_financier": "",
            "product_net_price_engineering_procurement_contractor": "",
            "product_net_price_hydraulic_engineers": "",
        }
    return {
        "product_pricing_id": str(product_pricing.id),
        "product_net_price": product_pricing.product_net_price,
        "product_net_price_technician": product_pricing.product_net_price_technician,
        "product_net_price_reseller": product_pricing.product_net_price_reseller,
        "product_net_price_financier": product_pricing.product_net_price_financier,
        "product_net_price_engineering_procurement_contractor": product_pricing.product_net_price_engineering_procurement_contractor,
        "product_net_price_hydraulic_engineers": product_pricing.product_net_price_hydraulic_engineers,
    }


def _sales_product_discount_map(product):
    try:
        product_discount = product.product_discount
    except ProductDiscount.DoesNotExist:
        product_discount = None
    if product_discount is None:
        return {
            "product_discount_id": "",
            "discount_type": "",
            "discount_value": "",
        }
    return {
        "product_discount_id": str(product_discount.id),
        "discount_type": product_discount.discount_type,
        "discount_value": product_discount.discount_value,
    }


def _sales_product_vat_map(product):
    try:
        product_vat = product.product_vat
    except ProductVAT.DoesNotExist:
        product_vat = None
    if product_vat is None:
        return {
            "product_vat_id": "",
            "vat_percentage_value": "",
        }
    return {
        "product_vat_id": str(product_vat.id),
        "vat_percentage_value": product_vat.vat_percentage_value,
    }


def _sales_product_map(product, company_branch=None):
    product_map = {
        "product_id": str(product.id),
        "product_name": product.product_name,
        "stock_keeping_unit": product.stock_keeping_unit,
        "unit_of_measurement": product.unit_of_measurement,
        "product_description": product.product_description,
        "product_image_catalogues_list": [],
        "product_features_catalogues_list": [],
        "product_components_list": [
            {
                "product_component_id": str(component.id),
                "component_name": component.component_name,
                "component_quantity": component.component_quantity,
            }
            for component in product.product_components.all()
        ],
        "product_brands_list": [
            {
                "product_brand_id": str(brand.id),
                "product_brand_name": brand.product_brand_name,
                "product_brand_description": brand.product_brand_description,
            }
            for brand in product.product_brands.all()
        ],
        "product_pricing_map": _sales_product_pricing_map(product),
        "product_discount_map": _sales_product_discount_map(product),
        "product_vat_map": _sales_product_vat_map(product),
    }
    if company_branch is not None:
        attach_branch_stock_fields(product_map, product, company_branch)
    return product_map


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def sales_products(request):
    company_serial_number = request.data["serial_number"]
    active_user = request.user
    payload = {}
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        department_name = staff_profile.company_department.department_name if staff_profile.company_department else ""
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        if user_has_permission(staff_profile, "sales_and_marketing.product_catalog.view"):
            product_qs = Product.objects.filter(
                recycle_bin=False,
            ).order_by("-id").select_related(
                "product_pricing",
                "product_discount",
                "product_vat",
            ).prefetch_related(
                "product_components",
                "product_brands",
            )
            all_categories = Category.objects.filter(
                recycle_bin=False,
            ).prefetch_related(
                Prefetch("category_products", queryset=product_qs),
            ).order_by("-id")

            category_list = []
            company_branch = staff_profile.company_branch
            for category in all_categories:
                category_list.append({
                    "category_id": str(category.id),
                    "category_name": category.category_name,
                    "category_description": category.category_description,
                    "product_list": [
                        _sales_product_map(product, company_branch)
                        for product in category.category_products.all()
                    ],
                })

            payload["category_list"] = category_list
            payload["customer_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 sales_quotations(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 = {}
    creator_map = {}
    sales_quotation_map = {}
    sales_quotation_list = []
    pending_price_request_change_sales_quotation_list = []
    page_index = request.data.get("pageIndex", "1")
    start_index = 0
    last_index = 0
    try:
        if page_index == "1":
            start_index = 0
            last_index = 20
        elif page_index == "2":
            start_index = 20
            last_index = 40
        elif page_index == "3":
            start_index = 40
            last_index = 60
        elif page_index == "4":
            start_index = 60
            last_index = 80
        else:
            start_index = 80
            last_index = 0
        staff_profile = StaffProfile.objects.get(user=active_user)
        department_name = staff_profile.company_department.department_name if staff_profile.company_department else ""
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_branch = staff_profile.company_branch
        if user_has_permission(staff_profile, "sales_and_marketing.quotation.view"):
            if staff_profile.is_head_of_department == True and (department_name == "sales"):
                quotations_qs = SalesQuotation.objects.filter(recycle_bin=False).order_by("-id")
            elif staff_branch is not None:
                quotations_qs = staff_branch.branch_sale_quotations.filter(
                    recycle_bin=False, created_by=staff_profile).order_by("-id")
            else:
                quotations_qs = SalesQuotation.objects.filter(
                    recycle_bin=False, created_by=staff_profile).order_by("-id")
            branch_sale_quotations = quotations_qs[start_index:last_index] if last_index != 0 else quotations_qs[start_index:]
            for sale_quotation in branch_sale_quotations:
                sales_quotation_map = {}
                sales_quotation_items_list = []
                sales_quotation_map["sale_quotation_id"] = str(
                    sale_quotation.id)
                sales_quotation_map["sales_quotation_number"] = sale_quotation.sales_quotation_number
                sales_quotation_map["origin"] = sale_quotation.origin
                sales_quotation_map["crm_quote_uuid"] = sale_quotation.crm_quote_uuid or ""
                sales_quotation_map["synced_to_crm"] = "true" if sale_quotation.synced_to_crm else "false"
                sales_quotation_map["has_converted_order"] = "true" if sale_quotation.converted_customer_orders.filter(recycle_bin=False).exists() else "false"
                sales_quotation_map["quotation_net_value"] = sale_quotation.quotation_net_value
                sales_quotation_map["sales_quotation_approved"] = "true" if sale_quotation.sales_quotation_approved == True else "false"
                creator_map = {}
                creator_map["staff_id"] = str(
                    sale_quotation.created_by.id) if sale_quotation.created_by is not None else ""
                creator_map["staff_name"] = f'{sale_quotation.created_by.first_name} {sale_quotation.created_by.last_name}' if sale_quotation.created_by is not None else ""
                creator_map["staff_position"] = sale_quotation.created_by.staff_position.position_title if (sale_quotation.created_by is not None and sale_quotation.created_by.staff_position is not None) else ""
                sales_quotation_map["created_by"] = creator_map
                creator_map = {}
                creator_map["staff_id"] = str(
                    sale_quotation.last_updated_by.id) if sale_quotation.last_updated_by is not None else ""
                creator_map["staff_name"] = f'{sale_quotation.last_updated_by.first_name} {sale_quotation.last_updated_by.last_name}' if sale_quotation.last_updated_by is not None else ""
                creator_map["staff_position"] = sale_quotation.last_updated_by.staff_position.position_title if (sale_quotation.last_updated_by is not None and sale_quotation.last_updated_by.staff_position is not None) else ""
                sales_quotation_map["last_updated_by"] = creator_map
                sales_quotation_map["created_on"] = datetime.strftime(
                    sale_quotation.created_on.astimezone(target_timezone), date_format) if sale_quotation.created_on is not None else ""
                sales_quotation_map["last_updated_on"] = datetime.strftime(
                    sale_quotation.last_updated_on.astimezone(target_timezone), date_format) if sale_quotation.last_updated_on is not None else ""
                # quotation_price_change_request_active
                try:
                    sales_quotation_map["quotation_price_change_request_active"] = "true" if sale_quotation.quotation_price_change_request_active == True else "false"
                except:
                    sales_quotation_map["quotation_price_change_request_active"] = "false"
                # attach customer
                customer_profile = sale_quotation.customer_profile
                customer_profile_map = {}
                customer_profile_map["customer_profile_id"] = str(
                    customer_profile.id) if customer_profile is not None else ""
                customer_profile_map["customer_first_name"] = customer_profile.customer_first_name if customer_profile is not None else ""
                customer_profile_map["customer_last_name"] = customer_profile.customer_last_name if customer_profile is not None else ""
                customer_profile_map["email_address"] = customer_profile.email_address if customer_profile is not None else ""
                customer_profile_map["phone_number"] = customer_profile.phone_number if customer_profile is not None else ""
                customer_profile_map["customer_title"] = customer_profile.customer_title if customer_profile is not None else ""
                customer_profile_map["company_name"] = customer_profile.company_name if customer_profile is not None else ""
                customer_profile_map["customer_type"] = customer_profile.customer_type if customer_profile is not None else ""
                customer_profile_map["kra_pin"] = customer_profile.kra_pin if customer_profile is not None else ""
                customer_profile_map["certificate_of_registration_number"] = customer_profile.certificate_of_registration_number if customer_profile is not None else ""
                sales_quotation_map["customer"] = customer_profile_map
                customer_profile_map = {}
                # end
                sales_quotation_items = sale_quotation.sales_quotation_items.all().order_by("-id")
                for sale_quotation_item in sales_quotation_items:
                    sales_quotation_item_map = {}
                    sales_quotation_item_map["sale_quotation_item_id"] = str(
                        sale_quotation_item.id)
                    sales_quotation_item_map["product_id"] = str(
                        sale_quotation_item.product.id) if sale_quotation_item.product is not None else ""
                    sales_quotation_item_map["product_name"] = str(
                        sale_quotation_item.product.product_name) if sale_quotation_item.product is not None else ""
                    sales_quotation_item_map["quantity"] = sale_quotation_item.quantity
                    sales_quotation_item_map["price_per_item"] = sale_quotation_item.price_per_item
                    sales_quotation_item_map["discount_per_item"] = sale_quotation_item.discount_per_item
                    sales_quotation_item_map["gross_subtotal"] = sale_quotation_item.gross_subtotal
                    sales_quotation_item_map["total_discount"] = sale_quotation_item.total_discount
                    try:
                        vat_percentage_value = float(sale_quotation_item.product.product_vat.vat_percentage_value) if (sale_quotation_item.product is not None and sale_quotation_item.product.product_vat is not None) else 0.0
                    except Exception:
                        vat_percentage_value = 0.0
                    sales_quotation_item_map["vat_per_item"] = f"{(vat_percentage_value / 100) * float(sale_quotation_item.price_per_item)}"
                    sales_quotation_item_map["net_subtotal"] = sale_quotation_item.net_subtotal
                    sales_quotation_item_map["request_price_change"] = "true" if sale_quotation_item.request_price_change == True else "false"
                    sales_quotation_item_map["requested_new_price_after_discount"] = sale_quotation_item.requested_new_price_after_discount
                    sales_quotation_items_list.append(
                        sales_quotation_item_map)
                sales_quotation_map["sales_quotation_items_list"] = sales_quotation_items_list
                if sale_quotation.quotation_price_change_request_active == True:
                    pending_price_request_change_sales_quotation_list.append(
                        sales_quotation_map)
                else:
                    sales_quotation_list.append(sales_quotation_map)
            payload["pending_price_request_change_sales_quotation_list"] = pending_price_request_change_sales_quotation_list
            payload["sale_quotations_list"] = sales_quotation_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 customer_orders(request):
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    company_serial_number = request.data["serial_number"]
    page_index = request.data.get("pageIndex", "1")
    active_user = request.user
    payload = {}
    creator_map = {}
    customer_order_map = {}
    customer_orders_list = []
    customer_order_item_map = {}
    customer_order_items_list = []
    sales_order_map = {}
    # sales_orders_list = []
    sales_order_item_map = {}
    sales_order_items_list = []
    start_index = 0
    last_index = 0
    try:
        if page_index == "1":
            start_index = 0
            last_index = 20
        elif page_index == "2":
            start_index = 20
            last_index = 40
        elif page_index == "3":
            start_index = 40
            last_index = 60
        elif page_index == "4":
            start_index = 60
            last_index = 80
        else:
            start_index = 80
            last_index = 0
        staff_profile = StaffProfile.objects.get(user=active_user)
        department_name = staff_profile.company_department.department_name if staff_profile.company_department else ""
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_branch = staff_profile.company_branch
        if user_has_permission(staff_profile, "sales_and_marketing.customer_order.view"):
            if staff_profile.is_head_of_department == True and department_name == "marketing":
                customer_orders_qs = CustomerOrder.objects.filter(
                    recycle_bin=False, agent_profile=None).order_by("-id")
            elif staff_branch is not None:
                customer_orders_qs = staff_branch.branch_customer_orders.filter(
                    recycle_bin=False, created_by=staff_profile, agent_profile=None).order_by("-id")
            else:
                customer_orders_qs = CustomerOrder.objects.filter(
                    recycle_bin=False, created_by=staff_profile, agent_profile=None).order_by("-id")
            branch_customer_orders = customer_orders_qs[start_index:last_index] if last_index != 0 else customer_orders_qs[start_index:]
            for customer_order in branch_customer_orders:
                customer_order_map = {}
                customer_order_items_list = []
                order_items_return_list = []
                customer_order_payments_list = []
                customer_order_map["customer_profile_id"] = str(
                    customer_order.customer_profile.id) if customer_order.customer_profile is not None else ""
                customer_order_map["customer_order_id"] = str(
                    customer_order.id)
                customer_order_map["customer_order_number"] = customer_order.customer_order_number
                customer_order_map["origin"] = customer_order.origin
                customer_order_map["source_quotation_number"] = (
                    customer_order.source_quotation.sales_quotation_number
                    if customer_order.source_quotation_id else ""
                )
                customer_order_map["crm_quote_ref"] = (
                    customer_order.customer_order_description
                    if customer_order.origin == "crm" else ""
                )
                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"] = datetime.strftime(
                    customer_order.expected_delivery_date, '%d/%m/%Y') 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 is not None and 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 and 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 is not None and 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) if customer_order_item.product is not None else ""
                    customer_order_item_map["product_name"] = customer_order_item.product.product_name if customer_order_item.product is not None else ""
                    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 is not None and 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 is not None and 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["product_id"] = str(
                            sales_order_item.product.id) if sales_order_item.product is not None else ""
                        sales_order_item_map["product_name"] = sales_order_item.product.product_name if sales_order_item.product 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
                    # print(customer_order_map["sales_order_map"])
                    # print("running")
                except Exception as e:
                    # print(e)
                    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
                # 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
                        customer_order_payment_map["currency"] = order_payment.account_paid_to.account_currency
                        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)
            payload["customer_orders_list"] = customer_orders_list
            return Response({"message": "true", "payload": payload}, status=200)
        else:
            return Response({"message": "false", "payload": payload}, status=401)
    except:
        return Response({"message": "false", "payload": payload}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def supply_and_purchasing(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 = {}
    creator_map = {}
    supplier_list = []
    landed_costs_list = []
    purchase_order_list = []
    purchase_order_product_instances_list = []
    category_list = []
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_branch = staff_profile.company_branch
        if user_has_permission(staff_profile, "sales_and_marketing.purchase_order_sales.view"):
            all_suppliers = Supplier.objects.filter(
                recycle_bin=False,).order_by("-id")
            all_landed_costs = LandedCost.objects.filter(
                recycle_bin=False, company_profile=company_profile).order_by("-id")
            company_purchase_orders = company_profile.company_purchase_orders.filter(
                recycle_bin=False).order_by("-id")
            all_branch_warehouses = staff_branch.branch_warehouses.filter(
                recycle_bin=False,).order_by("-id")
            all_categories = Category.objects.all().order_by("-id")
            for category in all_categories:
                if category.recycle_bin != True and category.category_name != "TRANSPORT FEE":
                    category_map = {}
                    product_list = []
                    category_map["category_id"] = str(category.id)
                    category_map["category_name"] = category.category_name
                    category_products = category.category_products.all().order_by("-id")
                    for product in category_products:
                        if product.recycle_bin != True:
                            product_map = {}
                            product_map["product_id"] = str(product.id)
                            product_map["product_name"] = product.product_name
                            product_map["unit_of_measurement"] = product.unit_of_measurement
                            product_list.append(product_map)
                    category_map["product_list"] = product_list
                    category_list.append(category_map)
            # add suppliers
            for supplier in all_suppliers:
                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)
            # end of suppliers
            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)

            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.astimezone(target_timezone), 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.astimezone(target_timezone), 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)
            for warehouse in all_branch_warehouses:
                purchase_requisition_list = []
                warehouse_purchase_requisitions = warehouse.warehouse_purchase_requisitions.filter(
                    recycle_bin=False).order_by("-id")
                for purchase_requisition in warehouse_purchase_requisitions:
                    purchase_requisition_map = {}
                    purchase_requisition_instances_list = []
                    purchase_requisition_map["purchase_requisition_id"] = str(
                        purchase_requisition.id)
                    purchase_requisition_map["warehouse_name"] = warehouse.warehouse_name
                    purchase_requisition_map["branch_name"] = warehouse.company_branch.branch_name
                    purchase_requisition_map["purchase_requisition_number"] = purchase_requisition.purchase_requisition_number
                    purchase_requisition_map["purchase_requisition_description"] = purchase_requisition.purchase_requisition_description
                    purchase_requisition_map["purchase_requisition_approved"] = "true" if purchase_requisition.purchase_requisition_approved == True else "false"
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        purchase_requisition.created_by.id) if purchase_requisition.created_by is not None else ""
                    creator_map["staff_name"] = f'{purchase_requisition.created_by.first_name} {purchase_requisition.created_by.last_name}' if purchase_requisition.created_by is not None else ""
                    creator_map["staff_position"] = purchase_requisition.created_by.staff_position.position_title if purchase_requisition.created_by.staff_position is not None else ""
                    purchase_requisition_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        purchase_requisition.last_updated_by.id) if purchase_requisition.last_updated_by is not None else ""
                    creator_map["staff_name"] = f'{purchase_requisition.last_updated_by.first_name} {purchase_requisition.last_updated_by.last_name}' if purchase_requisition.last_updated_by is not None else ""
                    creator_map["staff_position"] = purchase_requisition.last_updated_by.staff_position.position_title if purchase_requisition.last_updated_by.staff_position is not None else ""
                    purchase_requisition_map["last_updated_by"] = creator_map
                    purchase_requisition_map["created_on"] = datetime.strftime(
                        purchase_requisition.created_on.astimezone(target_timezone), date_format) if purchase_requisition.created_on is not None else ""
                    purchase_requisition_map["last_updated_on"] = datetime.strftime(
                        purchase_requisition.last_updated_on.astimezone(target_timezone), date_format) if purchase_requisition.last_updated_on is not None else ""
                    purchase_requisition_instances = purchase_requisition.purchase_requisition_instances.all().order_by("id")
                    for purchase_requisition_instance in purchase_requisition_instances:
                        if purchase_requisition_instance.recycle_bin != True:
                            purchase_requisition_instances_map = {}
                            purchase_requisition_instances_map["purchase_requisition_instance_id"] = str(
                                purchase_requisition_instance.id)
                            purchase_requisition_instances_map["product_id"] = str(
                                purchase_requisition_instance.product.id) if purchase_requisition_instance.product is not None else ""
                            purchase_requisition_instances_map["product_name"] = purchase_requisition_instance.product.product_name if purchase_requisition_instance.product is not None else ""
                            purchase_requisition_instances_map["unit_of_measurement"] = purchase_requisition_instance.product.unit_of_measurement if purchase_requisition_instance.product is not None else ""
                            purchase_requisition_instances_map[
                                "quantity"] = purchase_requisition_instance.quantity
                            purchase_requisition_instances_map[
                                "purchase_requisition_items_purchased"] = "true" if purchase_requisition_instance.purchase_requisition_items_purchased == True else "false"
                            purchase_requisition_instances_list.append(
                                purchase_requisition_instances_map)
                    purchase_requisition_map["purchase_requisition_instances_list"] = purchase_requisition_instances_list
                    enrich_purchase_requisition_map(
                        purchase_requisition,
                        purchase_requisition_map,
                        date_format,
                        target_timezone,
                    )
                    purchase_requisition_list.append(
                        purchase_requisition_map)
            payload["supplier_list"] = supplier_list
            payload["purchase_order_list"] = purchase_order_list
            payload["landed_costs_list"] = landed_costs_list
            payload["purchase_requisition_list"] = purchase_requisition_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 sales_dashboard(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 = {}
    creator_map = {}
    category_map = {}
    category_list = []
    product_map = {}
    product_list = []
    sale_outlet_map = {}
    sale_outlet_list = []
    sales_quotation_map = {}
    sales_quotation_list = []
    sales_quotation_item_map = {}
    sales_quotation_items_list = []
    customer_profile_map = {}
    customer_profiles_list = []
    customer_order_map = {}
    customer_orders_list = []
    customer_order_item_map = {}
    customer_order_items_list = []
    sales_order_map = {}
    # sales_orders_list = []
    sales_order_item_map = {}
    sales_order_items_list = []
    sales_commission_map = {}
    sales_commissions_list = []
    commission_sheet_map = {}
    commission_sheets_list = []
    commission_sheet_instance_map = {}
    commission_sheet_instance_list = []
    order_item_return_map = {}
    order_items_return_list = []
    return_item_map = {}
    return_items_list = []
    customer_order_payment_map = {}
    customer_order_payments_list = []
    refund_map = {}
    refunds_list = []
    company_profile_map = {}
    company_branches_list = []
    company_branch_map = {}
    # product specific containers
    product_image_catalogue_map = {}
    product_image_catalogues_list = []
    product_features_catalogue_map = {}
    product_features_catalogues_list = []
    product_features_attributes_map = {}
    product_features_attributes_list = []
    product_component_map = {}
    product_components_list = []
    product_brand_map = {}
    product_brands_list = []
    product_pricing_map = {}  # 0netoone
    product_discount_map = {}  # onetoone
    product_vat_map = {}  # onetoone

    # customer specific containers
    customer_shipping_address_map = {}
    customer_shipping_address_list = []
    supplier_list = []
    supplier_map = {}
    supplied_products_list = []
    supplied_product_map = {}
    purchase_order_list = []
    purchase_order_map = {}
    purchase_requisition_list = []
    purchase_requisition_map = {}
    purchase_order_product_instances_list = []
    purchase_order_product_instance_map = {}
    stock_requisition_instances_list = []
    stock_requisition_instance_map = {}
    landed_costs_list = []
    landed_cost_map = {}
    landed_cost_instances_list = []
    landed_cost_instance_map = {}
    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 == "sales" and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
        if company_profile and user_has_permission(staff_profile, "sales_and_marketing.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()
            all_categories = Category.objects.all().order_by("-id")
            all_customer_profiles = company_profile.company_customers.all().order_by("-id")
            all_sales_commissions = SalesCommission.objects.all().order_by("-id")
            all_warehouses = Warehouse.objects.all().order_by("-id")
            all_suppliers = Supplier.objects.all().order_by("-id")
            # all_purchase_orders = PurchaseOrder.objects.all().order_by("-id")
            all_landed_costs = LandedCost.objects.filter(
                recycle_bin=False, company_profile=company_profile).order_by("-id")
            company_purchase_orders = company_profile.company_purchase_orders.filter(
                recycle_bin=False).order_by("-id")
            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)
                    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.astimezone(target_timezone), 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.astimezone(target_timezone), 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
            warehouse_list = []
            for warehouse in all_warehouses:
                warehouse_map = {}
                warehouse_map["warehouse_id"] = str(warehouse.id)
                warehouse_map["warehouse_name"] = warehouse.warehouse_name
                warehouse_map["warehouse_location"] = warehouse.warehouse_location
                warehouse_list.append(warehouse_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
                                product_pricing_map["product_net_price_technician"] = product_pricing.product_net_price_technician
                                product_pricing_map["product_net_price_reseller"] = product_pricing.product_net_price_reseller
                                product_pricing_map["product_net_price_financier"] = product_pricing.product_net_price_financier
                                product_pricing_map["product_net_price_engineering_procurement_contractor"] = product_pricing.product_net_price_engineering_procurement_contractor
                            except:
                                product_pricing_map["product_pricing_id"] = ""
                                product_pricing_map["product_net_price"] = ""
                                product_pricing_map["product_net_price_technician"] = ""
                                product_pricing_map["product_net_price_reseller"] = ""
                                product_pricing_map["product_net_price_financier"] = ""
                                product_pricing_map["product_net_price_engineering_procurement_contractor"] = ""
                            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)
            # 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 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)
            # end of suppliers
            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"
                    branch_sale_outlets = branch.branch_sale_outlets.all().order_by("-id")
                    branch_customer_orders = branch.branch_customer_orders.all().order_by("-id")
                    branch_commission_sheets = branch.branch_commission_sheets.all().order_by("-id")
                    commission_sheets_list = []
                    sale_outlet_list = []
                    sales_quotation_list = []
                    customer_orders_list = []
                    sales_quotation_list = []
                    sale_outlet_list = []
                    for sale_outlet in branch_sale_outlets:
                        if sale_outlet.recycle_bin != True:
                            sale_outlet_map = {}
                            sale_outlet_map["sale_outlet_id"] = str(
                                sale_outlet.id)
                            sale_outlet_map["sale_outlet_location"] = sale_outlet.sale_outlet_location
                            sale_outlet_map["sale_outlet_contact_phone"] = sale_outlet.sale_outlet_contact_phone
                            sale_outlet_map["sale_outlet_description"] = sale_outlet.sale_outlet_description
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                sale_outlet.created_by.id) if sale_outlet.created_by is not None else ""
                            creator_map["staff_name"] = f'{sale_outlet.created_by.first_name} {sale_outlet.created_by.last_name}' if sale_outlet.created_by is not None else ""
                            creator_map["staff_position"] = sale_outlet.created_by.staff_position.position_title if sale_outlet.created_by is not None else ""
                            sale_outlet_map["created_by"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                sale_outlet.last_updated_by.id) if sale_outlet.last_updated_by is not None else ""
                            creator_map["staff_name"] = f'{sale_outlet.last_updated_by.first_name} {sale_outlet.last_updated_by.last_name}' if sale_outlet.last_updated_by is not None else ""
                            creator_map["staff_position"] = sale_outlet.last_updated_by.staff_position.position_title if sale_outlet.last_updated_by is not None else ""
                            sale_outlet_map["last_updated_by"] = creator_map
                            sale_outlet_map["created_on"] = datetime.strftime(
                                sale_outlet.created_on.astimezone(target_timezone), date_format) if sale_outlet.created_on is not None else ""
                            sale_outlet_map["last_updated_on"] = datetime.strftime(
                                sale_outlet.last_updated_on.astimezone(target_timezone), date_format) if sale_outlet.last_updated_on is not None else ""
                            sale_outlet_list.append(sale_outlet_map)
                    company_branch_map["sale_outlet_list"] = sale_outlet_list
                    # sales quotations
                    branch_sale_quotations = branch.branch_sale_quotations.all().order_by("-id")
                    for sale_quotation in branch_sale_quotations:
                        if sale_quotation.recycle_bin != True:
                            sales_quotation_map = {}
                            sales_quotation_items_list = []
                            sales_quotation_map["sale_quotation_id"] = str(
                                sale_quotation.id)
                            sales_quotation_map["sales_quotation_number"] = sale_quotation.sales_quotation_number
                            sales_quotation_map["quotation_net_value"] = sale_quotation.quotation_net_value
                            sales_quotation_map["sales_quotation_approved"] = "true" if sale_quotation.sales_quotation_approved == True else "false"
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                sale_quotation.created_by.id) if sale_quotation.created_by is not None else ""
                            creator_map["staff_name"] = f'{sale_quotation.created_by.first_name} {sale_quotation.created_by.last_name}' if sale_quotation.created_by is not None else ""
                            creator_map["staff_position"] = sale_quotation.created_by.staff_position.position_title if sale_quotation.created_by is not None else ""
                            sales_quotation_map["created_by"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                sale_quotation.last_updated_by.id) if sale_quotation.last_updated_by is not None else ""
                            creator_map["staff_name"] = f'{sale_quotation.last_updated_by.first_name} {sale_quotation.last_updated_by.last_name}' if sale_quotation.last_updated_by is not None else ""
                            creator_map["staff_position"] = sale_quotation.last_updated_by.staff_position.position_title if sale_quotation.last_updated_by is not None else ""
                            sales_quotation_map["last_updated_by"] = creator_map
                            sales_quotation_map["created_on"] = datetime.strftime(
                                sale_quotation.created_on.astimezone(target_timezone), date_format) if sale_quotation.created_on is not None else ""
                            sales_quotation_map["last_updated_on"] = datetime.strftime(
                                sale_quotation.last_updated_on.astimezone(target_timezone), date_format) if sale_quotation.last_updated_on is not None else ""
                            # attach customer
                            customer_profile = sale_quotation.customer_profile
                            customer_profile_map = {}
                            customer_profile_map["customer_profile_id"] = str(
                                customer_profile.id) if customer_profile is not None else ""
                            customer_profile_map["customer_first_name"] = customer_profile.customer_first_name if customer_profile is not None else ""
                            customer_profile_map["customer_last_name"] = customer_profile.customer_last_name if customer_profile is not None else ""
                            customer_profile_map["email_address"] = customer_profile.email_address if customer_profile is not None else ""
                            customer_profile_map["phone_number"] = customer_profile.phone_number if customer_profile is not None else ""
                            customer_profile_map["customer_title"] = customer_profile.customer_title if customer_profile is not None else ""
                            customer_profile_map["company_name"] = customer_profile.company_name if customer_profile is not None else ""
                            customer_profile_map["customer_type"] = customer_profile.customer_type if customer_profile is not None else ""
                            customer_profile_map["kra_pin"] = customer_profile.kra_pin if customer_profile is not None else ""
                            customer_profile_map["certificate_of_registration_number"] = customer_profile.certificate_of_registration_number if customer_profile is not None else ""
                            sales_quotation_map["customer"] = customer_profile_map
                            customer_profile_map = {}
                            # end
                            sales_quotation_items = sale_quotation.sales_quotation_items.all().order_by("-id")
                            for sale_quotation_item in sales_quotation_items:
                                sales_quotation_item_map = {}
                                sales_quotation_item_map["sale_quotation_item_id"] = str(
                                    sale_quotation_item.id)
                                sales_quotation_item_map["product_id"] = str(
                                    sale_quotation_item.product.id) if sale_quotation_item.product is not None else ""
                                sales_quotation_item_map["product_name"] = str(
                                    sale_quotation_item.product.product_name) if sale_quotation_item.product is not None else ""
                                sales_quotation_item_map["quantity"] = sale_quotation_item.quantity
                                sales_quotation_item_map["price_per_item"] = sale_quotation_item.price_per_item
                                sales_quotation_item_map["discount_per_item"] = sale_quotation_item.discount_per_item
                                sales_quotation_item_map["gross_subtotal"] = sale_quotation_item.gross_subtotal
                                sales_quotation_item_map["total_discount"] = sale_quotation_item.total_discount
                                sales_quotation_item_map["vat_per_item"] = f"{(float(sale_quotation_item.product.product_vat.vat_percentage_value)/100)*float(sale_quotation_item.price_per_item)}"
                                sales_quotation_item_map["net_subtotal"] = sale_quotation_item.net_subtotal
                                sales_quotation_items_list.append(
                                    sales_quotation_item_map)
                            sales_quotation_map["sales_quotation_items_list"] = sales_quotation_items_list
                            sales_quotation_list.append(sales_quotation_map)
                    company_branch_map["sales_quotation_list"] = sales_quotation_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_profile_id"] = str(
                                customer_order.customer_profile.id) if customer_order.customer_profile is not None else ""
                            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"] = datetime.strftime(
                                customer_order.expected_delivery_date, '%d/%m/%Y') 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["product_id"] = str(
                                        sales_order_item.product.id) if sales_order_item.product is not None else ""
                                    sales_order_item_map["product_name"] = sales_order_item.product.product_name if sales_order_item.product 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
                                # print(customer_order_map["sales_order_map"])
                                # print("running")
                            except Exception as e:
                                # print(e)
                                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
                            # 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
                                    customer_order_payment_map["currency"] = order_payment.account_paid_to.account_currency
                                    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
                    for commission_sheet in branch_commission_sheets:
                        if commission_sheet.recycle_bin != True:
                            commission_sheet_map = {}
                            commission_sheet_instance_list = []
                            commission_sheet_map["commission_sheet_id"] = str(
                                commission_sheet.id)
                            commission_sheet_map["commission_sheet_title"] = commission_sheet.commission_sheet_title
                            commission_sheet_map["commission_sheet_number"] = commission_sheet.commission_sheet_number
                            commission_sheet_map["commission_sheet_description"] = commission_sheet.commission_sheet_description
                            commission_sheet_map["commission_sheet_for_the_month_of"] = commission_sheet.commission_sheet_for_the_month_of
                            commission_sheet_map["commission_sheet_for_the_year"] = commission_sheet.commission_sheet_for_the_year
                            commission_sheet_map["commission_sheet_value"] = commission_sheet.commission_sheet_value
                            commission_sheet_map["commission_sheet_approved_by_finance"] = "true" if commission_sheet.commission_sheet_approved_by_finance == True else "false"
                            commission_sheet_map["commission_sheet_payment_settled"] = "true" if commission_sheet.commission_sheet_payment_settled == True else "false"
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                sales_order.created_by.id) if commission_sheet.created_by is not None else ""
                            creator_map["staff_name"] = f'{commission_sheet.created_by.first_name} {commission_sheet.created_by.last_name}' if commission_sheet.created_by is not None else ""
                            creator_map["staff_position"] = commission_sheet.created_by.staff_position.position_title if commission_sheet.created_by.staff_position is not None else ""
                            customer_order_map["created_by"] = creator_map
                            creator_map = {}
                            creator_map["staff_id"] = str(
                                commission_sheet.last_updated_by.id) if commission_sheet.last_updated_by is not None else ""
                            creator_map["staff_name"] = f'{commission_sheet.last_updated_by.first_name} {commission_sheet.last_updated_by.last_name}' if commission_sheet.last_updated_by is not None else ""
                            creator_map["staff_position"] = commission_sheet.last_updated_by.staff_position.position_title if commission_sheet.last_updated_by.staff_position is not None else ""
                            commission_sheet_map["last_updated_by"] = creator_map
                            commission_sheet_map["created_on"] = datetime.strftime(
                                commission_sheet.created_on.astimezone(target_timezone), date_format) if commission_sheet.created_on is not None else ""
                            commission_sheet_map["last_updated_on"] = datetime.strftime(
                                commission_sheet.last_updated_on.astimezone(target_timezone), date_format) if commission_sheet.last_updated_on is not None else ""
                            commission_items = commission_sheet.commission_items.all().order_by("-id")
                            for commission_item in commission_items:
                                commission_sheet_instance_map = {}
                                commission_sheet_instance_map["commission_sheet_instance_id"] = str(
                                    commission_item.id)
                                commission_sheet_instance_map["customer_order_id"] = str(
                                    commission_item.customer_order.id) if commission_item.customer_order is not None else ""
                                commission_sheet_instance_map["commission_value"] = commission_item.commission_value
                                commission_sheet_instance_list.append(
                                    commission_sheet_instance_map)
                            commission_sheet_map["commission_sheet_instance_list"] = commission_sheet_instance_list
                            commission_sheets_list.append(commission_sheet_map)
                    company_branch_map["commission_sheets_list"] = commission_sheets_list
                    all_chart_of_accounts = branch.branch_chart_of_accounts.filter(
                        recycle_bin=False).order_by("-id")
                    chart_of_account_list = []
                    for account in all_chart_of_accounts:
                        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
                        chart_of_account_list.append(chart_of_account_map)
                    company_branch_map["chart_of_account_list"] = chart_of_account_list
                    # get branch warehouse
                    # if branch.main_branch == True:
                    all_branch_warehouses = branch.branch_warehouses.all()
                    warehouse_list = []
                    for warehouse in all_branch_warehouses:
                        if warehouse.recycle_bin != True:
                            warehouse_map = {}
                            warehouse_map["warehouse_id"] = str(warehouse.id)
                            warehouse_map["warehouse_company_branch_id"] = str(
                                warehouse.company_branch.id)
                            warehouse_map["warehouse_company_branch_name"] = warehouse.company_branch.branch_name
                            warehouse_map["warehouse_name"] = warehouse.warehouse_name
                            warehouse_map["warehouse_location"] = warehouse.warehouse_location
                            warehouse_map["warehouse_capacity"] = warehouse.warehouse_capacity
                            warehouse_map["warehouse_contact_phone"] = warehouse.warehouse_contact_phone
                            warehouse_map["warehouse_description"] = warehouse.warehouse_description
                            # add purchase requisition
                            purchase_requisition_list = []
                            warehouse_purchase_requisitions = warehouse.warehouse_purchase_requisitions.all().order_by("-id")
                            for purchase_requisition in warehouse_purchase_requisitions:
                                if purchase_requisition.recycle_bin != True:
                                    purchase_requisition_map = {}
                                    purchase_requisition_instances_list = []
                                    purchase_requisition_map["purchase_requisition_id"] = str(
                                        purchase_requisition.id)
                                    purchase_requisition_map["purchase_requisition_number"] = purchase_requisition.purchase_requisition_number
                                    purchase_requisition_map["purchase_requisition_description"] = purchase_requisition.purchase_requisition_description
                                    purchase_requisition_map["purchase_requisition_approved"] = "true" if purchase_requisition.purchase_requisition_approved == True else "false"
                                    creator_map = {}
                                    creator_map["staff_id"] = str(
                                        purchase_requisition.created_by.id) if purchase_requisition.created_by is not None else ""
                                    creator_map["staff_name"] = f'{purchase_requisition.created_by.first_name} {purchase_requisition.created_by.last_name}' if purchase_requisition.created_by is not None else ""
                                    creator_map["staff_position"] = purchase_requisition.created_by.staff_position.position_title if purchase_requisition.created_by.staff_position is not None else ""
                                    purchase_requisition_map["created_by"] = creator_map
                                    creator_map = {}
                                    creator_map["staff_id"] = str(
                                        purchase_requisition.last_updated_by.id) if purchase_requisition.last_updated_by is not None else ""
                                    creator_map["staff_name"] = f'{purchase_requisition.last_updated_by.first_name} {purchase_requisition.last_updated_by.last_name}' if purchase_requisition.last_updated_by is not None else ""
                                    creator_map["staff_position"] = purchase_requisition.last_updated_by.staff_position.position_title if purchase_requisition.last_updated_by.staff_position is not None else ""
                                    purchase_requisition_map["last_updated_by"] = creator_map
                                    purchase_requisition_map["created_on"] = datetime.strftime(
                                        purchase_requisition.created_on.astimezone(target_timezone), date_format) if purchase_requisition.created_on is not None else ""
                                    purchase_requisition_map["last_updated_on"] = datetime.strftime(
                                        purchase_requisition.last_updated_on.astimezone(target_timezone), date_format) if purchase_requisition.last_updated_on is not None else ""
                                    purchase_requisition_instances = purchase_requisition.purchase_requisition_instances.all().order_by("id")
                                    for purchase_requisition_instance in purchase_requisition_instances:
                                        if purchase_requisition_instance.recycle_bin != True:
                                            purchase_requisition_instances_map = {}
                                            purchase_requisition_instances_map["purchase_requisition_instance_id"] = str(
                                                purchase_requisition_instance.id)
                                            purchase_requisition_instances_map["product_id"] = str(
                                                purchase_requisition_instance.product.id) if purchase_requisition_instance.product is not None else ""
                                            purchase_requisition_instances_map[
                                                "quantity"] = purchase_requisition_instance.quantity
                                            purchase_requisition_instances_map[
                                                "purchase_requisition_items_purchased"] = "true" if purchase_requisition_instance.purchase_requisition_items_purchased == True else "false"
                                            purchase_requisition_instances_list.append(
                                                purchase_requisition_instances_map)
                                    purchase_requisition_map["purchase_requisition_instances_list"] = purchase_requisition_instances_list
                                    purchase_requisition_list.append(
                                        purchase_requisition_map)
                            warehouse_map["purchase_requisition_list"] = purchase_requisition_list
                            # end purchase requisition
                            warehouse_list.append(warehouse_map)
                    company_branch_map["warehouse_list"] = warehouse_list
                    company_branches_list.append(company_branch_map)
            for customer_profile in all_customer_profiles:
                if customer_profile.recycle_bin != True:
                    customer_profile_map = {}
                    customer_shipping_address_list = []
                    customer_documents = customer_profile.customer_documents.all().order_by("-id")
                    kra_pin_certificate_path = ""
                    certificate_of_registration_path = ""
                    if customer_documents is not None:
                        for customer_doc in customer_documents:
                            if customer_doc.document_type == "pin_certificate":
                                kra_pin_certificate_path = customer_doc.saved_document_path
                                break
                        for customer_doc in customer_documents:
                            if customer_doc.document_type == "certificate_of_registration":
                                certificate_of_registration_path = customer_doc.saved_document_path
                                break
                    customer_profile_map["customer_profile_id"] = str(
                        customer_profile.id)
                    customer_profile_map["customer_first_name"] = customer_profile.customer_first_name
                    customer_profile_map["customer_last_name"] = customer_profile.customer_last_name
                    customer_profile_map["email_address"] = customer_profile.email_address
                    customer_profile_map["phone_number"] = customer_profile.phone_number
                    customer_profile_map["customer_title"] = customer_profile.customer_title
                    customer_profile_map["company_name"] = customer_profile.company_name
                    customer_profile_map["customer_type"] = customer_profile.customer_type
                    customer_profile_map["kra_pin"] = customer_profile.kra_pin
                    customer_profile_map["kra_pin_certificate_path"] = kra_pin_certificate_path
                    customer_profile_map["certificate_of_registration_number"] = customer_profile.certificate_of_registration_number
                    customer_profile_map["certificate_of_registration_path"] = certificate_of_registration_path
                    customer_profile_map["is_profile_set"] = "true" if customer_profile.is_profile_set == True else "false"
                    customer_profile_map["created_on"] = datetime.strftime(
                        customer_profile.created_on.astimezone(target_timezone), date_format) if customer_profile.created_on is not None else ""
                    customer_profile_map["last_updated_on"] = datetime.strftime(
                        customer_profile.last_updated_on.astimezone(target_timezone), date_format) if customer_profile.last_updated_on is not None else ""
                    customer_shipping_address = customer_profile.customer_shipping_address.all().order_by("-id")
                    customer_profile_map["customer_account_manager"] = {"staff_id": "", "staff_name": ""}
                    for shipping_address in customer_shipping_address:
                        customer_shipping_address_map = {}
                        customer_shipping_address_map["customer_shipping_address_id"] = str(
                            shipping_address.id)
                        customer_shipping_address_map["shipping_address"] = shipping_address.shipping_address
                        customer_shipping_address_map["pick_up_point"] = shipping_address.pick_up_point
                        customer_shipping_address_map["shipping_town"] = shipping_address.shipping_town
                        customer_shipping_address_list.append(
                            customer_shipping_address_map)
                    customer_profile_map["customer_shipping_address_list"] = customer_shipping_address_list
                    customer_profiles_list.append(customer_profile_map)
            for sale_commission in all_sales_commissions:
                if sale_commission.recycle_bin != True:
                    sales_commission_map = {}
                    sales_commission_map["sale_commission_id"] = str(
                        sale_commission.id)
                    sales_commission_map["commission_title"] = sale_commission.commission_title
                    sales_commission_map["commission_description"] = sale_commission.commission_description
                    sales_commission_map["commission_value"] = sale_commission.commission_value
                    sales_commission_map["commission_period_start_date"] = sale_commission.commission_period_start_date if sale_commission.commission_period_start_date is not None else ""
                    sales_commission_map["commission_period_end_date"] = sale_commission.commission_period_end_date if sale_commission.commission_period_end_date is not None else ""
                    sales_commission_map["commission_module"] = sale_commission.commission_module
                    # attach products
                    sale_commission_products_list = []
                    sale_commission_products = sale_commission.product.all().order_by("-id")
                    for commission_product in sale_commission_products:
                        sale_commission_product_map = {}
                        sale_commission_product_map["product_id"] = str(
                            commission_product.product.id)
                        sale_commission_product_map["product_name"] = commission_product.product.product_name
                        sale_commission_products_list.append(
                            sale_commission_product_map)
                    sales_commission_map["sale_commission_products_list"] = sale_commission_products_list
                    # attach sales persons
                    sale_commission_sales_persons_list = []
                    sale_commission_sales_person = sale_commission.sales_person.all().order_by("-id")
                    for sales_person in sale_commission_sales_person:
                        sale_commission_sales_persons_map = {}
                        sale_commission_sales_persons_map["sales_person_id"] = str(
                            sales_person.id) if sales_person is not None else ""
                        sale_commission_sales_persons_map[
                            "sales_person_name"] = f"{sales_person.first_name} {sales_person.last_name}" if sales_person is not None else ""
                        sale_commission_sales_persons_list.append(
                            sale_commission_sales_persons_map)
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        sale_commission.created_by.id) if sale_commission.created_by is not None else ""
                    creator_map["staff_name"] = f'{sale_commission.created_by.first_name} {sale_commission.created_by.last_name}' if sale_commission.created_by is not None else ""
                    creator_map["staff_position"] = sale_commission.created_by.staff_position.position_title if sale_commission.created_by.staff_position is not None else ""
                    sales_commission_map["created_by"] = creator_map
                    creator_map = {}
                    creator_map["staff_id"] = str(
                        sale_commission.last_updated_by.id) if sale_commission.last_updated_by is not None else ""
                    creator_map["staff_name"] = f'{sale_commission.last_updated_by.first_name} {sale_commission.last_updated_by.last_name}' if sale_commission.last_updated_by is not None else ""
                    creator_map["staff_position"] = sale_commission.last_updated_by.staff_position.position_title if sale_commission.last_updated_by.staff_position is not None else ""
                    sales_commission_map["last_updated_by"] = creator_map
                    sales_commission_map["created_on"] = datetime.strftime(
                        commission_sheet.created_on.astimezone(target_timezone), date_format) if sale_commission.created_on is not None else ""
                    sales_commission_map["last_updated_on"] = datetime.strftime(
                        sale_commission.last_updated_on.astimezone(target_timezone), date_format) if sale_commission.last_updated_on is not None else ""
                    sales_commission_map["sale_commission_sales_persons_list"] = sale_commission_sales_persons_list
                    sales_commissions_list.append(sales_commission_map)
            company_profile_map["company_branches_list"] = company_branches_list
            company_profile_map["warehouse_list"] = warehouse_list
            payload["supplier_list"] = supplier_list
            payload["active_staff_profile_data"] = active_staff_profile_data
            payload["category_list"] = category_list
            payload["customer_profiles_list"] = customer_profiles_list
            payload["company_profile"] = company_profile_map
            payload["sales_commissions_list"] = sales_commissions_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 edit_product_features_and_attributes(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    product_features_catalogues_list = request.data.get(
        'product_features_catalogues_list', [])
    product_features_catalogues_list = json.loads(
        product_features_catalogues_list)
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        if user_has_permission(staff_profile, "sales_and_marketing.product_catalog.edit"):
            for product_feature in product_features_catalogues_list:
                product_feature_instance = ProductFeaturesCatalogue.objects.get(
                    id=int(product_feature["product_feature_id"]))
                feature_catalogue_serializer = ProductFeaturesCatalogueSerializer(
                    instance=product_feature_instance, data={'product_feature_title': product_feature["product_feature_title"]})
                if feature_catalogue_serializer.is_valid():
                    feature_catalogue_serializer.save()
                    for attribute_feature in product_feature["product_features_attributes_list"]:
                        attribute_instance = ProductFeaturesAttributes.objects.get(
                            id=int(attribute_feature["feature_attribute_id"]))
                        attribute_serializer = ProductFeaturesAttributesSerializer(instance=attribute_instance, data={
                                                                                   'feature_attribute_title': attribute_feature["feature_attribute_title"], 'feature_attribute_description': attribute_feature["feature_attribute_description"]})
                        if attribute_serializer.is_valid():
                            attribute_serializer.save()
            return Response({"message": "Product features updated successfully", }, status=200)
            # else:
            #     error_messages = [str(value[0])
            #                       for value in feature_catalogue_serializer.errors.values()]
            #     return Response({"message": error_messages[0], }, 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 updating product features", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_product_components(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    product_components_list = request.data.get(
        'product_components_list', [])
    product_components_list = json.loads(
        product_components_list)
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        # print(product_components_list)
        if user_has_permission(staff_profile, "sales_and_marketing.product_catalog.edit"):
            for product_component in product_components_list:
                # print(product_component)
                product_component_instance = ProductComponent.objects.get(
                    id=int(product_component["product_component_id"]))
                product_component_serializer = ProductComponentSerializer(instance=product_component_instance, data={
                                                                          'component_name': product_component["component_name"], 'component_quantity': product_component["component_quantity"]})
                if product_component_serializer.is_valid():
                    product_component_serializer.save()
            return Response({"message": "Product components updated successfully", }, status=200)
        # else:
        #     error_messages = [str(value[0])
        #                         for value in product_component_serializer.errors.values()]
        #     return Response({"message": error_messages[0], }, 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 updating product components", }, status=500)


# @api_view(['POST'])
# @authentication_classes([TokenAuthentication])
# @permission_classes([IsAuthenticated])
# def edit_product_brands(request):
#     active_user = request.user
#     company_serial_number = request.data["serial_number"]
#     product_brands_list = request.data.get(
#         'product_brands_list', [])
#     product_brands_list = json.loads(
#         product_brands_list)
#     try:
#         staff_profile = StaffProfile.objects.get(user=active_user)
#         company_profile = CompanyProfile.objects.get(
#             company_serial_number=company_serial_number)
#         if staff_profile.company_department.department_name == "sales" and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
#             for product_brand in product_brands_list:
#                 product_brand_instance = ProductComponent.objects.get(
#                     id=int(product_brand["product_brand_id"]))
#                 product_brand_serializer = ProductBrandSerializer(instance=product_brand_instance, data={
#                     'product_brand_name': product_brand["product_brand_name"], 'product_brand_description': product_brand["product_brand_description"]})
#                 if product_brand_serializer.is_valid():
#                     product_brand_serializer.save()
#                     return Response({"message": "Product brand updated successfully", }, status=200)
#                 else:
#                     error_messages = [str(value[0])
#                                       for value in product_brand_serializer.errors.values()]
#                     return Response({"message": error_messages[0], }, 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 updating product brands", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_product_brands(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    product_brands_list = request.data.get(
        'product_brands_list', [])
    product_brands_list = json.loads(
        product_brands_list)
    try:
        # print(product_brands_list)
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        if user_has_permission(staff_profile, "sales_and_marketing.product_catalog.edit"):
            for product_brand in product_brands_list:
                product_brand_instance = ProductBrand.objects.get(
                    id=int(product_brand["product_brand_id"]))
                product_brand_serializer = ProductBrandSerializer(instance=product_brand_instance, data={
                    'product_brand_name': product_brand["product_brand_name"], 'product_brand_description': product_brand["product_brand_description"]})
                if product_brand_serializer.is_valid():
                    product_brand_serializer.save()
                else:
                    print(product_brand_serializer.errors)
            return Response({"message": "Product brand updated successfully", }, status=200)
            # else:
            #     error_messages = [str(value[0])
            #                       for value in product_brand_serializer.errors.values()]
            #     return Response({"message": error_messages[0], }, 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 updating product brands", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_product_pricing(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    product_pricing_id = request.data["product_pricing_id"]
    product_net_price = request.data["product_net_price"]
    product_net_price_technician = request.data["product_net_price_technician"]
    product_net_price_reseller = request.data["product_net_price_reseller"]
    product_net_price_financier = request.data["product_net_price_financier"]
    product_net_price_engineering_procurement_contractor = request.data[
        "product_net_price_engineering_procurement_contractor"]
    #product_net_price_hydraulic_engineers
    # product_net_price_hydraulic_engineers = request.data[
    #     "product_net_price_hydraulic_engineers"]
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        if user_has_permission(staff_profile, "sales_and_marketing.product_catalog.edit"):
            product_pricing_instance = ProductPricing.objects.get(
                id=int(product_pricing_id))
            product_pricing_serializer = ProductPricingSerializer(
                instance=product_pricing_instance, data={'product_net_price': product_net_price, 'product_net_price_technician': product_net_price_technician, 'product_net_price_reseller': product_net_price_reseller, 'product_net_price_financier': product_net_price_financier, 'product_net_price_engineering_procurement_contractor': product_net_price_engineering_procurement_contractor})
            if product_pricing_serializer.is_valid():
                product_pricing_serializer.save()
                # send a notification to everyone
                subject = f"{product_pricing_instance.product.product_name} Update"
                message = f"The prices for {product_pricing_instance.product.product_name} have changed as follows; End users - {product_net_price}, Technicians - {product_net_price_technician}, Resellers - {product_net_price_reseller}, Financiers - {product_net_price_financier}, Engineering Procurement Contractors - {product_net_price_engineering_procurement_contractor}. Changes effected by {staff_profile.first_name} {staff_profile.last_name} ({staff_profile.staff_position.position_title})"
                # recipient_list = [f'{staff_requesting_leave.personal_email}']
                # try:
                #     send_general_mail(request, subject,
                #                     message, recipient_list)
                # except:
                #     pass
                try:
                    list_of_staff_ids = []
                    all_relevant_staff = StaffProfile.objects.filter(
                        recycle_bin=False)
                    for staff in all_relevant_staff:
                        if staff.company_department != "human_resource_management" or staff.company_department != "warehouse_management":
                            list_of_staff_ids.append(
                                staff.id)
                    notification_title = subject
                    notification_body = message
                    create_notifications(notification_title,
                                         notification_body, list_of_staff_ids)
                except:
                    pass
                return Response({"message": "Product pricing updated successfully", }, status=200)
            else:
                error_messages = [str(value[0])
                                  for value in product_pricing_serializer.errors.values()]
                return Response({"message": error_messages[0], }, 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 updating product pricing", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_product_discount(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    product_discount_id = request.data["product_discount_id"]
    discount_type = request.data["discount_type"]
    discount_value = request.data["discount_value"]
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        if user_has_permission(staff_profile, "sales_and_marketing.product_catalog.edit"):
            product_discount_instance = ProductDiscount.objects.get(
                id=int(product_discount_id))
            product_discount_serializer = ProductDiscountSerializer(
                instance=product_discount_instance, data={'discount_type': discount_type, 'discount_value': discount_value})
            if product_discount_serializer.is_valid():
                product_discount_serializer.save()
                return Response({"message": "Product discount updated successfully", }, status=200)
            else:
                error_messages = [str(value[0])
                                  for value in product_discount_serializer.errors.values()]
                return Response({"message": error_messages[0], }, 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 updating product discount", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_product_vat(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    product_vat_id = request.data["product_vat_id"]
    vat_percentage_value = request.data["vat_percentage_value"]
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        if user_has_permission(staff_profile, "sales_and_marketing.product_catalog.edit"):
            product_vat_instance = ProductVAT.objects.get(
                id=int(product_vat_id))
            product_vat_serializer = ProductVATSerializer(
                instance=product_vat_instance, data={'vat_percentage_value': vat_percentage_value, })
            if product_vat_serializer.is_valid():
                product_vat_serializer.save()
                return Response({"message": "Product V.A.T value updated successfully", }, status=200)
            else:
                error_messages = [str(value[0])
                                  for value in product_vat_serializer.errors.values()]
                return Response({"message": error_messages[0], }, 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 updating product discount", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_landed_cost(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    name_of_expense = request.data["name_of_expense"]
    description_of_calculation = request.data["description_of_calculation"]
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        if user_has_permission(staff_profile, "sales_and_marketing.landed_cost.add"):
            landed_cost_serializer = LandedCostSerializer(
                data={'company_profile': company_profile.id, 'name_of_expense': name_of_expense, 'description_of_calculation': description_of_calculation, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            if landed_cost_serializer.is_valid():
                landed_cost_serializer.save()
                return Response({"message": "Landed cost created successfully", }, status=200)
            else:
                return Response({"message": "Unable to create landed cost", }, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:
        return Response({"message": "Error creating landed cost", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_landed_cost(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    name_of_expense = request.data["name_of_expense"]
    description_of_calculation = request.data["description_of_calculation"]
    landed_cost_id = request.data["landed_cost_id"]
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        landed_cost_instance = LandedCost.objects.get(id=int(landed_cost_id))
        if user_has_permission(staff_profile, "sales_and_marketing.landed_cost.edit"):
            landed_cost_serializer = LandedCostSerializer(instance=landed_cost_instance,
                                                          data={'company_profile': company_profile.id, 'name_of_expense': name_of_expense, 'description_of_calculation': description_of_calculation, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            if landed_cost_serializer.is_valid():
                landed_cost_serializer.save()
                return Response({"message": "Landed cost edited successfully", }, status=200)
            else:
                return Response({"message": "Unable to edit landed cost", }, status=406)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:
        return Response({"message": "Error editing landed cost", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_landed_cost(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    landed_cost_id = request.data["landed_cost_id"]
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        # if (staff_profile.company_department.department_name == "sales") and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
        if user_has_permission(staff_profile, "sales_and_marketing.landed_cost.delete"):
            landed_cost_instance = LandedCost.objects.get(
                id=int(landed_cost_id))
            if landed_cost_instance.recycle_bin != True:
                landed_cost_instance.recycle_bin = True
                landed_cost_instance.save()
                return Response({"message": "Landed cost deleted successfully", }, status=200)
            else:

                landed_cost_instance.delete()
                return Response({"message": "You have permanently deleted landed cost", }, status=200)
        else:
            return Response({"message": "You are unauthorized to perform this action", }, status=401)
    except:
        return Response({"message": "Error deleting landed cost", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_customer(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    customer_first_name = request.data["customer_first_name"]
    customer_last_name = request.data["customer_last_name"]
    email_address = request.data["email_address"]
    phone_number = request.data["phone_number"]
    customer_title = request.data["customer_title"]
    company_name = request.data["company_name"]
    customer_type = request.data["customer_type"]
    customer_account_manager_id = request.data.get("customer_account_manager_id", "")
    phone_number_exists = False
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        # RBAC for the ERP UI; legacy sales/marketing department for the CRM contract.
        authorized = (
            user_has_permission(staff_profile, "sales_and_marketing.customer.add")
            or check_if_system_administrator(staff_profile)
        )
        if not authorized and staff_profile.company_department is not None:
            authorized = staff_profile.company_department.department_name in ("sales", "marketing")
        if authorized:
            try:
                existing_cus = CustomerProfile.objects.get(
                    phone_number=phone_number)
                if existing_cus is not None:
                    phone_number_exists = True
            except Exception:
                pass
            if phone_number_exists != True:
                password = generate_random_string(6)
                serializers = UserSerializer(
                    data={'username': email_address, 'password': password})
                if serializers.is_valid():
                    user = serializers.save()
                    authenticate(
                        username=email_address, password=password)
                    customer_profile, _created = CustomerProfile.objects.get_or_create(
                        user=user,
                        email_address=user.username,
                        company_profile=company_profile,
                        customer_first_name=customer_first_name,
                        customer_last_name=customer_last_name,
                        phone_number=phone_number,
                        customer_title=customer_title,
                        company_name=company_name,
                        customer_type=customer_type,
                        is_profile_set=True,
                    )
                    # Assign the account manager (ported from live CRM flow).
                    if customer_account_manager_id:
                        try:
                            cam_staff = StaffProfile.objects.get(
                                id=int(customer_account_manager_id))
                            CustomerAccountManager.objects.get_or_create(
                                customer_profile=customer_profile,
                                defaults={"staff_profile": cam_staff})
                            # new managed customer changes portfolio metrics — refresh CRM
                            try:
                                from megawatt_api.crm_webhook import notify_crm_staff_performance
                                notify_crm_staff_performance([cam_staff.id])
                            except Exception as perf_error:
                                print(perf_error)
                        except Exception:
                            pass
                    recipient_list = [f'{email_address}']
                    message = "You have been successfully registered on Megawatt Energies Customer Platform. We're excited to welcome you to the Megawatt Energies family!"
                    try:
                        send_email_signup(request, message, recipient_list)
                    except Exception:
                        pass
                    return Response({"message": "Customer account created successfully", }, status=200)
                return Response({"message": "Unable to create customer account", }, status=406)
            return Response({"message": "A customer with a similar phone number already exists", }, status=406)
        return Response({"message": "You are unauthorized to perform this action", }, status=401)
    except Exception:
        return Response({"message": "Error creating customer account", }, status=500)



@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_customer(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    customer_first_name = request.data["customer_first_name"]
    customer_last_name = request.data["customer_last_name"]
    email_address = request.data["email_address"]
    phone_number = request.data["phone_number"]
    customer_title = request.data["customer_title"]
    company_name = request.data["company_name"]
    customer_type = request.data["customer_type"]
    customer_id = request.data.get("customer_id", "")
    kra_pin = request.data["kra_pin"]
    certificate_of_registration_number = request.data["certificate_of_registration_number"]
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        # if (staff_profile.company_department.department_name == "sales") and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
        if user_has_permission(staff_profile, "sales_and_marketing.customer.edit"):
            # password = generate_random_string(6)
            # Resolve by id, falling back to email within the company (CRM-safe).
            customer_profile_instance = None
            if customer_id:
                try:
                    customer_profile_instance = CustomerProfile.objects.get(
                        id=int(customer_id), company_profile=company_profile)
                except (ValueError, CustomerProfile.DoesNotExist):
                    customer_profile_instance = None
            if customer_profile_instance is None:
                try:
                    customer_profile_instance = CustomerProfile.objects.get(
                        email_address__iexact=email_address,
                        company_profile=company_profile)
                except CustomerProfile.DoesNotExist:
                    return Response({"message": "Customer account not found", }, status=406)
            serializers = CustomerProfileSerializer(instance=customer_profile_instance,
                                                    data={'customer_first_name': customer_first_name, 'customer_last_name': customer_last_name, 'kra_pin': kra_pin, 'certificate_of_registration_number': certificate_of_registration_number, 'email_address': email_address, 'phone_number': phone_number, 'customer_title': customer_title, 'company_name': company_name, 'customer_type': customer_type})
            if serializers.is_valid():
                serializers.save()

                return Response({"message": "Customer account updated successfully", }, status=200)
            else:
                print(serializers.errors)
                return Response({"message": "Unable to update customer account", }, status=406)
        else:
            return Response({"message": "You are unauthorized to perform this action", }, status=401)
    except:  # Exception as e:
        # print(e)
        return Response({"message": "Error updating customer account", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_customer(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    customer_id_to_delete = request.data["customer_id_to_delete"]
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        # if (staff_profile.company_department.department_name == "sales") and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
        if user_has_permission(staff_profile, "sales_and_marketing.customer.delete"):
            customer_instance = CustomerProfile.objects.get(
                id=int(customer_id_to_delete))
            if customer_instance.recycle_bin != True:
                customer_instance.recycle_bin = True
                customer_instance.save()
                return Response({"message": "Customer account deleted successfully", }, status=200)
            else:
                corresponding_user = customer_instance.user
                customer_instance.delete()
                corresponding_user.delete()
                return Response({"message": "You have permanently deleted customer account", }, status=200)
        else:
            return Response({"message": "You are unauthorized to perform this action", }, status=401)
    except:
        return Response({"message": "Error deleting customer account", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_sale_outlet(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    sale_outlet_name = request.data["sale_outlet_name"]
    # company_branch_id = request.data["company_branch_id"]
    sale_outlet_location = request.data["sale_outlet_location"]
    sale_outlet_contact_phone = request.data["sale_outlet_contact_phone"]
    sale_outlet_description = request.data["sale_outlet_description"]
    # print(request.data)
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        if user_has_permission(staff_profile, "sales_and_marketing.sale_outlet.add"):
            company_branch_id = staff_profile.company_branch.id
            sale_outlet_serializer = SaleOutletSerializer(data={'company_branch': int(company_branch_id), 'sale_outlet_name': sale_outlet_name,
                                                          'sale_outlet_location': sale_outlet_location, 'sale_outlet_contact_phone': sale_outlet_contact_phone, 'sale_outlet_description': sale_outlet_description})
            if sale_outlet_serializer.is_valid():
                sale_outlet_serializer.save()
                return Response({"message": "Sale outlet created successfully", }, status=200)
            else:
                error_messages = [str(value[0])
                                  for value in sale_outlet_serializer.errors.values()]
                Response({"message": error_messages[0], }, status=406)
        else:
            return Response({"message": "You are unauthorized to perform this action", }, status=401)
    except:  # Exception as e:
        # print(e)
        return Response({"message": "Error creating sale outlet", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_sale_quotation(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    quotation_net_value = request.data["quotation_net_value"]
    customer_id = request.data["customer_id"]
    sales_quotation_items_list = request.data.get(
        'sales_quotation_items_list', [])
    sales_quotation_items_list = json.loads(
        sales_quotation_items_list)
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        if user_has_permission(staff_profile, "sales_and_marketing.quotation.add"):
            company_branch = staff_profile.company_branch
            ok, stock_error = validate_line_items_stock(company_branch, sales_quotation_items_list)
            if not ok:
                return Response({"message": stock_error}, status=406)
            customer_profile = CustomerProfile.objects.get(id=int(customer_id))
            sale_quotation_instance = SalesQuotation.objects.create(
                quotation_net_value=str(quotation_net_value),
                company_branch=company_branch,
                created_by=staff_profile,
                last_updated_by=staff_profile,
                customer_profile=customer_profile,
            )
            for sale_quotation_item in sales_quotation_items_list:
                product_id = sale_quotation_item["product_id"]
                quantity = sale_quotation_item["quantity"]
                price_per_item = sale_quotation_item["price_per_item"]
                discount_per_item = sale_quotation_item["discount_per_item"]
                gross_subtotal = sale_quotation_item["gross_subtotal"]
                total_discount = sale_quotation_item["total_discount"]
                net_subtotal = sale_quotation_item["net_subtotal"]
                request_price_change = True if str(
                    sale_quotation_item.get("request_price_change", "false")).lower() == "true" else False
                requested_new_price_after_discount = sale_quotation_item.get(
                    "requested_new_price_after_discount", "0.00")
                quotation_item_serializer = SalesQuotationItemSerializer(data={'sales_quotation': sale_quotation_instance.id, 'product': int(
                    product_id), 'quantity': quantity, 'price_per_item': price_per_item, 'discount_per_item': discount_per_item, 'gross_subtotal': gross_subtotal, 'total_discount': total_discount, 'net_subtotal': net_subtotal, 'request_price_change': request_price_change, 'requested_new_price_after_discount': requested_new_price_after_discount})
                if quotation_item_serializer.is_valid():
                    quotation_item_serializer.save()
                else:
                    sale_quotation_instance.delete()
                    return Response({"message": "Error creating quotation item", }, status=406)
            return Response({
                "message": "Sale quotation created successfully",
                "payload": {
                    "sale_quotation_id": str(sale_quotation_instance.id),
                    "sales_quotation_number": sale_quotation_instance.sales_quotation_number,
                },
            }, status=200)
        else:
            return Response({"message": "You are unauthorized to perform this action", }, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "Error creating sale quotation", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def approve_sale_quotation(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    sale_quotation_id = int(request.data["sale_quotation_id"])
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        sale_quotation_instance = SalesQuotation.objects.get(
            id=sale_quotation_id)
        # if (staff_profile.company_department.department_name == "sales") and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
        if user_has_permission(staff_profile, "sales_and_marketing.quotation.approve"):
            sale_quotation_instance = SalesQuotation.objects.get(
                id=sale_quotation_id)
            sale_quotation_instance.sales_quotation_approved = True
            sale_quotation_instance.save()
            try:
                from sales_and_marketing.crm_quote_sync import sync_quotation_to_crm
                sync_quotation_to_crm(sale_quotation_instance, event="approved")
            except Exception as crm_exc:
                print(crm_exc)
            return Response({"message": "Sale quotation approved successfully"}, status=200)
        else:
            return Response({"message": "You are unauthorised to perform this action"}, status=401)

    except:
        return Response({"message": "Error approving sale quotation"}, status=200)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_sale_quotation_items(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    sale_quotation_id = int(request.data["sale_quotation_id"])
    quotation_net_value = 0.00
    sales_quotation_items_list = request.data.get(
        'sales_quotation_items_list', [])
    sales_quotation_items_list = json.loads(
        sales_quotation_items_list)
    quotation_price_change_request_active = False
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        # if (staff_profile.company_department.department_name == "sales") and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
        if user_has_permission(staff_profile, "sales_and_marketing.quotation.edit"):
            company_branch = staff_profile.company_branch
            ok, stock_error = validate_line_items_stock(company_branch, sales_quotation_items_list)
            if not ok:
                return Response({"message": stock_error}, status=406)
            sale_quotation_instance = SalesQuotation.objects.get(
                id=sale_quotation_id)
            quotation_price_change_request_active = sale_quotation_instance.quotation_price_change_request_active
            existing_sales_quotation_items = sale_quotation_instance.sales_quotation_items.all()
            for existing_item in existing_sales_quotation_items:
                existing_item.delete()
            for sale_quotation_item in sales_quotation_items_list:
                product_id = sale_quotation_item["product_id"]
                quantity = sale_quotation_item["quantity"]
                price_per_item = sale_quotation_item["price_per_item"]
                discount_per_item = sale_quotation_item["discount_per_item"]
                gross_subtotal = sale_quotation_item["gross_subtotal"]
                total_discount = sale_quotation_item["total_discount"]
                net_subtotal = sale_quotation_item["net_subtotal"]
                request_price_change = True if sale_quotation_item[
                    "request_price_change"] == "true" else False
                if quotation_price_change_request_active != True and request_price_change == True:
                    quotation_price_change_request_active = True
                    # create a notification
                    try:
                        list_of_staff_ids = get_hod_technical_sales_ids()
                        notification_title = "Price Change Request"
                        notification_body = f"Price change requested on sale quotation {sale_quotation_instance.sales_quotation_number}. Your approval is required urgently!"
                        create_notifications(notification_title,
                                             notification_body, list_of_staff_ids)
                    except Exception as e:
                        print(e)
                        pass
                    #
                requested_new_price_after_discount = sale_quotation_item[
                    "requested_new_price_after_discount"]

                quotation_item_serializer = SalesQuotationItemSerializer(data={'sales_quotation': sale_quotation_instance.id, 'product': int(
                    product_id), 'quantity': quantity, 'price_per_item': price_per_item, 'discount_per_item': discount_per_item, 'gross_subtotal': gross_subtotal, 'total_discount': total_discount, 'net_subtotal': net_subtotal, 'request_price_change': request_price_change, 'requested_new_price_after_discount': requested_new_price_after_discount})
                if quotation_item_serializer.is_valid():
                    quotation_item_serializer.save()
                    quotation_net_value += float(
                        sale_quotation_item["net_subtotal"])
                else:
                    print(quotation_item_serializer.errors)
            sale_quotation_instance.quotation_net_value = f"{quotation_net_value}"
            sale_quotation_instance.quotation_price_change_request_active = quotation_price_change_request_active
            sale_quotation_instance.save()
            try:
                from sales_and_marketing.crm_quote_sync import sync_quotation_to_crm
                sync_quotation_to_crm(sale_quotation_instance, event="updated")
            except Exception as crm_exc:
                print(crm_exc)
            return Response({"message": "Sale quotation updated successfully", }, status=200)
        else:
            return Response({"message": "You are unauthorized to perform this action", }, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "Error editing sale quotation", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def approve_price_change_quotation(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    sale_quotation_id = int(request.data["sale_quotation_id"])
    quotation_net_value = 0.00
    sales_quotation_items_list = request.data.get(
        'sales_quotation_items_list', [])
    sales_quotation_items_list = json.loads(
        sales_quotation_items_list)
    # quotation_price_change_request_active = False
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        if user_has_permission(staff_profile, "sales_and_marketing.quotation.approve"):
            sale_quotation_instance = SalesQuotation.objects.get(
                id=sale_quotation_id)
            existing_sales_quotation_items = sale_quotation_instance.sales_quotation_items.all()
            for existing_item in existing_sales_quotation_items:
                existing_item.delete()
            for sale_quotation_item in sales_quotation_items_list:
                product_id = sale_quotation_item["product_id"]
                quantity = sale_quotation_item["quantity"]
                price_per_item = sale_quotation_item["price_per_item"]
                discount_per_item = sale_quotation_item["discount_per_item"]
                gross_subtotal = sale_quotation_item["gross_subtotal"]
                total_discount = sale_quotation_item["total_discount"]
                net_subtotal = sale_quotation_item["net_subtotal"]
                request_price_change = True if sale_quotation_item[
                    "request_price_change"] == "true" else False
                requested_new_price_after_discount = sale_quotation_item[
                    "requested_new_price_after_discount"]
                requested_price_change_approved = True if sale_quotation_item[
                    "requested_price_change_approved"] == "true" else False
                # if requested_price_change_approved == True:

                quotation_item_serializer = SalesQuotationItemSerializer(data={'sales_quotation': sale_quotation_instance.id, 'product': int(
                    product_id), 'quantity': quantity, 'price_per_item': price_per_item, 'discount_per_item': discount_per_item, 'gross_subtotal': gross_subtotal, 'total_discount': total_discount, 'net_subtotal': net_subtotal, 'request_price_change': request_price_change, 'requested_new_price_after_discount': requested_new_price_after_discount, 'requested_price_change_approved': requested_price_change_approved})
                if quotation_item_serializer.is_valid():
                    quotation_item_serializer.save()
                    quotation_net_value += float(
                        sale_quotation_item["net_subtotal"])
                else:
                    print(quotation_item_serializer.errors)
            sale_quotation_instance.quotation_net_value = f"{quotation_net_value}"
            sale_quotation_instance.quotation_price_change_request_active = False
            sale_quotation_instance.save()
            try:
                from sales_and_marketing.crm_quote_sync import sync_quotation_to_crm
                sync_quotation_to_crm(sale_quotation_instance, event="price_change_approved")
            except Exception as crm_exc:
                print(crm_exc)
            return Response({"message": "Sale quotation updated successfully", }, status=200)
        else:
            return Response({"message": "You are unauthorized to perform this action", }, status=401)
    except Exception as e:
        print(e)
        return Response({"message": "Error editing sale quotation", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_customer_order(request):
    date_format = '%d/%m/%Y'
    active_user = request.user

    try:
        company_serial_number = request.data["serial_number"]
        customer_id = request.data["customer_id"]
        customer_order_type = request.data["customer_order_type"]
        customer_order_description = request.data["customer_order_description"]
        customer_order_total_gross_value = request.data["customer_order_total_gross_value"]
        customer_order_total_discount = request.data["customer_order_total_discount"]
        customer_order_total_net_value = request.data["customer_order_total_net_value"]
        customer_order_approved = request.data["customer_order_approved"]
        sales_person_id = request.data["sales_person_id"]
        expected_delivery_date = datetime.strptime(
            request.data["expected_delivery_date"], date_format).strftime("%Y-%m-%d") if len(request.data["expected_delivery_date"]) > 0 else None
        customer_order_items_list = request.data.get(
            'customer_order_items_list', [])
        customer_order_items_list = json.loads(
            customer_order_items_list)
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        # if (staff_profile.company_department.department_name == "sales") and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
        if user_has_permission(staff_profile, "sales_and_marketing.customer_order.add"):
            company_branch = staff_profile.company_branch
            ok, stock_error = validate_line_items_stock(company_branch, customer_order_items_list)
            if not ok:
                return Response({"message": stock_error}, status=406)
            customer_profile = None
            sales_person = None
            try:
                if len(customer_id) > 0:
                    customer_profile = CustomerProfile.objects.get(
                        id=int(customer_id))
            except:
                customer_profile = None
            try:
                if len(sales_person_id) > 0:
                    sales_person = StaffProfile.objects.get(
                        id=int(sales_person_id))
            except:
                sales_person = None
            customer_order_serializer = CustomerOrderSerializer(
                data={'company_branch': company_branch.id, 'customer_profile': customer_profile.id, 'customer_order_type': customer_order_type, 'customer_order_description': customer_order_description, 'customer_order_total_gross_value': customer_order_total_gross_value, 'customer_order_total_discount': customer_order_total_discount, 'customer_order_total_net_value': customer_order_total_net_value, 'customer_order_approved': customer_order_approved, 'expected_delivery_date': expected_delivery_date, 'sales_person': sales_person.id, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            if customer_order_serializer.is_valid():
                new_order = customer_order_serializer.save()
                for customer_order_item in customer_order_items_list:
                    product_id = customer_order_item["product_id"]
                    quantity = customer_order_item["quantity"]
                    price_per_item = customer_order_item["price_per_item"]
                    discount_per_item = customer_order_item["discount_per_item"]
                    gross_subtotal = customer_order_item["gross_subtotal"]
                    total_discount = customer_order_item["total_discount"]
                    net_subtotal = customer_order_item["net_subtotal"]
                    order_item_serializer = CustomerOrderItemSerializer(data={'customer_order': new_order.id, 'product': int(
                        product_id), 'quantity': quantity, 'price_per_item': price_per_item, 'discount_per_item': discount_per_item, 'gross_subtotal': gross_subtotal, 'total_discount': total_discount, 'net_subtotal': net_subtotal})
                    if order_item_serializer.is_valid():
                        order_item_serializer.save()
                # notify finance department
                try:
                    list_of_staff_ids = []
                    # get finance department staff
                    finance_dept = CompanyDepartment.objects.get(
                        department_name="finance_and_accounting")
                    all_finance_staff = StaffProfile.objects.filter(
                        company_department=finance_dept)
                    for finance_staff in all_finance_staff:
                        list_of_staff_ids.append(
                            finance_staff.id)
                    notification_title = f"Customer Order {new_order.customer_order_number}"
                    notification_body = f"A new customer order of number {new_order.customer_order_number} has been created. Approval by finance department is required."
                    create_notifications(notification_title,
                                         notification_body, list_of_staff_ids)
                except:
                    pass
                return Response({"message": f"Customer order {new_order.customer_order_number} created successfully", }, status=200)
            else:
                # print(customer_order_serializer.errors)
                return Response({"message": "Error creating customer order", }, status=406)
        else:
            return Response({"message": "You are unauthorized to perform this action", }, status=401)
    except:  # Exception as e:
        # print(e)
        return Response({"message": "Error creating customer order", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def convert_quotation_to_order(request):
    """Convert an approved ERP quotation into a customer order.

    Mirrors CRM push-to-ERP: stock reservation, finance notification, and
    CRM webhooks for stock + performance + quote conversion status.
    """
    from datetime import date as date_cls
    from decimal import Decimal
    from sales_and_marketing.models import CustomerOrder, CustomerOrderItem, SalesQuotationItem
    from sales_and_marketing.crm_quote_sync import (
        build_crm_quotation_converted_payload,
        quotation_has_price_change,
    )
    from megawatt_api.crm_quote_webhook import notify_crm_quotation
    from megawatt_api.crm_webhook import notify_crm_staff_performance, account_manager_staff_ids_for_order
    from megawatt_api.stock_webhook import notify_crm_stock

    date_format = '%d/%m/%Y'
    try:
        company_serial_number = request.data["serial_number"]
        sale_quotation_id = int(request.data["sale_quotation_id"])
        expected_delivery_date = request.data.get("expected_delivery_date", "")
        sales_person_id = request.data.get("sales_person_id", "")

        staff_profile = StaffProfile.objects.get(user=request.user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)

        if not user_has_permission(staff_profile, "sales_and_marketing.customer_order.add"):
            return Response({"message": "You are unauthorized to perform this action"}, status=401)

        quotation = SalesQuotation.objects.get(id=sale_quotation_id, recycle_bin=False)
        if CustomerOrder.objects.filter(source_quotation=quotation, recycle_bin=False).exists():
            return Response({"message": "Quotation already converted to an order"}, status=406)

        if quotation_has_price_change(quotation) and not quotation.sales_quotation_approved:
            return Response({
                "message": "Quotation requires price-change approval before conversion",
            }, status=406)

        line_items = []
        for qi in SalesQuotationItem.objects.filter(sales_quotation=quotation):
            line_items.append({
                "product_id": str(qi.product_id),
                "quantity": qi.quantity,
                "price_per_item": qi.price_per_item,
                "discount_per_item": qi.discount_per_item,
                "gross_subtotal": qi.gross_subtotal,
                "total_discount": qi.total_discount,
                "net_subtotal": qi.net_subtotal,
            })

        company_branch = staff_profile.company_branch
        ok, stock_error = validate_line_items_stock(company_branch, line_items)
        if not ok:
            return Response({"message": stock_error}, status=406)

        def _d(v):
            return Decimal(str(v or "0").replace(",", "") or "0")

        gross_total = Decimal("0")
        discount_total = Decimal("0")
        net_total = Decimal("0")
        for qi in SalesQuotationItem.objects.filter(sales_quotation=quotation):
            gross_total += _d(qi.gross_subtotal)
            discount_total += _d(qi.total_discount)
            net_total += _d(qi.net_subtotal)

        sales_person = staff_profile
        if sales_person_id and len(str(sales_person_id)) > 0:
            try:
                sales_person = StaffProfile.objects.get(id=int(sales_person_id))
            except Exception:
                sales_person = staff_profile

        delivery = date_cls.today()
        if expected_delivery_date and len(str(expected_delivery_date)) > 0:
            delivery = datetime.strptime(
                expected_delivery_date, date_format).date()

        customer_order_serializer = CustomerOrderSerializer(data={
            'company_branch': company_branch.id,
            'customer_profile': quotation.customer_profile_id,
            'source_quotation': quotation.id,
            'customer_order_type': 'order_offline',
            'customer_order_description': quotation.sales_quotation_number,
            'customer_order_total_gross_value': str(gross_total.quantize(Decimal("0.01"))),
            'customer_order_total_discount': str(discount_total.quantize(Decimal("0.01"))),
            'customer_order_total_net_value': str(net_total.quantize(Decimal("0.01"))),
            'customer_order_approved': False,
            'expected_delivery_date': delivery,
            'sales_person': sales_person.id,
            'created_by': staff_profile.id,
            'last_updated_by': staff_profile.id,
            'origin': 'erp',
        })
        if not customer_order_serializer.is_valid():
            return Response({"message": "Error creating customer order"}, status=406)

        new_order = customer_order_serializer.save()
        for qi in SalesQuotationItem.objects.filter(sales_quotation=quotation):
            CustomerOrderItem.objects.create(
                customer_order=new_order,
                product=qi.product,
                quantity=qi.quantity,
                price_per_item=qi.price_per_item,
                discount_per_item=qi.discount_per_item,
                gross_subtotal=qi.gross_subtotal,
                total_discount=qi.total_discount,
                net_subtotal=qi.net_subtotal,
            )

        try:
            from warehouse_management.stock_availability import reserve_stock_for_order
            affected_product_ids = reserve_stock_for_order(new_order, staff_profile)
            if affected_product_ids:
                notify_crm_stock(affected_product_ids)
        except Exception as stock_error:
            print(stock_error)

        try:
            finance_dept = CompanyDepartment.objects.get(
                department_name="finance_and_accounting")
            finance_ids = list(
                StaffProfile.objects.filter(company_department=finance_dept).values_list("id", flat=True))
            create_notifications(
                f"Customer Order {new_order.customer_order_number}",
                f"A new customer order of number {new_order.customer_order_number} has been created. Approval by finance department is required.",
                finance_ids,
            )
        except Exception:
            pass

        try:
            notify_crm_staff_performance(account_manager_staff_ids_for_order(new_order))
        except Exception as perf_error:
            print(perf_error)

        try:
            notify_crm_quotation(build_crm_quotation_converted_payload(quotation, new_order))
        except Exception as crm_exc:
            print(crm_exc)

        return Response({
            "message": f"Customer order {new_order.customer_order_number} created from quotation",
            "payload": {
                "customer_order_id": str(new_order.id),
                "customer_order_number": new_order.customer_order_number,
            },
        }, status=200)
    except SalesQuotation.DoesNotExist:
        return Response({"message": "Quotation not found"}, status=404)
    except Exception as e:
        print(e)
        return Response({"message": "Error converting quotation to order"}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_sale_order(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    customer_order_id = request.data["customer_order_id"]
    # sale_outlet_id = request.data["sale_outlet_id"]
    warehouse_id = request.data["warehouse_id"]
    sales_order_description = request.data["sales_order_description"]
    # sales_order_items_list = request.data.get(
    #     'sales_order_items_list', [])
    # sales_order_items_list = json.loads(
    #     sales_order_items_list)
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        # if (staff_profile.company_department.department_name == "sales") and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
        if user_has_permission(staff_profile, "sales_and_marketing.customer_order.add"):
            # company_branch = staff_profile.company_branch
            sales_order_serializer = SalesOrderSerializer(
                data={'customer_order': int(customer_order_id), 'warehouse': int(warehouse_id), 'sales_order_description': sales_order_description, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            if sales_order_serializer.is_valid():
                new_sales_order = sales_order_serializer.save()
                customer_order_instance = CustomerOrder.objects.get(
                    id=int(customer_order_id))
                for sale_order_item in customer_order_instance.customer_order_items.all():
                    product_id = sale_order_item.product.id
                    quantity = sale_order_item.quantity
                    sale_order_item_serializer = SalesOrderItemsSerializer(
                        data={'sales_order': new_sales_order.id, 'product': product_id, 'quantity': quantity})
                    if sale_order_item_serializer.is_valid():
                        sale_order_item_serializer.save()
                # create stock requisition
                stock_requisition_serializer = StockRequisitionSerializer(
                    data={'warehouse': int(warehouse_id), 'stock_requisition_description': new_sales_order.sales_order_number, 'created_by': staff_profile.id,
                          'last_updated_by': staff_profile.id, })
                if stock_requisition_serializer.is_valid():
                    new_stock_requisition = stock_requisition_serializer.save()
                    for sale_order_item in customer_order_instance.customer_order_items.all():
                        product_id = sale_order_item.product.id
                        quantity = sale_order_item.quantity
                        stock_requisition_instance_serializer = StockRequisitionInstanceSerializer(
                            data={'product': product_id, 'quantity': quantity, 'stock_requisition': new_stock_requisition.id, 'created_by': staff_profile.id,
                                  'last_updated_by': staff_profile.id, })
                        if stock_requisition_instance_serializer.is_valid():
                            stock_requisition_instance_serializer.save()
                    try:
                        # notify warehouse
                        active_warehouse = Warehouse.objects.get(
                            id=int(warehouse_id))
                        warehouse_branch = active_warehouse.company_branch
                        all_warehouse_heads = StaffProfile.objects.filter(
                            company_branch=warehouse_branch, is_head_of_department=True)
                        list_of_staff_ids = []
                        for warehouse_staff in all_warehouse_heads:
                            list_of_staff_ids.append(
                                warehouse_staff.id)
                        notification_title = f"New Stock Requisition Created"
                        notification_body = f"Stock requisition of number {new_stock_requisition.stock_requisition_number} has been created. Approval by warehouse department is required."
                        create_notifications(notification_title,
                                             notification_body, list_of_staff_ids)
                    except:
                        pass
                else:
                    pass
                    # print(stock_requisition_serializer.errors)
                # end of creating stock requisition
                return Response({"message": "Sale order created successfully", }, status=200)
            else:
                # print(sales_order_serializer.errors)
                return Response({"message": "Unable to create sale order", }, 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 sales order", }, status=500)


# @api_view(['POST'])
# @authentication_classes([TokenAuthentication])
# @permission_classes([IsAuthenticated])
# def create_customer_order_payment(request):
#     active_user = request.user
#     company_serial_number = request.data["serial_number"]
#     customer_order_id = request.data["customer_order_id"]
#     payment_method = request.data["payment_method"]
#     payer_account_number = request.data["payer_account_number"]
#     try:
#         staff_profile = StaffProfile.objects.get(user=active_user)
#         company_profile = CompanyProfile.objects.get(
#             company_serial_number=company_serial_number)
#         if staff_profile.company_department.department_name == "sales" and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
#             customer_order_payment_serializer = CustomerOrderPaymentSerializer(data={'customer_order': int(
#                     customer_order_id), 'payment_method': payment_method, 'payer_account_number': payer_account_number})
#             if customer_order_payment_serializer.is_valid():
#                 new_payment = customer_order_payment_serializer.save()
#                 return Response({"message": f"payment {new_payment.payment_number} created successfully", }, status=200)
#             else:
#                 error_messages = [str(value[0])
#                                   for value in customer_order_payment_serializer.errors.values()]
#                 Response({"message": error_messages[0], }, status=406)
#         else:
#             return Response({"message": "You are unauthorized to perform this action", }, status=401)
#     except:  # Exception as e:
#         # print(e)
#         return Response({"message": "Error creating order payment", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def edit_customer_order(request):
    active_user = request.user
    date_format = '%d/%m/%Y'
    try:
        company_serial_number = request.data["serial_number"]
        customer_order_id = request.data["customer_order_id"]
        customer_order_fulfilled_for_transit = True if request.data[
            "customer_order_fulfilled_for_transit"] == "true" else False
        customer_ordered_delivered_to_destination = True if request.data[
            "customer_ordered_delivered_to_destination"] == "true" else False
        customer_order_picked_by_customer = True if request.data[
            "customer_order_picked_by_customer"] == "true" else False
        customer_order_cancelled_by_customer = True if request.data[
            "customer_order_cancelled_by_customer"] == "true" else False
        customer_order_cancelled_by_sales_team = True if request.data[
            "customer_order_cancelled_by_sales_team"] == "true" else False
        expected_delivery_date = datetime.strptime(
            request.data["expected_delivery_date"], date_format).strftime("%Y-%m-%d") if len(request.data["expected_delivery_date"]) > 0 else None
        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 == "sales") and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
        if user_has_permission(staff_profile, "sales_and_marketing.customer_order.edit"):
            customer_order_instance = CustomerOrder.objects.get(
                id=int(customer_order_id))
            # customer_order_instance.customer_order_approved = True
            customer_order_serializer = CustomerOrderSerializer(instance=customer_order_instance, data={'customer_order_fulfilled_for_transit': customer_order_fulfilled_for_transit, 'customer_ordered_delivered_to_destination': customer_ordered_delivered_to_destination,
                                                                'customer_order_picked_by_customer': customer_order_picked_by_customer, 'customer_order_cancelled_by_customer': customer_order_cancelled_by_customer, 'customer_order_cancelled_by_sales_team': customer_order_cancelled_by_sales_team, 'expected_delivery_date': expected_delivery_date})
            if customer_order_serializer.is_valid():
                customer_order_serializer.save()
                try:
                    sales_order = SalesOrder.objects.get(
                        customer_order=customer_order_instance)
                    sales_order.sales_order_fulfilled = customer_order_fulfilled_for_transit
                    sales_order.save()
                except:
                    pass
                return Response({"message": "Customer order updated successfully", }, status=200)
            else:
                return Response({"message": "Unable to update customer order", }, 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 updating customer order", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_sale_quotation(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    sale_quotation_id_to_delete = request.data["sale_quotation_id_to_delete"]
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        # if (staff_profile.company_department.department_name == "sales") and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
        if user_has_permission(staff_profile, "sales_and_marketing.quotation.delete"):
            sale_quotation_instance = SalesQuotation.objects.get(
                id=int(sale_quotation_id_to_delete))
            if sale_quotation_instance.recycle_bin != True:
                sale_quotation_instance.recycle_bin = True
                sale_quotation_instance.save()
                return Response({"message": "Sale quotation deleted successfully", }, status=200)
            else:

                sale_quotation_instance.delete()
                return Response({"message": "You have permanently deleted sale quotation", }, status=200)
        else:
            return Response({"message": "You are unauthorized to perform this action", }, status=401)
    except:
        return Response({"message": "Error deleting sale quotation", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_customer_order(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    customer_order_id_to_delete = request.data["customer_order_id_to_delete"]
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        # if (staff_profile.company_department.department_name == "sales") and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
        if user_has_permission(staff_profile, "sales_and_marketing.customer_order.delete"):
            customer_order_instance = CustomerOrder.objects.get(
                id=int(customer_order_id_to_delete))
            if customer_order_instance.recycle_bin != True:
                customer_order_instance.recycle_bin = True
                customer_order_instance.save()
                return Response({"message": "Customer order deleted successfully", }, status=200)
            else:

                customer_order_instance.delete()
                return Response({"message": "You have permanently deleted customer order", }, status=200)
        else:
            return Response({"message": "You are unauthorized to perform this action", }, status=401)
    except:
        return Response({"message": "Error deleting customer order", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def create_purchase_order(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    purchase_order_product_instances_list = request.data.get(
        'purchase_order_product_instances', [])
    purchase_order_product_instances_list = json.loads(
        purchase_order_product_instances_list)
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        # if (staff_profile.company_department.department_name == "sales") and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
        if user_has_permission(staff_profile, "sales_and_marketing.purchase_order_sales.add"):
            purchase_order_serializer = purchaseOrderSerializer(
                data={'company_profile': company_profile.id, 'created_by': staff_profile.id, 'last_updated_by': staff_profile.id})
            if purchase_order_serializer.is_valid():
                new_purchase_order = purchase_order_serializer.save()
                # create purchase instance
                purchase_order_value_overall = 0.00
                purchase_order_landed_costs_overall = 0.00
                for product_instance in purchase_order_product_instances_list:
                    supplier_id = product_instance["supplier_id"]
                    purchase_product_id = product_instance["purchase_product_id"]
                    purchase_value_per_unit = product_instance["purchase_value_per_unit"]
                    cost_currency = product_instance["cost_currency"]
                    exchange_rate = product_instance["exchange_rate"]
                    purchase_value_overall = product_instance["purchase_value_overall"]
                    quantity_purchased = product_instance["quantity_purchased"]
                    product_purchase_instance_serializer = productPurchaseInstanceSerializer(data={'purchase_order': new_purchase_order.id, 'supplier': int(
                        supplier_id), 'purchase_product': int(purchase_product_id), 'purchase_value_per_unit': purchase_value_per_unit, 'cost_currency': cost_currency, 'exchange_rate': exchange_rate, 'purchase_value_overall': purchase_value_overall, 'quantity_purchased': quantity_purchased})
                    if product_purchase_instance_serializer.is_valid():
                        new_product_purchase_instance = product_purchase_instance_serializer.save()
                        purchase_order_value_overall += float(new_product_purchase_instance.purchase_value_overall)*float(
                            new_product_purchase_instance.exchange_rate)
                        # create landed cost instances and attach
                        landed_cost_product_purchase_instances_list = []
                        landed_cost_product_purchase_instances_list = product_instance[
                            "landed_cost_product_purchase_instances_list"]
                        for landed_cost_instance in landed_cost_product_purchase_instances_list:
                            if landed_cost_instance["selected"] == "true":
                                landed_cost_id = landed_cost_instance["landed_cost_id"]
                                cost_value = landed_cost_instance["cost_value"]
                                cost_currency = landed_cost_instance["cost_currency"]
                                exchange_rate = landed_cost_instance["exchange_rate"]
                                cost_amount_paid = landed_cost_instance["cost_amount_paid"]
                                cost_amount_due = landed_cost_instance["cost_amount_due"]
                                # landed cost
                                landed_cost = LandedCost.objects.get(
                                    id=int(landed_cost_id))
                                # existing_landed_cost_instances = LandedCostInstance.objects.filter(
                                #     reference=new_purchase_order.purchase_order_number, landed_cost=landed_cost)

                                # # existing_product_purchase_instances = new_purchase_order.purchase_order_product_instances.all()
                                # # for existing_purchase_instance in existing_product_purchase_instances:
                                # #     existing_landed_cost_instances = existing_purchase_instance.landed_cost_product_purchase_instances.all()
                                # #     #landed_cost_instance_already_exist = False
                                # existing_instance = None
                                # for existing_landed_cost_instance in existing_landed_cost_instances:
                                #     if existing_landed_cost_instance.landed_cost == landed_cost:
                                #         # landed_cost_instance_already_exist = True
                                #         # print("found")
                                #         existing_instance = existing_landed_cost_instance
                                #         break
                                # if existing_instance is not None:
                                #     existing_instance.product_purchase_instance.add(
                                #         new_product_purchase_instance)
                                # else:
                                new_landed_cost_instance = LandedCostInstance.objects.create(landed_cost=landed_cost, product_purchase_instance=new_product_purchase_instance, cost_value=cost_value, cost_currency=cost_currency,
                                                                                             exchange_rate=exchange_rate, cost_amount_paid=cost_amount_paid, cost_amount_due=cost_amount_due, reference=new_purchase_order.purchase_order_number)
                                #     new_landed_cost_instance.product_purchase_instance.add(
                                #         new_product_purchase_instance)
                                purchase_order_landed_costs_overall += float(
                                    cost_value) * float(exchange_rate)
                    else:
                        new_purchase_order.delete()
                        return Response({"message": "Creation of purchase order exited prematurely", }, status=406)
                new_purchase_order.purchase_value_overall = f'{purchase_order_value_overall}'
                new_purchase_order.purchase_order_landed_costs_overall = f'{purchase_order_landed_costs_overall}'
                new_purchase_order.save()
                # notify finance department
                try:
                    list_of_staff_ids = []
                    # get finance department staff
                    finance_dept = CompanyDepartment.objects.get(
                        department_name="finance_and_accounting")
                    all_finance_staff = StaffProfile.objects.filter(
                        company_department=finance_dept)
                    for finance_staff in all_finance_staff:
                        list_of_staff_ids.append(
                            finance_staff.id)
                    notification_title = f"Purchase Order {new_purchase_order.purchase_order_number}"
                    notification_body = f"A new purchase order of number {new_purchase_order.purchase_order_number} has been created. Approval by finance department is required."
                    create_notifications(notification_title,
                                         notification_body, list_of_staff_ids)
                except:
                    pass
                return Response({"message": "Purchase order created successfully", }, status=200)
            else:
                return Response({"message": "Unable to create pruchase order", }, 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 purchase order", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_purchase_order(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    purchase_order_id = request.data["purchase_order_id"]
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        # if (staff_profile.company_department.department_name == "sales") and staff_profile.is_head_of_department == True and staff_profile.has_read_write_priviledges == True and company_profile:
        if user_has_permission(staff_profile, "sales_and_marketing.purchase_order_sales.delete"):
            purchase_order = PurchaseOrder.objects.get(id=purchase_order_id)
            existing_landed_cost_instances = LandedCostInstance.objects.filter(
                reference=purchase_order.purchase_order_number,)
            if purchase_order.recycle_bin != True:
                purchase_order.recycle_bin = True
                purchase_order.save()
                return Response({"message": "Purchase order deleted successfully", }, status=200)
            else:
                purchase_order.delete()
                for landed_cost_instance in existing_landed_cost_instances:
                    landed_cost_instance.delete()
                return Response({"message": "Purchase order permanently deleted successfully", }, status=200)
        else:
            return Response({"message": "You are unauthorised to perform this action", }, status=401)
    except:
        return Response({"message": "Error deleting purchase order", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def upload_customer_documents(request):
    active_user = request.user
    company_serial_number = request.data["serial_number"]
    document_type = request.data["document_type"]
    customer_id = request.data["customer_id"]
    # get folder path
    try:
        folder_path = create_folder_if_not_exists()
        files = request.FILES.getlist('files[]')
        for file in files:
            file_path = os.path.join(folder_path, file.name)
            with open(file_path, 'wb+') as destination:
                for chunk in file.chunks():
                    destination.write(chunk)
                # save the file details in the database
                customer_profile = CustomerProfile.objects.get(
                    id=int(customer_id))
                customer_document = CustomerDocs.objects.create(
                    customer_profile=customer_profile, document_type=document_type, saved_document_path=file_path)
        return Response({"message": "Customer document(s) uploaded successfully", }, status=200)
    except:
        return Response({"message": "Error uploading customer documents", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def get_customer_order_documents(request):
    """List documents (LPO / POP) attached to a customer order — for finance
    review during approval. Download via download-customer-documents/file_path."""
    payload = {}
    document_list = []
    try:
        customer_order_id = request.data["customer_order_id"]
        documents = CustomerOrderDocument.objects.filter(
            customer_order_id=int(customer_order_id)).order_by("-id")
        for document in documents:
            document_list.append({
                "document_id": str(document.id),
                "document_type": document.document_type,
                "original_name": document.original_name,
                "file_path": document.saved_document_path,
                "uploaded_via": document.uploaded_via,
                "created_on": document.created_on.isoformat() if document.created_on else "",
            })
        payload["order_documents"] = document_list
        return Response({"message": "true", "payload": payload}, status=200)
    except Exception as e:
        print(e)
        payload["order_documents"] = document_list
        return Response({"message": "false", "payload": payload}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def download_customer_documents(request):
    file_path = request.data["file_path"]
    if os.path.exists(file_path):
        return FileResponse(open(file_path, 'rb'), as_attachment=True)
    else:
        raise Http404("File not found")


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def delete_customer_documents(request):
    customer_id = request.data["customer_id"]
    document_type = request.data["document_type"]
    try:
        # customer_doc_instance = CustomerDocs.objects.get(
        #     saved_document_path=file_path)
        customer_profile = CustomerProfile.objects.get(id=int(customer_id))
        all_customer_docs = CustomerDocs.objects.all().filter(
            customer_profile=customer_profile, document_type=document_type)
        for doc in all_customer_docs:
            file_path = doc.saved_document_path
            if os.path.exists(file_path):
                os.remove(file_path)
                doc.delete()
        return Response({"message": "Document deleted successfully", }, status=200)
    except:
        return Response({"message": "Unable to delete document.", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def sales_get_single_customer_profile(request):
    customer_profile_map = {}
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    shopping_history = []
    try:
        customer_id = request.data["customer_id"]
        # print(customer_id)
        customer_profile = CustomerProfile.objects.get(id=int(customer_id))
        customer_profile_map["customer_profile_id"] = str(
            customer_profile.id)
        customer_profile_map["customer_first_name"] = customer_profile.customer_first_name
        customer_profile_map["customer_last_name"] = customer_profile.customer_last_name
        customer_profile_map["email_address"] = customer_profile.email_address
        customer_profile_map["phone_number"] = customer_profile.phone_number
        customer_profile_map["customer_title"] = customer_profile.customer_title
        customer_profile_map["company_name"] = customer_profile.company_name
        customer_profile_map["customer_type"] = customer_profile.customer_type
        # customer_profile_map["kra_pin"] = customer_profile.kra_pin
        # customer_profile_map["kra_pin_certificate_path"] = kra_pin_certificate_path
        customer_profile_map["certificate_of_registration_number"] = customer_profile.certificate_of_registration_number
        # customer_profile_map["certificate_of_registration_path"] = certificate_of_registration_path
        # customer_profile_map["is_profile_set"] = "true" if customer_profile.is_profile_set == True else "false"
        customer_profile_map["created_on"] = datetime.strftime(
            customer_profile.created_on.astimezone(target_timezone), date_format) if customer_profile.created_on is not None else ""
        customer_profile_map["last_updated_on"] = datetime.strftime(
            customer_profile.last_updated_on.astimezone(target_timezone), date_format) if customer_profile.last_updated_on is not None else ""
        customer_order_history = customer_profile.customer_order_history.filter(
            recycle_bin=False).order_by("-id")
        for customer_order in customer_order_history:
            customer_order_items = customer_order.customer_order_items.all()
            for order_item in customer_order_items:
                order_item_map = {}
                order_item_map["customer_order_number"] = customer_order.customer_order_number
                order_item_map["product_name"] = order_item.product.product_name
                order_item_map["quantity"] = order_item.quantity
                order_item_map["price_per_item"] = order_item.price_per_item
                order_item_map["discount_per_item"] = order_item.discount_per_item
                order_item_map["net_subtotal"] = order_item.net_subtotal
                order_item_map["created_on"] = datetime.strftime(
                    customer_order.created_on.astimezone(target_timezone), date_format) if customer_order.created_on is not None else ""
                shopping_history.append(order_item_map)
        customer_profile_map["shopping_history"] = shopping_history
        customer_profile_map["customer_shipping_address_list"] = []
        return Response({"customer_profile_map": customer_profile_map, }, status=200)
    except Exception as e:
        print(e)
        return Response({"message": "Error retrieving customer profile", }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def sales_get_single_quotation(request):
    customer_profile_map = {}
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    sale_quotation_map = {}
    company_profile_map = {}
    main_warehouse_map = {}
    payload = {}
    try:
        staff_profile = StaffProfile.objects.get(user=request.user)
        branch = staff_profile.company_branch
        #
        company_profile = branch.company_profile
        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
        #
        main_branch = CompanyBranch.objects.filter(
            main_branch=True, recycle_bin=False).first()
        main_warehouse = main_branch.branch_warehouses.filter(
            recycle_bin=False).first()
        main_warehouse_map["warehouse_id"] = str(main_warehouse.id)
        main_warehouse_map["warehouse_company_branch_id"] = str(
            main_warehouse.company_branch.id)
        main_warehouse_map["warehouse_company_branch_name"] = main_warehouse.company_branch.branch_name
        main_warehouse_map["warehouse_name"] = main_warehouse.warehouse_name
        main_warehouse_map["warehouse_location"] = main_warehouse.warehouse_location
        main_warehouse_map["warehouse_capacity"] = main_warehouse.warehouse_capacity
        main_warehouse_map["warehouse_contact_phone"] = main_warehouse.warehouse_contact_phone
        main_warehouse_map["warehouse_description"] = main_warehouse.warehouse_description
        #
        company_profile_map["main_warehouse"] = main_warehouse_map
        preferred_currency = branch.company_profile.company_preferred_currency
        sale_quotation_id = int(request.data["sale_quotation_id"])
        sale_quotation = SalesQuotation.objects.get(
            id=sale_quotation_id)
        sales_quotation_map = {}
        sales_quotation_items_list = []
        sales_quotation_map["sale_quotation_id"] = str(
            sale_quotation.id)
        sales_quotation_map["sales_quotation_number"] = sale_quotation.sales_quotation_number
        sales_quotation_map["quotation_net_value"] = sale_quotation.quotation_net_value
        sales_quotation_map["sales_quotation_approved"] = "true" if sale_quotation.sales_quotation_approved == True else "false"
        creator_map = {}
        creator_map["staff_id"] = str(
            sale_quotation.created_by.id) if sale_quotation.created_by is not None else ""
        creator_map["staff_name"] = f'{sale_quotation.created_by.first_name} {sale_quotation.created_by.last_name}' if sale_quotation.created_by is not None else ""
        creator_map["staff_position"] = sale_quotation.created_by.staff_position.position_title if sale_quotation.created_by is not None else ""
        sales_quotation_map["created_by"] = creator_map
        creator_map = {}
        creator_map["staff_id"] = str(
            sale_quotation.last_updated_by.id) if sale_quotation.last_updated_by is not None else ""
        creator_map["staff_name"] = f'{sale_quotation.last_updated_by.first_name} {sale_quotation.last_updated_by.last_name}' if sale_quotation.last_updated_by is not None else ""
        creator_map["staff_position"] = sale_quotation.last_updated_by.staff_position.position_title if sale_quotation.last_updated_by is not None else ""
        sales_quotation_map["last_updated_by"] = creator_map
        sales_quotation_map["created_on"] = datetime.strftime(
            sale_quotation.created_on.astimezone(target_timezone), date_format) if sale_quotation.created_on is not None else ""
        sales_quotation_map["last_updated_on"] = datetime.strftime(
            sale_quotation.last_updated_on.astimezone(target_timezone), date_format) if sale_quotation.last_updated_on is not None else ""
        # quotation_price_change_request_active
        sales_quotation_map["quotation_price_change_request_active"] = "true" if sale_quotation.quotation_price_change_request_active == True else "false"
        # attach customer
        customer_profile = sale_quotation.customer_profile
        customer_profile_map = {}
        customer_profile_map["customer_profile_id"] = str(
            customer_profile.id) if customer_profile is not None else ""
        customer_profile_map["customer_first_name"] = customer_profile.customer_first_name if customer_profile is not None else ""
        customer_profile_map["customer_last_name"] = customer_profile.customer_last_name if customer_profile is not None else ""
        customer_profile_map["email_address"] = customer_profile.email_address if customer_profile is not None else ""
        customer_profile_map["phone_number"] = customer_profile.phone_number if customer_profile is not None else ""
        customer_profile_map["customer_title"] = customer_profile.customer_title if customer_profile is not None else ""
        customer_profile_map["company_name"] = customer_profile.company_name if customer_profile is not None else ""
        customer_profile_map["customer_type"] = customer_profile.customer_type if customer_profile is not None else ""
        customer_profile_map["kra_pin"] = customer_profile.kra_pin if customer_profile is not None else ""
        customer_profile_map["certificate_of_registration_number"] = customer_profile.certificate_of_registration_number if customer_profile is not None else ""
        sales_quotation_map["customer"] = customer_profile_map
        customer_profile_map = {}
        # end
        sales_quotation_items = sale_quotation.sales_quotation_items.all().order_by("-id")
        for sale_quotation_item in sales_quotation_items:
            sales_quotation_item_map = {}
            sales_quotation_item_map["sale_quotation_item_id"] = str(
                sale_quotation_item.id)
            sales_quotation_item_map["product_id"] = str(
                sale_quotation_item.product.id) if sale_quotation_item.product is not None else ""
            sales_quotation_item_map["product_name"] = str(
                sale_quotation_item.product.product_name) if sale_quotation_item.product is not None else ""
            sales_quotation_item_map["quantity"] = sale_quotation_item.quantity
            sales_quotation_item_map["price_per_item"] = sale_quotation_item.price_per_item
            sales_quotation_item_map["discount_per_item"] = sale_quotation_item.discount_per_item
            sales_quotation_item_map["gross_subtotal"] = sale_quotation_item.gross_subtotal
            sales_quotation_item_map["total_discount"] = sale_quotation_item.total_discount
            sales_quotation_item_map["vat_per_item"] = f"{(float(sale_quotation_item.product.product_vat.vat_percentage_value)/100)*float(sale_quotation_item.price_per_item)}"
            sales_quotation_item_map["net_subtotal"] = sale_quotation_item.net_subtotal
            sales_quotation_item_map["request_price_change"] = "true" if sale_quotation_item.request_price_change == True else "false"
            sales_quotation_item_map["requested_new_price_after_discount"] = sale_quotation_item.requested_new_price_after_discount
            sales_quotation_item_map["requested_price_change_approved"] = "true" if sale_quotation_item.requested_price_change_approved == True else "false"

            # adding product maps
            product_pricing_map = {}
            product_discount_map = {}
            product_vat_map = {}
            product = sale_quotation_item.product
            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
                product_pricing_map["product_net_price_technician"] = product_pricing.product_net_price_technician
                product_pricing_map["product_net_price_reseller"] = product_pricing.product_net_price_reseller
                product_pricing_map["product_net_price_financier"] = product_pricing.product_net_price_financier
                product_pricing_map["product_net_price_engineering_procurement_contractor"] = product_pricing.product_net_price_engineering_procurement_contractor
            except:
                product_pricing_map["product_pricing_id"] = ""
                product_pricing_map["product_net_price"] = ""
                product_pricing_map["product_net_price_technician"] = ""
                product_pricing_map["product_net_price_reseller"] = ""
                product_pricing_map["product_net_price_financier"] = ""
                product_pricing_map["product_net_price_engineering_procurement_contractor"] = ""
            sales_quotation_item_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"] = ""
            sales_quotation_item_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"] = ""
            sales_quotation_item_map["product_vat_map"] = product_vat_map
            #
            sales_quotation_items_list.append(
                sales_quotation_item_map)
        sales_quotation_map["sales_quotation_items_list"] = sales_quotation_items_list
        sales_quotation_map["preferred_currency"] = preferred_currency
        all_chart_of_accounts = branch.branch_chart_of_accounts.filter(
            recycle_bin=False).order_by("-id")
        chart_of_account_list = []
        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
                chart_of_account_list.append(chart_of_account_map)
        payload["chart_of_account_list"] = chart_of_account_list
        payload["sale_quotation"] = sales_quotation_map
        payload["company_profile"] = company_profile_map
        return Response({"message": "true", "payload": payload}, status=200)
    except:
        return Response({"message": "false", "payload": payload}, status=500)


@api_view(['GET'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def sales_get_category_list_to_edit_items(request):
    customer_profile_map = {}
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    category_map = {}
    category_list = []
    try:
        all_categories = Category.objects.filter(
            recycle_bin=False).order_by("-id")
        for category in all_categories:
            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
                        product_pricing_map["product_net_price_technician"] = product_pricing.product_net_price_technician
                        product_pricing_map["product_net_price_reseller"] = product_pricing.product_net_price_reseller
                        product_pricing_map["product_net_price_financier"] = product_pricing.product_net_price_financier
                        product_pricing_map["product_net_price_engineering_procurement_contractor"] = product_pricing.product_net_price_engineering_procurement_contractor
                    except:
                        product_pricing_map["product_pricing_id"] = ""
                        product_pricing_map["product_net_price"] = ""
                        product_pricing_map["product_net_price_technician"] = ""
                        product_pricing_map["product_net_price_reseller"] = ""
                        product_pricing_map["product_net_price_financier"] = ""
                        product_pricing_map["product_net_price_engineering_procurement_contractor"] = ""
                    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)
        return Response({"category_list": category_list}, status=200)
    except:
        return Response({"category_list": category_list}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def get_sale_quotation_creation_items(request):
    customer_profile_map = {}
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    category_map = {}
    category_list = []
    customer_profile_map = {}
    customer_profiles_list = []
    try:
        company_serial_number = request.data["company_serial_number"]
        all_categories = Category.objects.filter(
            recycle_bin=False).order_by("-id")
        active_user = request.user
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        preferred_currency = company_profile.company_preferred_currency
        all_customer_profiles = []
        if user_has_permission(staff_profile, "sales_and_marketing.quotation.view"):
            all_customer_profiles = company_profile.company_customers.filter(
                recycle_bin=False).order_by(
                "-id")
        else:
            all_customer_profiles = list(
                company_profile.company_customers.filter(recycle_bin=False).order_by("-id")
            )
        for customer in all_customer_profiles:
            customer_profile_map = {}
            customer_profile_map["customer_profile_id"] = str(
                customer.id)
            customer_profile_map["customer_type"] = str(
                customer.customer_type)
            customer_profile_map["customer_first_name"] = customer.customer_first_name
            customer_profile_map["customer_last_name"] = customer.customer_last_name
            customer_profile_map["email_address"] = customer.email_address
            customer_profile_map["phone_number"] = customer.phone_number
            customer_profile_map["customer_title"] = customer.customer_title
            customer_profile_map["company_name"] = customer.company_name
            customer_profiles_list.append(customer_profile_map)
        for category in all_categories:
            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
                        product_pricing_map["product_net_price_technician"] = product_pricing.product_net_price_technician
                        product_pricing_map["product_net_price_reseller"] = product_pricing.product_net_price_reseller
                        product_pricing_map["product_net_price_financier"] = product_pricing.product_net_price_financier
                        product_pricing_map["product_net_price_engineering_procurement_contractor"] = product_pricing.product_net_price_engineering_procurement_contractor
                    except:
                        product_pricing_map["product_pricing_id"] = ""
                        product_pricing_map["product_net_price"] = ""
                        product_pricing_map["product_net_price_technician"] = ""
                        product_pricing_map["product_net_price_reseller"] = ""
                        product_pricing_map["product_net_price_financier"] = ""
                        product_pricing_map["product_net_price_engineering_procurement_contractor"] = ""
                    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
                    if staff_profile.company_branch is not None:
                        attach_branch_stock_fields(
                            product_map, product, staff_profile.company_branch,
                        )
                    product_list.append(product_map)
            category_map["product_list"] = product_list
            category_list.append(category_map)

        return Response({"preferred_currency": preferred_currency, "category_list": category_list, "customer_profiles_list": customer_profiles_list}, status=200)
    except Exception as e:
        print(e)
        return Response({"category_list": category_list, "customer_profiles_list": customer_profiles_list}, status=500)


@api_view(['GET'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def get_supplier_creation_items(request):
    customer_profile_map = {}
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    category_map = {}
    category_list = []
    try:
        all_categories = Category.objects.filter(
            recycle_bin=False).order_by("-id")
        for category in all_categories:
            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_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_list.append(product_map)
            category_map["product_list"] = product_list
            category_list.append(category_map)
        return Response({"category_list": category_list, }, status=200)
    except Exception as e:
        print(e)
        return Response({"category_list": category_list, }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def get_supplier_to_edit(request):
    customer_profile_map = {}
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    category_map = {}
    category_list = []
    supplier_map = {}
    try:
        all_categories = Category.objects.filter(
            recycle_bin=False).order_by("-id")
        for category in all_categories:
            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_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_list.append(product_map)
            category_map["product_list"] = product_list
            category_list.append(category_map)
        supplier_id = request.data["supplier_id"]
        company_serial_number = request.data["serial_number"]
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        supplier = Supplier.objects.get(id=int(supplier_id))
        # 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
        return Response({"supplier_map": supplier_map, "category_list": category_list, }, status=200)
    except Exception as e:
        print(e)
        return Response({"supplier_map": supplier_map, "category_list": category_list, }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def get_single_customer_order(request):
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    company_serial_number = request.data["company_serial_number"]
    active_user = request.user
    # payload = {}
    creator_map = {}
    customer_order_map = {}
    customer_order_item_map = {}
    customer_order_items_list = []
    sales_order_map = {}
    # sales_orders_list = []
    sales_order_item_map = {}
    sales_order_items_list = []
    warehouse_map = {}
    warehouse_list = []
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        all_warehouses = Warehouse.objects.filter(recycle_bin=False)
        for warehouse in all_warehouses:
            warehouse_map = {}
            warehouse_map["warehouse_id"] = str(warehouse.id)
            warehouse_map["warehouse_name"] = warehouse.warehouse_name
            warehouse_map["warehouse_location"] = warehouse.warehouse_location
            warehouse_list.append(warehouse_map)
        customer_order_id = request.data["customer_order_id"]
        customer_order = CustomerOrder.objects.get(id=int(customer_order_id))
        customer_order_items_list = []
        order_items_return_list = []
        customer_order_payments_list = []
        customer_order_map["customer_profile_id"] = str(
            customer_order.customer_profile.id) if customer_order.customer_profile is not None else ""
        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"] = datetime.strftime(
            customer_order.expected_delivery_date, '%d/%m/%Y') 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["product_id"] = str(
                    sales_order_item.product.id) if sales_order_item.product is not None else ""
                sales_order_item_map["product_name"] = sales_order_item.product.product_name if sales_order_item.product 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
            # print(customer_order_map["sales_order_map"])
            # print("running")
        except Exception as e:
            # print(e)
            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
        # 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
                customer_order_payment_map["currency"] = order_payment.account_paid_to.account_currency
                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
        return Response({"customer_order_map": customer_order_map, "warehouse_list": warehouse_list, }, status=200)
    except Exception as e:
        print(e)
        return Response({"customer_order_map": customer_order_map, "warehouse_list": warehouse_list, }, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def get_customer_list_to_send_mail(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 = {}
    creator_map = {}
    customer_profile_map = {}
    customer_profiles_list = []
    try:
        staff_profile = StaffProfile.objects.get(user=active_user)
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        # if staff_profile.company_department.department_name == "sales" and company_profile:
        all_customer_profiles = []
        if user_has_permission(staff_profile, "sales_and_marketing.customer.view"):
            all_customer_profiles = company_profile.company_customers.filter(
                recycle_bin=False).order_by(
                "-id")
        else:
            all_customer_profiles = list(
                company_profile.company_customers.filter(recycle_bin=False).order_by("-id")
            )
        for customer_profile in all_customer_profiles:
            customer_profile_map = {}
            customer_profile_map["customer_profile_id"] = str(
                customer_profile.id)
            customer_profile_map["customer_first_name"] = customer_profile.customer_first_name
            customer_profile_map["customer_last_name"] = customer_profile.customer_last_name
            customer_profile_map["email_address"] = customer_profile.email_address
            customer_profile_map["phone_number"] = customer_profile.phone_number
            customer_profile_map["customer_title"] = customer_profile.customer_title
            customer_profile_map["company_name"] = customer_profile.company_name
            customer_profile_map["customer_type"] = customer_profile.customer_type
            _attach_empty_account_manager(customer_profile_map)
            customer_profiles_list.append(customer_profile_map)
        # payload["customer_profiles_list"] = customer_profiles_list
        return Response({"message": "true", "customer_profiles_list": customer_profiles_list}, status=200)
    except:
        return Response({"message": "false", "payload": payload}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def get_customer_list_based_on_type(request):
    customer_profiles_list = []
    staff_profile = StaffProfile.objects.get(user=request.user)
    #print(staff_profile.first_name)
    try:
        customer_type = request.data["customer_type"]
        all_customer_type = []
        if user_has_permission(staff_profile, "sales_and_marketing.customer.view"):
            all_customer_type = CustomerProfile.objects.filter(
                recycle_bin=False, customer_type=customer_type)
        else:
            company_profile = CompanyProfile.objects.order_by("id").first()
            if company_profile is not None:
                all_customer_type = list(
                    company_profile.company_customers.filter(
                        recycle_bin=False, customer_type=customer_type
                    ).order_by("-id")
                )
        # filter based on user
        for customer_profile in all_customer_type:
            customer_profile_map = {}
            customer_profile_map["customer_profile_id"] = str(
                customer_profile.id)
            customer_profile_map["customer_first_name"] = customer_profile.customer_first_name
            customer_profile_map["customer_last_name"] = customer_profile.customer_last_name
            customer_profile_map["email_address"] = customer_profile.email_address
            customer_profile_map["phone_number"] = customer_profile.phone_number
            customer_profile_map["customer_title"] = customer_profile.customer_title
            customer_profile_map["company_name"] = customer_profile.company_name
            customer_profile_map["customer_type"] = customer_profile.customer_type
            customer_profile_map["kra_pin"] = customer_profile.kra_pin
            customer_profile_map["certificate_of_registration_number"] = customer_profile.certificate_of_registration_number
            customer_profile_map["total_purchase_value"] = get_customer_overall_purchase_value(customer_profile)
            _attach_empty_account_manager(customer_profile_map)
            customer_profiles_list.append(customer_profile_map)
        # print(customer_profiles_list)
        return Response({"customer_profiles_list": customer_profiles_list}, status=200)
    except:
        return Response({"customer_profiles_list": customer_profiles_list}, status=500)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def agent_orders(request):
    target_timezone = pytz.timezone('Africa/Nairobi')
    date_format = '%d/%m/%Y, %H:%M'
    company_serial_number = request.data["serial_number"]
    page_index = request.data.get("pageIndex", "1")
    active_user = request.user
    payload = {}
    creator_map = {}
    customer_order_map = {}
    customer_orders_list = []
    customer_order_item_map = {}
    customer_order_items_list = []
    sales_order_map = {}
    # sales_orders_list = []
    sales_order_item_map = {}
    sales_order_items_list = []
    start_index = 0
    last_index = 0
    try:
        if page_index == "1":
            start_index = 0
            last_index = 20
        elif page_index == "2":
            start_index = 20
            last_index = 40
        elif page_index == "3":
            start_index = 40
            last_index = 60
        elif page_index == "4":
            start_index = 60
            last_index = 80
        else:
            start_index = 80
            last_index = 0
        staff_profile = StaffProfile.objects.get(user=active_user)
        department_name = staff_profile.company_department.department_name if staff_profile.company_department else ""
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_branch = staff_profile.company_branch
        if user_has_permission(staff_profile, "sales_and_marketing.agent_orders.view"):
            if staff_profile.is_head_of_department == True and (department_name == "sales"):
                agent_orders_qs = CustomerOrder.objects.filter(
                    recycle_bin=False, agent_profile__isnull=False).order_by("-id")
            elif staff_branch is not None:
                agent_orders_qs = staff_branch.branch_customer_orders.filter(
                    recycle_bin=False, created_by=staff_profile, agent_profile__isnull=False).order_by("-id")
            else:
                agent_orders_qs = CustomerOrder.objects.filter(
                    recycle_bin=False, created_by=staff_profile, agent_profile__isnull=False).order_by("-id")
            branch_customer_orders = agent_orders_qs[start_index:last_index] if last_index != 0 else agent_orders_qs[start_index:]
            for customer_order in branch_customer_orders:
                customer_order_map = {}
                customer_order_items_list = []
                order_items_return_list = []
                customer_order_payments_list = []
                customer_order_map["customer_profile_id"] = str(
                    customer_order.customer_profile.id) if customer_order.customer_profile is not None else ""
                customer_order_map["customer_order_id"] = str(
                    customer_order.id)
                customer_order_map["customer_order_number"] = customer_order.customer_order_number
                customer_order_map["origin"] = customer_order.origin
                customer_order_map["source_quotation_number"] = (
                    customer_order.source_quotation.sales_quotation_number
                    if customer_order.source_quotation_id else ""
                )
                customer_order_map["crm_quote_ref"] = (
                    customer_order.customer_order_description
                    if customer_order.origin == "crm" else ""
                )
                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"] = datetime.strftime(
                    customer_order.expected_delivery_date, '%d/%m/%Y') 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 is not None and 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 and 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 is not None and customer_order.last_updated_by.staff_position is not None) else ""
                customer_order_map["last_updated_by"] = creator_map
                agent_map = {}
                ##
                agent_map["agent_profile_id"] = str(
                    customer_order.agent_profile.id) if customer_order.agent_profile is not None else ""
                agent_map["agent_name"] = f"{customer_order.agent_profile.first_name} {customer_order.agent_profile.last_name}" if customer_order.agent_profile is not None else ""
                agent_map["email_address"] = customer_order.agent_profile.email_address if customer_order.agent_profile is not None else ""
                agent_map["phone_number"] = customer_order.agent_profile.phone_number if customer_order.agent_profile is not None else ""
                customer_order_map["agent_map"] = agent_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) if customer_order_item.product is not None else ""
                    customer_order_item_map["product_name"] = customer_order_item.product.product_name if customer_order_item.product is not None else ""
                    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 is not None and 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 is not None and 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["product_id"] = str(
                            sales_order_item.product.id) if sales_order_item.product is not None else ""
                        sales_order_item_map["product_name"] = sales_order_item.product.product_name if sales_order_item.product 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
                    # print(customer_order_map["sales_order_map"])
                    # print("running")
                except Exception as e:
                    # print(e)
                    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
                # 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
                        customer_order_payment_map["currency"] = order_payment.account_paid_to.account_currency
                        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)
            payload["customer_orders_list"] = customer_orders_list
            return Response({"message": "true", "payload": payload}, status=200)
        else:
            return Response({"message": "false", "payload": payload}, status=401)
    except:
        return Response({"message": "false", "payload": payload}, status=500)


def get_customer_overall_purchase_value(customer_profile):
    total_purchase_value = 0.0
    all_customer_orders = CustomerOrder.objects.filter(recycle_bin=False,customer_profile=customer_profile,customer_order_approved=True)
    for order in all_customer_orders:
        total_purchase_value += float(order.customer_order_total_net_value)
    return f"{total_purchase_value}"


# ─── STAFF PERFORMANCE ────────────────────────────────────────────────────────

from datetime import datetime as _dt
from django.db.models import Sum, Count


def _parse_month_range(month_str):
    """Return (start_date, end_date) for a YYYY-MM string."""
    try:
        start = _dt.strptime(month_str, "%Y-%m").replace(day=1)
        import calendar
        last_day = calendar.monthrange(start.year, start.month)[1]
        end = start.replace(day=last_day, hour=23, minute=59, second=59)
        from django.utils import timezone
        return timezone.make_aware(start), timezone.make_aware(end)
    except Exception:
        from django.utils import timezone
        now = timezone.now()
        import calendar
        last_day = calendar.monthrange(now.year, now.month)[1]
        start = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
        end = now.replace(day=last_day, hour=23, minute=59, second=59, microsecond=0)
        return start, end


def _parse_date_range(request_data):
    """
    Resolve (start, end, period_label) from request data.
    Accepts:
      - date_from + date_to  (YYYY-MM-DD custom range)
      - month                (YYYY-MM)
      - falls back to current month
    Returns (start_aware, end_aware, period_label, month_str_or_none)
    """
    from django.utils import timezone as _tz
    date_from = request_data.get("date_from", "").strip()
    date_to = request_data.get("date_to", "").strip()
    month_str = request_data.get("month", "").strip()

    if date_from and date_to:
        try:
            start = _tz.make_aware(_dt.strptime(date_from, "%Y-%m-%d").replace(hour=0, minute=0, second=0))
            end   = _tz.make_aware(_dt.strptime(date_to,   "%Y-%m-%d").replace(hour=23, minute=59, second=59))
            label = f"{date_from} to {date_to}"
            return start, end, label, None
        except Exception:
            pass

    if not month_str:
        now = _tz.now().astimezone(pytz.timezone('Africa/Nairobi'))
        month_str = now.strftime("%Y-%m")

    start, end = _parse_month_range(month_str)
    label = _dt.strptime(month_str, "%Y-%m").strftime("%B %Y")
    return start, end, label, month_str


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def staff_performance_dashboard(request):
    """
    My personal performance for a date range (default: current month).
    Body: { serial_number, month? (YYYY-MM), date_from? (YYYY-MM-DD), date_to? (YYYY-MM-DD) }
    """
    serial_number = request.data.get("serial_number", "")
    active_user = request.user

    try:
        from system_administration.models import CompanyProfile
        CompanyProfile.objects.get(company_serial_number=serial_number)
        staff_profile = StaffProfile.objects.get(user=active_user)
    except Exception as e:
        return Response({"message": "false", "error": str(e)}, status=400)

    start, end, period_label, month_str = _parse_date_range(request.data)

    # Previous period (same duration, shifted back)
    duration = end - start
    prev_end = start - __import__('datetime').timedelta(seconds=1)
    prev_start = prev_end - duration

    # Querysets for this staff
    my_orders_qs = staff_profile.customer_offline_order_created_by.filter(
        recycle_bin=False, agent_profile=None)
    my_quotes_qs = staff_profile.sales_quotation_created_by.filter(recycle_bin=False)

    # Current month orders
    curr_orders = my_orders_qs.filter(created_on__gte=start, created_on__lte=end)
    curr_quotes = my_quotes_qs.filter(created_on__gte=start, created_on__lte=end)

    # Previous month orders
    prev_orders = my_orders_qs.filter(created_on__gte=prev_start, created_on__lte=prev_end)

    def sum_order_value(qs):
        total = 0.0
        for o in qs.values_list("customer_order_total_net_value", flat=True):
            try:
                total += float(o or 0)
            except (TypeError, ValueError):
                pass
        return round(total, 2)

    curr_sales_value = sum_order_value(curr_orders)
    prev_sales_value = sum_order_value(prev_orders)
    deviation = round(curr_sales_value - prev_sales_value, 2)
    deviation_pct = None
    if prev_sales_value > 0:
        deviation_pct = round((deviation / prev_sales_value) * 100, 1)
    elif curr_sales_value > 0:
        deviation_pct = 100.0

    order_count = curr_orders.count()
    quote_count = curr_quotes.count()

    # Unpaid orders
    unpaid_count = 0
    for order in curr_orders.select_related("customer_profile"):
        try:
            paid = float(order.customer_order_total_amount_paid or 0)
            value = float(order.customer_order_total_net_value or 0)
            if paid < value:
                unpaid_count += 1
        except (TypeError, ValueError):
            pass

    # Top customers by order count this month
    customer_order_counts = {}
    for order in curr_orders.select_related("customer_profile"):
        if order.customer_profile:
            name = f"{order.customer_profile.customer_first_name} {order.customer_profile.customer_last_name}".strip()
            company = order.customer_profile.company_name or ""
            key = name
            if key not in customer_order_counts:
                customer_order_counts[key] = {"name": name, "company": company, "order_count": 0, "total_value": 0.0}
            customer_order_counts[key]["order_count"] += 1
            try:
                customer_order_counts[key]["total_value"] += float(order.customer_order_total_net_value or 0)
            except (TypeError, ValueError):
                pass

    top_customers = sorted(customer_order_counts.values(), key=lambda x: x["total_value"], reverse=True)[:5]
    for c in top_customers:
        c["total_value"] = round(c["total_value"], 2)

    # Top products by quantity sold this month
    from .models import CustomerOrderItem
    product_sales = {}
    order_items = CustomerOrderItem.objects.filter(
        customer_order__in=curr_orders
    ).select_related("product")
    for item in order_items:
        name = item.product.product_name if item.product else "Unknown"
        if name not in product_sales:
            product_sales[name] = {"product": name, "qty": 0.0, "revenue": 0.0}
        try:
            product_sales[name]["qty"] += float(item.quantity or 0)
            product_sales[name]["revenue"] += float(item.net_subtotal or 0)
        except (TypeError, ValueError):
            pass

    top_products = sorted(product_sales.values(), key=lambda x: x["revenue"], reverse=True)[:5]
    for p in top_products:
        p["qty"] = round(p["qty"], 2)
        p["revenue"] = round(p["revenue"], 2)

    # 6-month trend
    _tz_nairobi = pytz.timezone('Africa/Nairobi')
    monthly_trend = []
    for i in range(5, -1, -1):
        from django.utils.timezone import now as _now
        import calendar
        ref = _now().astimezone(_tz_nairobi)
        m = (ref.month - i - 1) % 12 + 1
        y = ref.year + ((ref.month - i - 1) // 12)
        ms, me = _parse_month_range(f"{y}-{m:02d}")
        mo_orders = my_orders_qs.filter(created_on__gte=ms, created_on__lte=me)
        mo_value = sum_order_value(mo_orders)
        monthly_trend.append({
            "month": f"{y}-{m:02d}",
            "label": _dt(y, m, 1).strftime("%b %Y"),
            "orders": mo_orders.count(),
            "value": mo_value,
        })

    # Closed vs open
    closed_orders = curr_orders.filter(
        Q(customer_ordered_delivered_to_destination=True) | Q(customer_order_picked_by_customer=True)
    )
    open_orders = curr_orders.exclude(
        Q(customer_ordered_delivered_to_destination=True) | Q(customer_order_picked_by_customer=True) |
        Q(customer_order_cancelled_by_customer=True) | Q(customer_order_cancelled_by_sales_team=True)
    )

    payload = {
        "month": month_str or "",
        "period_label": period_label,
        "staff_name": f"{staff_profile.first_name} {staff_profile.last_name}".strip(),
        "curr_sales_value": curr_sales_value,
        "prev_sales_value": prev_sales_value,
        "deviation": deviation,
        "deviation_pct": deviation_pct,
        "order_count": order_count,
        "quote_count": quote_count,
        "unpaid_count": unpaid_count,
        "closed_count": closed_orders.count(),
        "open_count": open_orders.count(),
        "top_customers": top_customers,
        "top_products": top_products,
        "monthly_trend": monthly_trend,
    }
    return Response({"message": "true", "payload": payload}, status=200)


@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def management_performance_dashboard(request):
    """
    Team-wide performance for the HOD.
    Body: { serial_number, month? (YYYY-MM), date_from? (YYYY-MM-DD), date_to? (YYYY-MM-DD) }
    """
    serial_number = request.data.get("serial_number", "")
    active_user = request.user

    try:
        from system_administration.models import CompanyProfile
        company_profile = CompanyProfile.objects.get(company_serial_number=serial_number)
        staff_profile = StaffProfile.objects.get(user=active_user)
    except Exception as e:
        return Response({"message": "false", "error": str(e)}, status=400)

    if not user_has_permission(staff_profile, "sales_and_marketing.performance_dashboard.view"):
        return Response({"message": "false", "error": "Access denied."}, status=403)

    start, end, period_label, month_str = _parse_date_range(request.data)

    def sum_order_value(qs):
        total = 0.0
        for v in qs.values_list("customer_order_total_net_value", flat=True):
            try:
                total += float(v or 0)
            except (TypeError, ValueError):
                pass
        return round(total, 2)

    # All sales staff in the company (same department or all staff)
    all_staff = StaffProfile.objects.filter(
        company_department__company_profile=company_profile,
        company_department__department_name="sales",
    ).select_related("user")

    staff_table = []
    red_flags = []
    team_total_sales = 0.0
    team_total_orders = 0
    team_total_unpaid = 0

    for sp in all_staff:
        orders_qs = sp.customer_offline_order_created_by.filter(
            recycle_bin=False, agent_profile=None,
            created_on__gte=start, created_on__lte=end
        )
        quotes_qs = sp.sales_quotation_created_by.filter(
            recycle_bin=False,
            created_on__gte=start, created_on__lte=end
        )
        total_sales = sum_order_value(orders_qs)
        order_count = orders_qs.count()
        quote_count = quotes_qs.count()

        unpaid_value = 0.0
        unpaid_count = 0
        total_paid = 0.0
        for net_val, amt_paid in orders_qs.values_list("customer_order_total_net_value", "customer_order_total_amount_paid"):
            try:
                val = float(str(net_val or '0').replace(',', '').strip() or 0)
                paid = float(str(amt_paid or '0').replace(',', '').strip() or 0)
                total_paid += paid
                if val > 0 and paid < val:
                    unpaid_count += 1
                    unpaid_value += (val - paid)
            except (TypeError, ValueError):
                pass

        avg_order = round(total_sales / order_count, 2) if order_count else 0.0
        # Collection rate: if no amount_paid data, derive from closed orders
        if total_sales > 0 and total_paid > 0:
            collection_rate = round(min(100.0, (total_paid / total_sales) * 100), 1)
        elif total_sales > 0:
            closed = orders_qs.filter(
                Q(customer_ordered_delivered_to_destination=True) | Q(customer_order_picked_by_customer=True)
            ).count()
            collection_rate = round(min(100.0, (closed / order_count) * 100), 1) if order_count else 0.0
        else:
            collection_rate = 0.0

        team_total_sales += total_sales
        team_total_orders += order_count
        team_total_unpaid += unpaid_count

        name = f"{sp.first_name} {sp.last_name}".strip() or sp.user.username
        staff_table.append({
            "staff_id": str(sp.id),
            "name": name,
            "total_sales": total_sales,
            "order_count": order_count,
            "quote_count": quote_count,
            "avg_order_value": avg_order,
            "collection_rate": collection_rate,
            "unpaid_count": unpaid_count,
            "unpaid_value": round(unpaid_value, 2),
        })

        if unpaid_count > 3:
            red_flags.append({
                "name": name,
                "type": "high_unpaid",
                "detail": f"{unpaid_count} unpaid orders (KES {round(unpaid_value):,})",
            })

    # Sort by total sales desc, keep only staff with any activity
    staff_table.sort(key=lambda x: x["total_sales"], reverse=True)
    staff_table = [s for s in staff_table if s["total_sales"] > 0 or s["order_count"] > 0 or s["quote_count"] > 0]
    staff_table = staff_table[:20]  # cap at 20 for chart readability

    # Top performer
    top_performer = staff_table[0]["name"] if staff_table else None

    # All-team top customers
    all_orders_qs = CustomerOrder.objects.filter(
        recycle_bin=False, agent_profile=None,
        created_on__gte=start, created_on__lte=end
    ).select_related("customer_profile")
    customer_sales = {}
    for order in all_orders_qs:
        if order.customer_profile:
            name = f"{order.customer_profile.customer_first_name} {order.customer_profile.customer_last_name}".strip()
            if name not in customer_sales:
                customer_sales[name] = {"name": name, "company": order.customer_profile.company_name or "", "total_value": 0.0, "order_count": 0}
            try:
                customer_sales[name]["total_value"] += float(order.customer_order_total_net_value or 0)
            except (TypeError, ValueError):
                pass
            customer_sales[name]["order_count"] += 1
    top_customers = sorted(customer_sales.values(), key=lambda x: x["total_value"], reverse=True)[:5]
    for c in top_customers:
        c["total_value"] = round(c["total_value"], 2)

    payload = {
        "month": month_str or "",
        "period_label": period_label,
        "staff_table": staff_table,
        "team_totals": {
            "total_sales": round(team_total_sales, 2),
            "total_orders": team_total_orders,
            "total_unpaid": team_total_unpaid,
            "staff_count": len(staff_table),
            "avg_per_staff": round(team_total_sales / len(staff_table), 2) if staff_table else 0,
        },
        "top_performer": top_performer,
        "red_flags": red_flags,
        "top_customers": top_customers,
    }
    return Response({"message": "true", "payload": payload}, status=200)

@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def sales_team(request):
    company_serial_number = request.data["serial_number"]
    active_user = request.user
    payload = {}
    sales_team_list = []
    try:
        company_profile = CompanyProfile.objects.get(
            company_serial_number=company_serial_number)
        staff_profile = StaffProfile.objects.get(user=active_user)
        department_name = staff_profile.company_department.department_name if staff_profile.company_department else ""
        if user_has_permission(staff_profile, "sales_and_marketing.performance_dashboard.view"):
            sales_dept = CompanyDepartment.objects.filter(department_name="sales").first()
            staff_qs = StaffProfile.objects.filter(
                recycle_bin=False, company_department=sales_dept) if sales_dept else StaffProfile.objects.none()
            for staff in staff_qs:
                if staff_profile.is_head_of_department or staff.id == staff_profile.id:
                    sales_team_list.append({
                        "staff_id": str(staff.id),
                        "email_address": staff.user.username if staff.user is not None else "",
                        "staff_position": staff.staff_position.position_title if staff.staff_position is not None else "",
                        "staff_number": staff.staff_number,
                        "first_name": staff.first_name,
                        "last_name": staff.last_name,
                        "phone_number": staff.phone_number,
                        "staff_title": staff.staff_title,
                        "company_branch_name": staff.company_branch.branch_name if staff.company_branch is not None else "",
                        "company_department": staff.company_department.department_name if staff.company_department is not None else "",
                        "is_head_of_department": "true" if staff.is_head_of_department else "false",
                        "customer_accounts_managed": "0",
                    })
            payload["sales_team_list"] = sales_team_list
            payload["marketing_team_list"] = []
            return Response({"message": "true", "payload": payload}, status=200)
        return Response({"message": "false", "payload": payload}, status=401)
    except Exception as e:
        logger.exception("sales_team failed")
        return Response({"message": "false", "payload": payload}, status=500)

