Игорь Надеин 69402567e3 feat(procurement): add budget control and alerts
Budget Model Enhancements:
- Add reserved_amount property (sum of pending requests)
- Add available_amount property (remaining - reserved)
- Add _quarter_months() helper method

API Endpoints:
- Add /budgets/my-department/ endpoint for user's department budget
- Add /stats/overview/ for procurement statistics
- Add /stats/by-department/ for department-level statistics
- Register ProcurementStatsViewSet in urls.py

Budget Alerts:
- Add _check_budget_alert() method in ProcurementRequestViewSet
- Send notifications when budget < 20% (low) or < 10% (critical)
- Alerts sent to department head via NotificationService

Serializers:
- Add reserved_amount, available_amount to BudgetSerializer
- Add BudgetDetailSerializer with pending_requests list

Permissions:
- Fix led_departments → headed_departments in BudgetViewSet
- Allow my_department endpoint for all authenticated users

Tests:
- Add test_budget.py with 11 new tests
- TestBudgetReservedAmount (3 tests)
- TestBudgetMyDepartmentEndpoint (3 tests)
- TestProcurementStatsEndpoints (4 tests)
- TestBudgetAlerts (1 test)

All 52 procurement tests passing:
✅ 20/20 Model tests
✅ 12/12 API tests
✅ 9/9 Workflow tests
✅ 11/11 Budget tests (NEW)
2025-12-09 10:19:24 +03:00

66 lines
1.2 KiB
Python

"""
URL конфигурация для API модуля закупок.
"""
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from .views import (
BudgetViewSet,
EquipmentCategoryViewSet,
EquipmentViewSet,
MaintenanceRecordViewSet,
ProcurementItemViewSet,
ProcurementRequestViewSet,
ProcurementStatsViewSet,
SupplierViewSet,
)
app_name = 'procurement'
router = DefaultRouter()
router.register(
r'requests',
ProcurementRequestViewSet,
basename='procurementrequest'
)
router.register(
r'items',
ProcurementItemViewSet,
basename='procurementitem'
)
router.register(
r'equipment-categories',
EquipmentCategoryViewSet,
basename='equipmentcategory'
)
router.register(
r'equipment',
EquipmentViewSet,
basename='equipment'
)
router.register(
r'maintenance',
MaintenanceRecordViewSet,
basename='maintenancerecord'
)
router.register(
r'budgets',
BudgetViewSet,
basename='budget'
)
router.register(
r'suppliers',
SupplierViewSet,
basename='supplier'
)
router.register(
r'stats',
ProcurementStatsViewSet,
basename='stats'
)
urlpatterns = [
path('', include(router.urls)),
]