165 lines
7.4 KiB
Python
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='Налаштування видалено.')
|