- Убрать remaining_amount и utilization_percentage из list_display (это @property) - Добавить методы get_remaining_amount и get_utilization_percentage - Защитить от None в allocated_amount - Исправить prefetch_related в views_frontend
161 lines
7.0 KiB
Markdown
161 lines
7.0 KiB
Markdown
# Механизм назначения согласующих в заявках на закупку
|
||
|
||
## Как это работает
|
||
|
||
### 1. Определение требуемых ролей (модель `ProcurementRequest`)
|
||
|
||
Когда пользователь отправляет заявку на согласование (`submit` action), система определяет какие роли нужны:
|
||
|
||
```python
|
||
# в 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()`)
|
||
|
||
После определения ролей система ищет людей, занимающих эти должности:
|
||
|
||
```python
|
||
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. "Финансовый менеджер не найдена"
|
||
```python
|
||
# Причина: нет пользователя с правом change_budget
|
||
# Решение:
|
||
Django Admin → Users → выбрать пользователя → добавить permission change_budget
|
||
```
|
||
|
||
### 2. "Директор не найден"
|
||
```python
|
||
# Причина: нет суперпользователей в системе
|
||
# Решение:
|
||
Django Admin → Users → выбрать пользователя → поставить галочку is_superuser
|
||
```
|
||
|
||
### 3. Разные согласующие для разных отделов
|
||
```python
|
||
# Текущая реализация: один финменеджер и один директор на всю компанию
|
||
# Чтобы сделать разных:
|
||
# 1. Создать модель ApprovalChain или DepartmentApprovalPolicy
|
||
# 2. Связать со своими финменеджерами и директорами
|
||
# 3. Изменить логику поиска в submit action
|
||
```
|
||
|
||
## API для отладки
|
||
|
||
### Проверить какие роли требуются для заявки
|
||
```bash
|
||
GET /api/procurement/requests/{id}/
|
||
# Ответ содержит поле "required_approvals" если его добавить в сериализатор
|
||
```
|
||
|
||
### Узнать кто назначен согласующим
|
||
```bash
|
||
GET /api/procurement/requests/{id}/
|
||
# approvals: [
|
||
# { id, approver, role, status, comment }
|
||
# ]
|
||
```
|
||
|
||
## Параметры для настройки
|
||
|
||
```python
|
||
# backend/procurement/constants.py
|
||
|
||
APPROVAL_THRESHOLD_LOW = 10_000 # ← Можно менять
|
||
APPROVAL_THRESHOLD_HIGH = 50_000 # ← Можно менять
|
||
|
||
# Порог | Рол требующиеся
|
||
# < 10K | Руководитель отдела
|
||
# 10K - 50K | Руководитель + Финансы
|
||
# > 50K | Руководитель + Финансы + Директор
|
||
```
|