Implement duty schedule import functionality and enhance user management
- Added a new command `/import_duty_schedule` for importing duty schedules via JSON, restricted to admin users. - Introduced a two-step import process: specifying handover time and uploading a JSON file. - Updated the database schema to allow `telegram_user_id` to be nullable for user creation by full name. - Implemented repository functions for user management, including `get_or_create_user_by_full_name` and `delete_duties_in_range`. - Enhanced README documentation with details on the new import command and JSON format requirements. - Added comprehensive tests for the duty schedule parser and integration tests for the import functionality.
This commit is contained in:
93
tests/test_repository_duty_range.py
Normal file
93
tests/test_repository_duty_range.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""Tests for delete_duties_in_range and get_or_create_user_by_full_name."""
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from db.models import Base, User, Duty
|
||||
from db.repository import (
|
||||
delete_duties_in_range,
|
||||
get_or_create_user_by_full_name,
|
||||
get_duties,
|
||||
insert_duty,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def session():
|
||||
engine = create_engine("sqlite:///:memory:", connect_args={"check_same_thread": False})
|
||||
Base.metadata.create_all(engine)
|
||||
Session = sessionmaker(bind=engine, autocommit=False, autoflush=False)
|
||||
s = Session()
|
||||
try:
|
||||
yield s
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user_a(session):
|
||||
u = User(
|
||||
telegram_user_id=None,
|
||||
full_name="User A",
|
||||
username=None,
|
||||
first_name=None,
|
||||
last_name=None,
|
||||
)
|
||||
session.add(u)
|
||||
session.commit()
|
||||
session.refresh(u)
|
||||
return u
|
||||
|
||||
|
||||
def test_get_or_create_user_by_full_name_creates(session):
|
||||
u = get_or_create_user_by_full_name(session, "Новый Пользователь")
|
||||
assert u.id is not None
|
||||
assert u.full_name == "Новый Пользователь"
|
||||
assert u.telegram_user_id is None
|
||||
|
||||
|
||||
def test_get_or_create_user_by_full_name_returns_existing(session, user_a):
|
||||
u = get_or_create_user_by_full_name(session, "User A")
|
||||
assert u.id == user_a.id
|
||||
assert u.full_name == "User A"
|
||||
|
||||
|
||||
def test_delete_duties_in_range_removes_only_in_range(session, user_a):
|
||||
# Duties: 2026-02-01 06:00 - 2026-02-02 06:00; 2026-02-15 - 2026-02-16; 2026-02-28 - 2026-03-01
|
||||
insert_duty(
|
||||
session,
|
||||
user_a.id,
|
||||
"2026-02-01T06:00:00Z",
|
||||
"2026-02-02T06:00:00Z",
|
||||
)
|
||||
insert_duty(
|
||||
session,
|
||||
user_a.id,
|
||||
"2026-02-15T06:00:00Z",
|
||||
"2026-02-16T06:00:00Z",
|
||||
)
|
||||
insert_duty(
|
||||
session,
|
||||
user_a.id,
|
||||
"2026-02-28T06:00:00Z",
|
||||
"2026-03-01T06:00:00Z",
|
||||
)
|
||||
deleted = delete_duties_in_range(session, user_a.id, "2026-02-10", "2026-02-20")
|
||||
assert deleted == 1
|
||||
remaining = get_duties(session, "2026-01-01", "2026-03-31")
|
||||
assert len(remaining) == 2
|
||||
starts = [d[0].start_at for d in remaining]
|
||||
assert "2026-02-01T06:00:00Z" in starts
|
||||
assert "2026-02-28T06:00:00Z" in starts
|
||||
assert "2026-02-15T06:00:00Z" not in starts
|
||||
|
||||
|
||||
def test_delete_duties_in_range_other_user_unchanged(session, user_a):
|
||||
user_b = get_or_create_user_by_full_name(session, "User B")
|
||||
insert_duty(session, user_a.id, "2026-02-10T06:00:00Z", "2026-02-11T06:00:00Z")
|
||||
insert_duty(session, user_b.id, "2026-02-10T06:00:00Z", "2026-02-11T06:00:00Z")
|
||||
delete_duties_in_range(session, user_a.id, "2026-02-01", "2026-02-28")
|
||||
remaining = get_duties(session, "2026-02-01", "2026-02-28")
|
||||
assert len(remaining) == 1
|
||||
assert remaining[0][1] == "User B"
|
||||
Reference in New Issue
Block a user