Files
ACORE/apps/visit_manager/views_calendar.py
T
lokses 3e969e29dc visit_manager: события календаря
Модель и сервис событий календаря, вью и страница календаря.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-09 18:03:44 +03:00

151 lines
4.6 KiB
Python

"""Views портального календаря."""
from __future__ import annotations
from datetime import datetime
from django.contrib.auth.decorators import login_required
from django.core.exceptions import ValidationError
from django.http import HttpResponseForbidden
from django.shortcuts import get_object_or_404
from django.views.decorators.http import require_POST
from core.portal_access import user_can_manage_hr_portal
from core.utils.htmx import render_page
from apps.visit_manager.calendar_service import build_calendar_context
from apps.visit_manager.models import CalendarEvent
def _scope_from_request(request) -> str:
scope = request.GET.get('scope') or request.POST.get('scope') or 'mine'
return scope if scope in ('mine', 'team') else 'mine'
def _month_from_request(request) -> str | None:
return request.GET.get('month') or request.POST.get('month') or None
def _render_calendar(request, **extra):
context = build_calendar_context(
request.user,
month_str=_month_from_request(request),
scope=_scope_from_request(request),
)
context.update(extra)
return render_page(request, 'calendar.html', context)
@login_required
def calendar_view(request):
return _render_calendar(request)
def _parse_date(raw: str):
raw = (raw or '').strip()
if not raw:
return None
try:
return datetime.strptime(raw, '%Y-%m-%d').date()
except ValueError:
return None
def _parse_time(raw: str):
raw = (raw or '').strip()
if not raw:
return None
for fmt in ('%H:%M', '%H:%M:%S'):
try:
return datetime.strptime(raw, fmt).time()
except ValueError:
continue
return None
@login_required
@require_POST
def calendar_event_create_view(request):
title = request.POST.get('title', '').strip()
event_type = request.POST.get('event_type', 'other').strip() or 'other'
visibility = request.POST.get('visibility', 'company').strip() or 'company'
date_from = _parse_date(request.POST.get('date_from', ''))
date_to = _parse_date(request.POST.get('date_to', '')) or date_from
time_from = _parse_time(request.POST.get('time_from', ''))
time_to = _parse_time(request.POST.get('time_to', ''))
location = request.POST.get('location', '').strip()
notes = request.POST.get('notes', '').strip()
form_data = {
'title': title,
'event_type': event_type,
'visibility': visibility,
'date_from': request.POST.get('date_from', ''),
'date_to': request.POST.get('date_to', ''),
'time_from': request.POST.get('time_from', ''),
'time_to': request.POST.get('time_to', ''),
'location': location,
'notes': notes,
}
errors = []
if not title:
errors.append('Укажите название события.')
if not date_from:
errors.append('Укажите дату начала.')
if event_type not in dict(CalendarEvent.EVENT_TYPES):
event_type = 'other'
if visibility not in dict(CalendarEvent.VISIBILITY_CHOICES):
visibility = 'company'
if errors:
return _render_calendar(
request,
cal_form_open=True,
cal_form_errors=errors,
cal_form_data=form_data,
)
event = CalendarEvent(
title=title,
event_type=event_type,
visibility=visibility,
date_from=date_from,
date_to=date_to or date_from,
time_from=time_from,
time_to=time_to,
location=location,
notes=notes,
created_by=request.user,
)
try:
event.save()
except ValidationError as exc:
messages = []
if hasattr(exc, 'message_dict'):
for msgs in exc.message_dict.values():
messages.extend(msgs)
else:
messages.extend(exc.messages)
return _render_calendar(
request,
cal_form_open=True,
cal_form_errors=messages or ['Не удалось сохранить событие.'],
cal_form_data=form_data,
)
return _render_calendar(request, cal_form_message='Событие создано.')
@login_required
@require_POST
def calendar_event_delete_view(request, pk):
event = get_object_or_404(CalendarEvent, pk=pk)
allowed = (
event.created_by_id == request.user.pk
or getattr(request.user, 'is_staff', False)
or user_can_manage_hr_portal(request.user)
)
if not allowed:
return HttpResponseForbidden()
event.delete()
return _render_calendar(request, cal_form_message='Событие удалено.')