Add event type handling for duties in the system
- Introduced a new `event_type` column in the `duties` table to categorize duties as 'duty', 'unavailable', or 'vacation'. - Updated the duty schedule import functionality to parse and store event types from the JSON input. - Enhanced the API response to include event types for each duty, improving the calendar display logic. - Modified the web application to visually differentiate between duty types in the calendar and duty list. - Updated tests to cover new event type functionality and ensure correct parsing and storage of duties. - Revised README documentation to reflect changes in duty event types and their representation in the system.
This commit is contained in:
@@ -101,22 +101,37 @@ def _run_import(
|
||||
result: DutyScheduleResult,
|
||||
hour_utc: int,
|
||||
minute_utc: int,
|
||||
) -> tuple[int, int]:
|
||||
) -> tuple[int, int, int, int]:
|
||||
"""Returns (num_users, num_duty, num_unavailable, num_vacation)."""
|
||||
session = get_session(database_url)
|
||||
try:
|
||||
from_date_str = result.start_date.isoformat()
|
||||
to_date_str = result.end_date.isoformat()
|
||||
total_duties = 0
|
||||
for full_name, duty_dates in result.entries:
|
||||
user = get_or_create_user_by_full_name(session, full_name)
|
||||
num_duty = num_unavailable = num_vacation = 0
|
||||
for entry in result.entries:
|
||||
user = get_or_create_user_by_full_name(session, entry.full_name)
|
||||
delete_duties_in_range(session, user.id, from_date_str, to_date_str)
|
||||
for d in duty_dates:
|
||||
for d in entry.duty_dates:
|
||||
start_at = _duty_to_iso(d, hour_utc, minute_utc)
|
||||
d_next = d + timedelta(days=1)
|
||||
end_at = _duty_to_iso(d_next, hour_utc, minute_utc)
|
||||
insert_duty(session, user.id, start_at, end_at)
|
||||
total_duties += 1
|
||||
return (len(result.entries), total_duties)
|
||||
insert_duty(session, user.id, start_at, end_at, event_type="duty")
|
||||
num_duty += 1
|
||||
for d in entry.unavailable_dates:
|
||||
start_at = _duty_to_iso(d, hour_utc, minute_utc)
|
||||
d_next = d + timedelta(days=1)
|
||||
end_at = _duty_to_iso(d_next, hour_utc, minute_utc)
|
||||
insert_duty(
|
||||
session, user.id, start_at, end_at, event_type="unavailable"
|
||||
)
|
||||
num_unavailable += 1
|
||||
for d in entry.vacation_dates:
|
||||
start_at = _duty_to_iso(d, hour_utc, minute_utc)
|
||||
d_next = d + timedelta(days=1)
|
||||
end_at = _duty_to_iso(d_next, hour_utc, minute_utc)
|
||||
insert_duty(session, user.id, start_at, end_at, event_type="vacation")
|
||||
num_vacation += 1
|
||||
return (len(result.entries), num_duty, num_unavailable, num_vacation)
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
@@ -149,15 +164,21 @@ async def handle_duty_schedule_document(update: Update, context: ContextTypes.DE
|
||||
|
||||
loop = asyncio.get_running_loop()
|
||||
try:
|
||||
num_users, num_duties = await loop.run_in_executor(
|
||||
num_users, num_duty, num_unavailable, num_vacation = await loop.run_in_executor(
|
||||
None,
|
||||
lambda: _run_import(config.DATABASE_URL, result, hour_utc, minute_utc),
|
||||
)
|
||||
except Exception as e:
|
||||
await update.message.reply_text(f"Ошибка импорта: {e}")
|
||||
else:
|
||||
total = num_duty + num_unavailable + num_vacation
|
||||
parts = [f"{num_users} пользователей", f"{num_duty} дежурств"]
|
||||
if num_unavailable:
|
||||
parts.append(f"{num_unavailable} недоступностей")
|
||||
if num_vacation:
|
||||
parts.append(f"{num_vacation} отпусков")
|
||||
await update.message.reply_text(
|
||||
f"Импорт выполнен: {num_users} пользователей, {num_duties} дежурств."
|
||||
"Импорт выполнен: " + ", ".join(parts) + f" (всего {total} событий)."
|
||||
)
|
||||
finally:
|
||||
context.user_data.pop("awaiting_duty_schedule_file", None)
|
||||
|
||||
Reference in New Issue
Block a user