Правки логики

This commit is contained in:
2026-09-21 20:37:18 +03:00
parent f653a06820
commit 536679925a
30 changed files with 447 additions and 191 deletions
+5 -1
View File
@@ -69,7 +69,7 @@ class PortalPharmacyEditForm(forms.ModelForm):
'curator': forms.Select(attrs={'class': 'input'}),
}
def __init__(self, *args, **kwargs):
def __init__(self, *args, user=None, **kwargs):
super().__init__(*args, **kwargs)
from apps.employees.models import Employee
@@ -98,3 +98,7 @@ class PortalPharmacyEditForm(forms.ModelForm):
self.fields['building'].required = False
self.fields['apartment'].required = False
self.fields['location'].required = False
if user is not None and not user.has_perm('locations.manage_location_access'):
for field in ('head_pharmacist', 'responsible_manager', 'curator'):
self.fields.pop(field, None)
+2 -1
View File
@@ -1,3 +1,4 @@
from .access import GroupLocationAccess
from .base import Location, LocationManager
from .pharmacies import Pharmacy, PharmacyManager, PharmacyPhone, PharmacyHistory
from .dislocation import DislocationColumnPreset
@@ -9,7 +10,7 @@ from .pharmacy_visibility import (
)
__all__ = [
'Location', 'LocationManager',
'GroupLocationAccess', 'Location', 'LocationManager',
'Pharmacy', 'PharmacyManager', 'PharmacyPhone', 'PharmacyHistory',
'DislocationColumnPreset',
'PharmacyCardVisibility', 'pharmacy_card_flags',
+1
View File
@@ -128,6 +128,7 @@ class Location(BaseModel):
objects = LocationManager()
class Meta:
permissions = [('view_all_locations', 'Доступ к данным всех локаций портала'), ('manage_location_access', 'Назначение ответственных за локации')]
verbose_name = _('Локация')
verbose_name_plural = _('Локации')
indexes = [
+4 -1
View File
@@ -104,6 +104,9 @@ def user_can_view_pharmacy_section(user, pharmacy, level: str) -> bool:
"""Проверка уровня видимости для user × pharmacy."""
if not user or not getattr(user, 'is_authenticated', False):
return False
from core.location_access import accessible_pharmacies
if not accessible_pharmacies(user).filter(pk=pharmacy.pk).exists():
return False
if getattr(user, 'is_superuser', False):
return True
@@ -116,7 +119,7 @@ def user_can_view_pharmacy_section(user, pharmacy, level: str) -> bool:
if level == PharmacyCardVisibility.Level.OWN_OR_STAFF:
if getattr(user, 'is_staff', False):
return True
return getattr(user, 'user_pharmacy_id', None) == getattr(pharmacy, 'pk', None)
return True # область уже проверена: своя или закреплённая аптека
if level == PharmacyCardVisibility.Level.IT:
from core.portal_access import user_can_access
if user_can_access(user, 'it_manager'):
+5 -2
View File
@@ -1,3 +1,4 @@
from core.test_utils import grant_all_locations
from unittest import mock
from django.core.exceptions import ValidationError
@@ -355,6 +356,8 @@ class PharmacyCardVisibilityTests(TestCase):
cls.it_user = Employee.objects.create_user(username='vis.it', **common)
it_group, _ = Group.objects.get_or_create(name='IT')
cls.it_user.groups.add(it_group)
grant_all_locations(cls.it_user)
grant_all_locations(cls.staff)
PharmacyCardVisibility.load()
def _set_level(self, section, level):
@@ -464,7 +467,7 @@ class PharmacyCardVisibilityTests(TestCase):
everyone = PharmacyCardVisibility.Level.EVERYONE
hidden = PharmacyCardVisibility.Level.HIDDEN
self.assertTrue(user_can_view_pharmacy_section(self.stranger, self.pharmacy, everyone))
self.assertFalse(user_can_view_pharmacy_section(self.stranger, self.pharmacy, everyone))
self.assertFalse(user_can_view_pharmacy_section(self.staff, self.pharmacy, hidden))
self.assertTrue(user_can_view_pharmacy_section(self.superuser, self.pharmacy, hidden))
@@ -489,7 +492,7 @@ class PharmacyCardVisibilityTests(TestCase):
self._set_level('rro', PharmacyCardVisibility.Level.EVERYONE)
self._set_level('equipment', PharmacyCardVisibility.Level.HIDDEN)
flags = pharmacy_card_flags(self.stranger, self.pharmacy)
self.assertTrue(flags['can_view_rro'])
self.assertFalse(flags['can_view_rro'])
self.assertFalse(flags['can_view_equipment'])
def test_detail_view_hides_tab_when_section_staff_only(self):
+5 -3
View File
@@ -8,6 +8,8 @@ from django.views.decorators.http import require_POST
from core.utils.htmx import render_page
from core.location_access import accessible_pharmacies
from .forms import PortalPharmacyEditForm
from .models import Pharmacy, pharmacy_card_flags, user_can_edit_pharmacy
@@ -68,7 +70,7 @@ def _pharmacy_detail_context(request, pharmacy, *, form=None, edit_mode=False,
can_edit = flags['can_edit']
if edit_mode and can_edit and form is None:
form = PortalPharmacyEditForm(instance=pharmacy)
form = PortalPharmacyEditForm(instance=pharmacy, user=request.user)
return {
'pharmacy': pharmacy,
@@ -94,7 +96,7 @@ def _pharmacy_detail_context(request, pharmacy, *, form=None, edit_mode=False,
@require_POST
def pharmacy_update_view(request, pk):
pharmacy = get_object_or_404(
Pharmacy.objects.select_related(
accessible_pharmacies(request.user).select_related(
'organization', 'location_region', 'head_pharmacist__post',
'responsible_manager', 'curator',
).prefetch_related('phones'),
@@ -103,7 +105,7 @@ def pharmacy_update_view(request, pk):
if not user_can_edit_pharmacy(request.user, pharmacy):
return HttpResponseForbidden()
form = PortalPharmacyEditForm(request.POST, instance=pharmacy)
form = PortalPharmacyEditForm(request.POST, instance=pharmacy, user=request.user)
if form.is_valid():
pharmacy = form.save(commit=False)
pharmacy._history_user = request.user