3e969e29dc
Модель и сервис событий календаря, вью и страница календаря. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
151 lines
4.6 KiB
Python
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='Событие удалено.')
|