HEX
Server: nginx/1.18.0
System: Linux mail.dakarash.co.id 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User: www-data (33)
PHP: 8.1.2-1ubuntu2.23
Disabled: NONE
Upload Files
File: /home/django/apps/cargochains/sales/auth.py
# sales/auth.py
from django.db.models import Q
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin

# ---- supervisor / akses luas ----
def is_sales_supervisor(user):
    """
    True jika superuser atau anggota group 'Sales Supervisor'.
    Group opsional: kalau tidak dipakai, tetap True untuk superuser saja.
    """
    if not user or not user.is_authenticated:
        return False
    try:
        return user.is_superuser or user.groups.filter(name__iexact="Sales Supervisor").exists()
    except Exception:
        return getattr(user, "is_superuser", False)

def can_view_all_sales(user):
    """
    True jika boleh melihat SEMUA data sales:
    - superuser, atau
    - punya permission 'sales.view_all_sales', atau
    - (opsional) anggota grup 'Sales Supervisor'
    """
    return (
        getattr(user, "is_superuser", False)
        or (user.is_authenticated and user.has_perm("sales.view_all_sales"))
        or is_sales_supervisor(user)
    )

# ---- filter queryset per user ----
def sales_queryset_for_user(qs, user, include_null=False):
    """
    Supervisor/role-izin: lihat semua.
    User biasa: hanya miliknya (mendeteksi field kepemilikan secara dinamis).
    Prioritas field: sales_user > salesperson > created_by
    include_null=True => ikutkan record lama yang fieldnya NULL (opsional).
    """
    if not user or not user.is_authenticated:
        return qs.none()

    if can_view_all_sales(user):
        return qs

    field_names = {f.name for f in qs.model._meta.get_fields()}

    if "sales_user" in field_names:
        cond = Q(sales_user=user)
        if include_null:
            cond |= Q(sales_user__isnull=True)
        return qs.filter(cond)

    if "salesperson" in field_names:  # fallback untuk model lama yang masih pakai nama ini
        cond = Q(salesperson=user)
        if include_null:
            cond |= Q(salesperson__isnull=True)
        return qs.filter(cond)

    if "created_by" in field_names:
        return qs.filter(created_by=user)

    # kalau tidak ada field kepemilikan yang dikenal, ketat saja
    return qs.none()

# ---- (opsional) dekorator & mixin akses modul ----
from functools import wraps
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied

def sales_access_required(viewfunc):
    """
    Wajib login + wajib punya akses modul sales:
    - 'sales.access_sales' ATAU can_view_all_sales(user)
    """
    @wraps(viewfunc)
    @login_required
    def _wrapped(request, *args, **kwargs):
        u = request.user
        if u.has_perm("sales.access_sales") or can_view_all_sales(u):
            return viewfunc(request, *args, **kwargs)
        raise PermissionDenied("Tidak punya akses ke Sales module.")
    return _wrapped


class SalesAccessRequiredMixin(LoginRequiredMixin, PermissionRequiredMixin):
    """
    Mixin untuk CBV:
    - Wajib login
    - Boleh akses jika:
      * superuser, atau
      * punya permission 'sales.view_all_sales', atau
      * anggota grup 'Sales Supervisor' (opsional via is_sales_supervisor), atau
      * punya permission 'sales.access_sales'
    """
    permission_required = ("sales.access_sales",)
    raise_exception = False  # biar 403 (PermissionDenied) daripada redirect

    def has_permission(self):
        u = self.request.user
        # izinkan jika punya akses luas
        try:
            from .auth import can_view_all_sales  # jika fungsi ada di file yang sama, import tidak wajib
        except Exception:
            def can_view_all_sales(_u):  # fallback aman
                return getattr(_u, "is_superuser", False)
        return can_view_all_sales(u) or super().has_permission()