305 lines
9.3 KiB
Python
305 lines
9.3 KiB
Python
from functools import wraps
|
|
from django.shortcuts import get_object_or_404, redirect
|
|
from django.contrib import messages
|
|
from django.utils.translation import gettext_lazy as _
|
|
from django.core.exceptions import PermissionDenied
|
|
|
|
from .models import Warehouse, WarehouseLocation, Product
|
|
from common.models import UserConfig
|
|
|
|
|
|
def get_user_config(user):
|
|
"""
|
|
Récupère ou crée la configuration utilisateur.
|
|
"""
|
|
if not user.is_authenticated or not user.pk:
|
|
return None
|
|
try:
|
|
return user.config
|
|
except UserConfig.DoesNotExist:
|
|
return UserConfig.objects.create(user=user)
|
|
|
|
|
|
def user_can_view_warehouse(user, warehouse):
|
|
"""
|
|
Vérifie si l'utilisateur peut visualiser un entrepôt.
|
|
"""
|
|
if not user.is_authenticated:
|
|
return False
|
|
|
|
config = get_user_config(user)
|
|
if not config:
|
|
return False
|
|
|
|
return config.can_view_warehouse(warehouse)
|
|
|
|
|
|
def user_can_manage_warehouse(user, warehouse):
|
|
"""
|
|
Vérifie si l'utilisateur peut gérer un entrepôt.
|
|
"""
|
|
if not user.is_authenticated:
|
|
return False
|
|
|
|
config = get_user_config(user)
|
|
if not config:
|
|
return False
|
|
|
|
return config.can_manage_warehouse(warehouse)
|
|
|
|
|
|
def get_user_accessible_warehouses(user, can_manage=False):
|
|
"""
|
|
Retourne la liste des entrepôts accessibles par l'utilisateur.
|
|
"""
|
|
if not user.is_authenticated:
|
|
return Warehouse.objects.none()
|
|
|
|
config = get_user_config(user)
|
|
if not config:
|
|
return Warehouse.objects.none()
|
|
|
|
return config.get_accessible_warehouses(can_manage=can_manage)
|
|
|
|
|
|
def warehouse_view_required(view_func):
|
|
"""
|
|
Décorateur pour vérifier que l'utilisateur peut visualiser l'entrepôt.
|
|
L'ID de l'entrepôt doit être passé en paramètre 'warehouse_id'.
|
|
"""
|
|
@wraps(view_func)
|
|
def wrapper(request, warehouse_id, *args, **kwargs):
|
|
warehouse = get_object_or_404(Warehouse, id=warehouse_id)
|
|
|
|
if not user_can_view_warehouse(request.user, warehouse):
|
|
messages.error(
|
|
request,
|
|
_("Vous n'avez pas la permission de visualiser cet entrepôt.")
|
|
)
|
|
return redirect('stock:warehouses')
|
|
|
|
return view_func(request, warehouse_id, *args, **kwargs)
|
|
|
|
return wrapper
|
|
|
|
|
|
def warehouse_manage_required(view_func):
|
|
"""
|
|
Décorateur pour vérifier que l'utilisateur peut gérer l'entrepôt.
|
|
L'ID de l'entrepôt doit être passé en paramètre 'warehouse_id'.
|
|
"""
|
|
@wraps(view_func)
|
|
def wrapper(request, warehouse_id, *args, **kwargs):
|
|
warehouse = get_object_or_404(Warehouse, id=warehouse_id)
|
|
|
|
if not user_can_manage_warehouse(request.user, warehouse):
|
|
messages.error(
|
|
request,
|
|
_("Vous n'avez pas la permission de gérer cet entrepôt.")
|
|
)
|
|
return redirect('stock:warehouses')
|
|
|
|
return view_func(request, warehouse_id, *args, **kwargs)
|
|
|
|
return wrapper
|
|
|
|
|
|
def location_view_required(view_func):
|
|
"""
|
|
Décorateur pour vérifier que l'utilisateur peut visualiser l'emplacement d'entrepôt.
|
|
L'ID de l'emplacement doit être passé en paramètre 'location_id'.
|
|
"""
|
|
@wraps(view_func)
|
|
def wrapper(request, location_id, *args, **kwargs):
|
|
location = get_object_or_404(WarehouseLocation, id=location_id)
|
|
|
|
if not user_can_view_warehouse(request.user, location.warehouse):
|
|
messages.error(
|
|
request,
|
|
_("Vous n'avez pas la permission de visualiser cet emplacement.")
|
|
)
|
|
return redirect('stock:warehouses')
|
|
|
|
return view_func(request, location_id, *args, **kwargs)
|
|
|
|
return wrapper
|
|
|
|
|
|
def location_manage_required(view_func):
|
|
"""
|
|
Décorateur pour vérifier que l'utilisateur peut gérer l'emplacement d'entrepôt.
|
|
L'ID de l'emplacement doit être passé en paramètre 'location_id'.
|
|
"""
|
|
@wraps(view_func)
|
|
def wrapper(request, location_id, *args, **kwargs):
|
|
location = get_object_or_404(WarehouseLocation, id=location_id)
|
|
|
|
if not user_can_manage_warehouse(request.user, location.warehouse):
|
|
messages.error(
|
|
request,
|
|
_("Vous n'avez pas la permission de gérer cet emplacement.")
|
|
)
|
|
return redirect('stock:warehouses')
|
|
|
|
return view_func(request, location_id, *args, **kwargs)
|
|
|
|
return wrapper
|
|
|
|
|
|
def product_view_required(view_func):
|
|
"""
|
|
Décorateur pour vérifier que l'utilisateur peut visualiser un produit.
|
|
Vérifie que l'utilisateur a accès à au moins un entrepôt contenant ce produit.
|
|
L'ID du produit doit être passé en paramètre 'product_id'.
|
|
"""
|
|
@wraps(view_func)
|
|
def wrapper(request, product_id, *args, **kwargs):
|
|
product = get_object_or_404(Product, id=product_id)
|
|
|
|
# Bypasser pour les superutilisateurs, le staff ou les admins
|
|
config = get_user_config(request.user)
|
|
if request.user.is_superuser or request.user.is_staff or (config and config.has_role('admin')):
|
|
return view_func(request, product_id, *args, **kwargs)
|
|
|
|
# Bypasser si le produit n'a aucun stock physique n'importe où
|
|
if not product.stocks.exists():
|
|
return view_func(request, product_id, *args, **kwargs)
|
|
|
|
accessible_warehouses = get_user_accessible_warehouses(request.user)
|
|
|
|
# Vérifier si le produit est dans un entrepôt accessible
|
|
product_warehouses = Warehouse.objects.filter(
|
|
locations__stocks__product=product
|
|
).distinct()
|
|
|
|
if not product_warehouses.filter(id__in=accessible_warehouses).exists():
|
|
messages.error(
|
|
request,
|
|
_("Vous n'avez pas la permission de visualiser ce produit.")
|
|
)
|
|
return redirect('stock:warehouses')
|
|
|
|
return view_func(request, product_id, *args, **kwargs)
|
|
|
|
return wrapper
|
|
|
|
|
|
def filter_warehouses_by_permission(queryset, user, can_manage=False):
|
|
"""
|
|
Filtre un queryset de Warehouse en fonction des permissions de l'utilisateur.
|
|
"""
|
|
accessible_warehouses = get_user_accessible_warehouses(user, can_manage=can_manage)
|
|
return queryset.filter(id__in=accessible_warehouses)
|
|
|
|
|
|
def filter_locations_by_permission(queryset, user, can_manage=False):
|
|
"""
|
|
Filtre un queryset de WarehouseLocation en fonction des permissions de l'utilisateur.
|
|
"""
|
|
accessible_warehouses = get_user_accessible_warehouses(user, can_manage=can_manage)
|
|
return queryset.filter(warehouse__id__in=accessible_warehouses)
|
|
|
|
|
|
def filter_products_by_permission(queryset, user):
|
|
"""
|
|
Filtre un queryset de Product en fonction des permissions de l'utilisateur.
|
|
Retourne les produits présents dans les entrepôts accessibles, ainsi que
|
|
les produits qui ne sont pas encore associés à un emplacement (sans stock).
|
|
"""
|
|
from django.db.models import Q
|
|
accessible_warehouses = get_user_accessible_warehouses(user)
|
|
return queryset.filter(
|
|
Q(stocks__isnull=True) | Q(stocks__location__warehouse__id__in=accessible_warehouses)
|
|
).distinct()
|
|
|
|
|
|
def user_can_validate_inventory(user, warehouse):
|
|
"""
|
|
Vérifie si l'utilisateur peut valider les inventaires d'un entrepôt.
|
|
"""
|
|
if not user.is_authenticated:
|
|
return False
|
|
|
|
config = get_user_config(user)
|
|
if not config:
|
|
return False
|
|
|
|
return config.can_validate_inventory_for(warehouse)
|
|
|
|
|
|
def user_can_perform_inventory_on(user, location):
|
|
"""
|
|
Vérifie si l'utilisateur peut effectuer un inventaire sur un emplacement spécifique.
|
|
"""
|
|
if not user.is_authenticated:
|
|
return False
|
|
|
|
config = get_user_config(user)
|
|
if not config:
|
|
return False
|
|
|
|
return config.can_perform_inventory_on(location)
|
|
|
|
|
|
def user_can_validate_inventory_on(user, location):
|
|
"""
|
|
Vérifie si l'utilisateur peut valider les inventaires d'un emplacement spécifique.
|
|
"""
|
|
if not user.is_authenticated:
|
|
return False
|
|
|
|
config = get_user_config(user)
|
|
if not config:
|
|
return False
|
|
|
|
return config.can_validate_inventory_on(location)
|
|
|
|
|
|
def user_can_administer_warehouse(user, warehouse):
|
|
"""
|
|
Vérifie si l'utilisateur peut administrer un entrepôt spécifique.
|
|
"""
|
|
if not user.is_authenticated:
|
|
return False
|
|
|
|
config = get_user_config(user)
|
|
if not config:
|
|
return False
|
|
|
|
return config.can_administer_warehouse(warehouse)
|
|
|
|
|
|
def user_can_administer_any_warehouse(user):
|
|
"""
|
|
Vérifie si l'utilisateur peut administrer au moins un entrepôt.
|
|
"""
|
|
if not user.is_authenticated:
|
|
return False
|
|
|
|
config = get_user_config(user)
|
|
if not config:
|
|
return False
|
|
|
|
return config.can_administer_any_warehouse()
|
|
|
|
|
|
def user_can_manage_products(user):
|
|
"""
|
|
Vérifie si l'utilisateur peut gérer les produits (créer, modifier, supprimer).
|
|
Autorisé pour les rôles admin et pour les utilisateurs
|
|
ayant can_administer sur au moins un entrepôt.
|
|
"""
|
|
if not user.is_authenticated:
|
|
return False
|
|
|
|
if user.is_superuser:
|
|
return True
|
|
|
|
config = get_user_config(user)
|
|
if not config:
|
|
return False
|
|
|
|
return (
|
|
config.has_role('admin')
|
|
or config.can_administer_any_warehouse()
|
|
)
|