230 lines
7.0 KiB
Python

"""
django-rules: декларативные правила доступа для procurement (закупки)
Правила используются для проверки permissions на уровне объектов.
https://github.com/dfunckt/django-rules
"""
import rules
# -----------------------------------------------------------------------------
# ПРЕДИКАТЫ (predicates)
# -----------------------------------------------------------------------------
@rules.predicate
def is_superuser(user):
"""Суперпользователь имеет все права"""
return user.is_superuser
@rules.predicate
def is_procurement_manager(user):
"""
Пользователь является менеджером по закупкам.
Адаптируйте под вашу логику (по должности, группе и т.д.)
"""
if not hasattr(user, "position"):
return False
position_name = getattr(user.position, "name", "").lower()
return any(
keyword in position_name
for keyword in ["закупк", "снабжен", "procurement", "supply"]
)
@rules.predicate
def is_purchase_request_author(user, purchase_request):
"""Пользователь является автором заявки на закупку"""
if purchase_request is None:
return False
return (
purchase_request.created_by == user
or getattr(purchase_request, "author", None) == user
)
@rules.predicate
def is_purchase_request_approver(user, purchase_request):
"""Пользователь назначен согласующим для заявки на закупку"""
if purchase_request is None:
return False
# Проверка через approvers
if hasattr(purchase_request, "approvers"):
return user in purchase_request.approvers.all()
# Проверка через approval_chain
if hasattr(purchase_request, "approval_chain"):
return purchase_request.approval_chain.filter(approver=user).exists()
return False
@rules.predicate
def is_department_purchase_request(user, purchase_request):
"""Заявка на закупку относится к отделу пользователя"""
if purchase_request is None or not hasattr(user, "department"):
return False
if hasattr(purchase_request, "department"):
return purchase_request.department == user.department
# Проверка через автора
if hasattr(purchase_request, "created_by") and hasattr(
purchase_request.created_by, "department"
):
return purchase_request.created_by.department == user.department
return False
@rules.predicate
def can_approve_purchases(user):
"""
Пользователь может согласовывать закупки.
Адаптируйте под вашу логику (по должности, бюджетным лимитам и т.д.)
"""
if not hasattr(user, "position"):
return False
position_name = getattr(user.position, "name", "").lower()
return any(
keyword in position_name
for keyword in ["руководитель", "начальник", "директор", "финансов"]
)
@rules.predicate
def is_supplier_contact(user, supplier):
"""Пользователь является контактным лицом поставщика"""
if supplier is None:
return False
if hasattr(supplier, "contact_person"):
return supplier.contact_person == user
if hasattr(supplier, "managers"):
return user in supplier.managers.all()
return False
@rules.predicate
def is_contract_manager(user, contract):
"""Пользователь является менеджером договора"""
if contract is None:
return False
if hasattr(contract, "manager"):
return contract.manager == user
if hasattr(contract, "responsible_person"):
return contract.responsible_person == user
return False
@rules.predicate
def can_manage_suppliers(user):
"""Пользователь может управлять поставщиками"""
return is_procurement_manager(user) or is_superuser(user)
# -----------------------------------------------------------------------------
# ПРАВИЛА (rules)
# -----------------------------------------------------------------------------
# Просмотр заявки на закупку
rules.add_rule(
"procurement.view_purchase_request",
is_superuser
| is_purchase_request_author
| is_procurement_manager
| is_purchase_request_approver
| can_approve_purchases,
)
# Создание заявки на закупку
rules.add_rule(
"procurement.create_purchase_request",
rules.is_authenticated, # Любой сотрудник может создать заявку
)
# Изменение заявки на закупку
rules.add_rule(
"procurement.change_purchase_request",
is_superuser | is_purchase_request_author | is_procurement_manager,
)
# Удаление заявки на закупку
rules.add_rule(
"procurement.delete_purchase_request",
is_superuser | is_purchase_request_author,
)
# Согласование заявки на закупку
rules.add_rule(
"procurement.approve_purchase_request",
is_superuser
| is_purchase_request_approver
| can_approve_purchases
| is_procurement_manager,
)
# Изменение статуса заявки
rules.add_rule(
"procurement.change_request_status",
is_superuser | is_procurement_manager | can_approve_purchases,
)
# Просмотр поставщика
rules.add_rule(
"procurement.view_supplier",
is_superuser | is_procurement_manager | is_supplier_contact,
)
# Создание/изменение поставщика
rules.add_rule(
"procurement.manage_supplier", is_superuser | can_manage_suppliers
)
# Удаление поставщика
rules.add_rule("procurement.delete_supplier", is_superuser)
# Просмотр договора
rules.add_rule(
"procurement.view_contract",
is_superuser | is_contract_manager | is_procurement_manager,
)
# Создание/изменение договора
rules.add_rule(
"procurement.manage_contract",
is_superuser | is_contract_manager | can_manage_suppliers,
)
# Удаление договора
rules.add_rule("procurement.delete_contract", is_superuser)
# Просмотр всех заявок (для менеджеров)
rules.add_rule(
"procurement.view_all_requests",
is_superuser | is_procurement_manager | can_approve_purchases,
)
# Просмотр отчётов по закупкам
rules.add_rule(
"procurement.view_reports",
is_superuser | is_procurement_manager | can_approve_purchases,
)
# Экспорт данных по закупкам
rules.add_rule("procurement.export_data", is_superuser | is_procurement_manager)
# Примеры использования перенесены в проектную документацию.