locations: недостающие модули области доступа + гейт reports
Делает HEAD целостным: коммит 5366799 уже импортировал эти файлы, но они
не были добавлены в git (свежий checkout падал с ImportError, а migrate не
создавал таблицу GroupLocationAccess).
- core/location_access.py: область данных (accessible_pharmacies/locations,
scoped_queryset/employees, has_all_locations) — fail-closed
- apps/locations/models/access.py + миграция 0014: GroupLocationAccess,
право locations.view_all_locations
- core/tests_location_access.py: 15 сценариев scoping
- apps/reports/*: снятие лишнего гейта has_all_locations с IT-отчёта отдела
(руководитель не обязан иметь доступ ко всей сети) + тест
- apps/rro/tests: чужая аптека теперь 404 (единая область доступа), а не
«200 с урезанными панелями» — под новую модель
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
# Generated by Django 6.0.3 on 2026-09-21 17:24
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
('locations', '0013_pharmacy_edit_permission'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='location',
|
||||
options={'permissions': [('view_all_locations', 'Доступ к данным всех локаций портала'), ('manage_location_access', 'Назначение ответственных за локации')], 'verbose_name': 'Локация', 'verbose_name_plural': 'Локации'},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='GroupLocationAccess',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('group', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='location_access', to='auth.group', verbose_name='Группа')),
|
||||
('locations', models.ManyToManyField(blank=True, help_text='Дополняют свою локацию и закреплённые аптеки. Доступ к разделам выдаётся отдельно.', related_name='location_access_groups', to='locations.location', verbose_name='Доступные локации')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Область доступа группы',
|
||||
'verbose_name_plural': 'Области доступа групп',
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,14 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class GroupLocationAccess(models.Model):
|
||||
group = models.OneToOneField('auth.Group', on_delete=models.CASCADE, related_name='location_access', verbose_name=_('Группа'))
|
||||
locations = models.ManyToManyField('locations.Location', blank=True, related_name='location_access_groups', verbose_name=_('Доступные локации'), help_text=_('Дополняют свою локацию и закреплённые аптеки. Доступ к разделам выдаётся отдельно.'))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Область доступа группы')
|
||||
verbose_name_plural = _('Области доступа групп')
|
||||
|
||||
def __str__(self):
|
||||
return str(self.group)
|
||||
Reference in New Issue
Block a user