- Убрать remaining_amount и utilization_percentage из list_display (это @property) - Добавить методы get_remaining_amount и get_utilization_percentage - Защитить от None в allocated_amount - Исправить prefetch_related в views_frontend
7.0 KiB
7.0 KiB
Механизм назначения согласующих в заявках на закупку
Как это работает
1. Определение требуемых ролей (модель ProcurementRequest)
Когда пользователь отправляет заявку на согласование (submit action), система определяет какие роли нужны:
# в procurement/models.py - метод get_required_approvals()
cost = estimated_cost # Сумма заявки
if cost < 10,000₽: # НИЗКАЯ
→ [DEPARTMENT_HEAD] # Только руководитель отдела
elif cost < 100,000₽: # СРЕДНЯЯ
→ [DEPARTMENT_HEAD, # Руководитель отдела +
FINANCE_MANAGER] # Финансовый менеджер
else: # ВЫСОКАЯ (> 100K)
→ [DEPARTMENT_HEAD, # Руководитель отдела +
FINANCE_MANAGER, # Финансовый менеджер +
DIRECTOR] # Генеральный директор
2. Поиск конкретных людей (вьюсет ProcurementRequestViewSet.submit())
После определения ролей система ищет людей, занимающих эти должности:
for role in required_approvals:
approver = None
if role == DEPARTMENT_HEAD:
# ✅ Берёт руководителя из department.head
approver = procurement_request.department.head
elif role == FINANCE_MANAGER:
# ✅ Ищет пользователя с правом change_budget
approver = Employee.objects.filter(
is_active=True,
groups__permissions__codename='change_budget'
).first()
elif role == DIRECTOR:
# ✅ Берёт первого суперпользователя
approver = Employee.objects.filter(
is_superuser=True
).first()
# Создаём запись согласования
Approval.objects.create(
request=procurement_request,
approver=approver,
role=role,
status=ApprovalStatus.PENDING
)
Пример
Заявка на 50,000₽ от отдела IT
Сумма: 50,000₽
Отдел: IT (руководитель = Петр Петров)
┌─────────────────────────────────────────┐
│ Определение ролей (get_required_approvals)
│ 10,000 < 50,000 < 100,000
│ → [DEPARTMENT_HEAD, FINANCE_MANAGER]
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Поиск согласующих (submit action) │
├─────────────────────────────────────────┤
│ DEPARTMENT_HEAD │
│ → IT.head = Петр Петров ✓ │
│ │
│ FINANCE_MANAGER │
│ → Permission(change_budget) │
│ → Мария Сидорова ✓ │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ Создание записей согласования │
├─────────────────────────────────────────┤
│ Approval #1: Петр Петров (PENDING) │
│ Approval #2: Мария Сидорова (PENDING) │
└─────────────────────────────────────────┘
↓
Уведомления
↙ ↖
Петр Мария
Где это конфигурируется?
| Компонент | Где конфигурируется | Как |
|---|---|---|
| Пороги сумм | procurement/constants.py |
APPROVAL_THRESHOLD_LOW, APPROVAL_THRESHOLD_HIGH |
| Руководитель отдела | Django Admin → Departments | Выбрать head в модели Department |
| Финансовый менеджер | Django Admin → Permissions | Дать permission change_budget пользователю или группе |
| Директор | Django Admin → Users | Сделать пользователя суперпользователем (is_superuser=True) |
Потенциальные проблемы и решения
1. "Финансовый менеджер не найдена"
# Причина: нет пользователя с правом change_budget
# Решение:
Django Admin → Users → выбрать пользователя → добавить permission change_budget
2. "Директор не найден"
# Причина: нет суперпользователей в системе
# Решение:
Django Admin → Users → выбрать пользователя → поставить галочку is_superuser
3. Разные согласующие для разных отделов
# Текущая реализация: один финменеджер и один директор на всю компанию
# Чтобы сделать разных:
# 1. Создать модель ApprovalChain или DepartmentApprovalPolicy
# 2. Связать со своими финменеджерами и директорами
# 3. Изменить логику поиска в submit action
API для отладки
Проверить какие роли требуются для заявки
GET /api/procurement/requests/{id}/
# Ответ содержит поле "required_approvals" если его добавить в сериализатор
Узнать кто назначен согласующим
GET /api/procurement/requests/{id}/
# approvals: [
# { id, approver, role, status, comment }
# ]
Параметры для настройки
# backend/procurement/constants.py
APPROVAL_THRESHOLD_LOW = 10_000 # ← Можно менять
APPROVAL_THRESHOLD_HIGH = 50_000 # ← Можно менять
# Порог | Рол требующиеся
# < 10K | Руководитель отдела
# 10K - 50K | Руководитель + Финансы
# > 50K | Руководитель + Финансы + Директор