Files
ACORE/apps/utilities/views.py
T
2026-09-21 20:37:18 +03:00

165 lines
7.4 KiB
Python

from django.contrib.auth.decorators import login_required
from django.core.exceptions import ValidationError
from django.shortcuts import get_object_or_404
from django.views.decorators.http import require_POST
from apps.locations.models.pharmacies import Pharmacy
from core.models.directories import Directory
from core.portal_access import section_required
from core.location_access import accessible_pharmacies, scoped_queryset, require_location
from .helpers import (
attach_reading_display,
get_reading_mode,
meter_configs_map,
utility_type_modes_map,
)
from .models import UtilityMeterConfig, UtilityReading
from core.utils.permissions import is_owner_or_staff
def can_delete_reading(user, reading) -> bool:
return is_owner_or_staff(user, reading, 'submitted_by_id')
def _utilities_context(request, **extra):
"""Показання лічильників: staff бачить усі аптеки й фільтри."""
is_staff = request.user.is_staff
own_pharmacy = request.user.user_pharmacy
pharmacies = accessible_pharmacies(request.user).filter(is_active=True)
form_error = ''
config_message = ''
if request.method == 'POST':
if request.POST.get('form_kind') == 'meter_config':
if not is_staff:
config_message = 'Немає прав на налаштування лічильників.'
else:
pharmacy_id = request.POST.get('config_pharmacy')
utility_type_id = request.POST.get('config_utility_type')
reading_mode = request.POST.get('reading_mode', UtilityMeterConfig.READING_MODE_SINGLE)
if pharmacy_id and utility_type_id and reading_mode in dict(UtilityMeterConfig.READING_MODE_CHOICES):
require_location(request.user, pharmacy_id)
config, _created = UtilityMeterConfig.objects.update_or_create(
pharmacy_id=pharmacy_id,
utility_type_id=utility_type_id,
defaults={'reading_mode': reading_mode, 'is_active': True},
)
config.full_clean()
config.save()
config_message = 'Налаштування лічильника збережено.'
else:
config_message = 'Заповніть аптеку, тип лічильника та режим.'
else:
pharmacy_id = request.POST.get('pharmacy') or (own_pharmacy.pk if own_pharmacy else None)
utility_type_id = request.POST.get('utility_type')
reading_date = request.POST.get('reading_date')
value = request.POST.get('value')
value_day = request.POST.get('value_day')
value_night = request.POST.get('value_night')
if not pharmacy_id:
form_error = 'Показання не збережено: у вас не вказана аптека (зверніться до HR).'
elif not (utility_type_id and reading_date):
form_error = 'Показання не збережено: заповніть тип лічильника та дату.'
else:
require_location(request.user, pharmacy_id)
mode = get_reading_mode(pharmacy_id, utility_type_id)
reading = UtilityReading(
pharmacy_id=pharmacy_id,
utility_type_id=utility_type_id,
reading_date=reading_date,
comment=request.POST.get('comment', '').strip(),
submitted_by=request.user,
)
if mode == UtilityMeterConfig.READING_MODE_DAY_NIGHT:
reading.value_day = value_day or None
reading.value_night = value_night or None
else:
reading.value = value or None
try:
reading.full_clean()
reading.save()
except ValidationError as e:
form_error = ' '.join(m for messages in e.message_dict.values() for m in messages)
utility_types = Directory.objects.filter(directory_type__code='utility_type', is_active=True).order_by('name')
readings = scoped_queryset(request.user, UtilityReading.objects.all(), 'pharmacy').select_related(
'pharmacy', 'pharmacy__organization', 'utility_type', 'submitted_by',
)
filter_pharmacy = request.GET.get('pharmacy', '')
filter_type = request.GET.get('utility_type', '')
if filter_pharmacy:
readings = readings.filter(pharmacy_id=filter_pharmacy)
if filter_type:
readings = readings.filter(utility_type_id=filter_type)
pharmacies_for_form = pharmacies.select_related('organization').order_by('organization__name', 'pharmacy_number')
readings = list(readings[:200])
attach_reading_display(readings)
for r in readings:
r.can_delete = can_delete_reading(request.user, r)
meter_configs = list(
scoped_queryset(request.user, UtilityMeterConfig.objects.all(), 'pharmacy').select_related('pharmacy', 'pharmacy__organization', 'utility_type')
.filter(is_active=True)
.order_by('pharmacy__organization__name', 'pharmacy__pharmacy_number', 'utility_type__name')
)
import json
from django.core.serializers.json import DjangoJSONEncoder
context = {
'is_staff': is_staff,
'own_pharmacy': own_pharmacy,
'pharmacies_for_form': pharmacies_for_form,
'utility_types': utility_types,
'readings': readings,
'form_error': form_error,
'config_message': config_message,
'filter_pharmacy': filter_pharmacy,
'filter_type': filter_type,
'all_pharmacies': pharmacies.select_related('organization').order_by('organization__name', 'pharmacy_number'),
'meter_configs': meter_configs,
'meter_configs_json': json.dumps({f'{c.pharmacy_id}:{c.utility_type_id}': c.reading_mode for c in meter_configs}, cls=DjangoJSONEncoder),
'utility_type_modes_json': json.dumps(utility_type_modes_map(utility_types), cls=DjangoJSONEncoder),
'reading_mode_choices': UtilityMeterConfig.READING_MODE_CHOICES,
'own_pharmacy_id': own_pharmacy.pk if own_pharmacy else '',
}
context.update(extra)
return context
@login_required
@section_required('utilities')
def utilities_view(request):
from core.accounting_portal import render_accounting_portal
return render_accounting_portal(request, 'utilities')
@login_required
@section_required('utilities')
@require_POST
def utility_reading_delete_view(request, pk):
from core.accounting_portal import render_accounting_portal
reading = get_object_or_404(scoped_queryset(request.user, UtilityReading.objects.all(), 'pharmacy'), pk=pk)
if can_delete_reading(request.user, reading):
reading.delete()
return render_accounting_portal(request, 'utilities')
@login_required
@section_required('utilities')
@require_POST
def utility_meter_config_delete_view(request, pk):
from core.accounting_portal import render_accounting_portal
if not request.user.is_staff:
return render_accounting_portal(request, 'utilities', config_message='Немає прав.')
config = get_object_or_404(scoped_queryset(request.user, UtilityMeterConfig.objects.all(), 'pharmacy'), pk=pk)
config.delete()
return render_accounting_portal(request, 'utilities', config_message='Налаштування видалено.')