Refactor app structure and simplify team docs

This commit is contained in:
hyunho
2026-04-02 11:13:43 +09:00
parent 8125193378
commit f8ea345882
47 changed files with 4921 additions and 10495 deletions

View File

@@ -0,0 +1,145 @@
from __future__ import annotations
from datetime import date, datetime, time, timedelta
from typing import Callable
from fastapi import HTTPException
def fetch_members(get_conn) -> list[dict[str, object]]:
with get_conn() as conn:
with conn.cursor() as cur:
cur.execute(
"""
SELECT id, name, employee_id, company, rank, role, department, grp, division, team, cell,
work_status, work_time, phone, email, seat_label, photo_url,
sort_order, created_at, updated_at
FROM members
ORDER BY sort_order ASC, id ASC
"""
)
return cur.fetchall()
def fetch_history_revision(cur, revision_id: int) -> dict[str, object] | None:
cur.execute(
"""
SELECT id, revision_label, created_at, note
FROM history_revisions
WHERE scope = 'organization'
AND id = %s
""",
(revision_id,),
)
return cur.fetchone()
def fetch_history_revisions(
cur,
*,
app_timezone,
day: date | None = None,
limit: int = 100,
) -> list[dict[str, object]]:
safe_limit = max(1, min(int(limit), 500))
if day is None:
cur.execute(
"""
SELECT id, revision_label, created_at, note
FROM history_revisions
WHERE scope = 'organization'
ORDER BY created_at DESC, id DESC
LIMIT %s
""",
(safe_limit,),
)
return cur.fetchall()
day_start = datetime.combine(day, time.min, tzinfo=app_timezone)
day_end = day_start + timedelta(days=1)
cur.execute(
"""
SELECT id, revision_label, created_at, note
FROM history_revisions
WHERE scope = 'organization'
AND created_at >= %s
AND created_at < %s
ORDER BY created_at ASC, id ASC
LIMIT %s
""",
(day_start, day_end, safe_limit),
)
return cur.fetchall()
def fetch_history_revision_created_at(cur, revision_id: int) -> datetime:
revision = fetch_history_revision(cur, revision_id)
if revision is None:
raise HTTPException(status_code=404, detail="History revision not found.")
return revision["created_at"]
def fetch_current_member_state(cur) -> dict[int, dict[str, object]]:
cur.execute(
"""
SELECT id, name, employee_id, company, rank, role, department, grp, division, team, cell,
work_status, work_time, phone, email, seat_label, photo_url, sort_order,
created_at, updated_at
FROM members
"""
)
return {int(row["id"]): row for row in cur.fetchall()}
def fetch_current_seat_assignments(cur) -> dict[int, dict[str, object]]:
cur.execute(
"""
SELECT member_id, seat_map_id, seat_slot_id, seat_label, updated_at
FROM seat_positions
"""
)
return {int(row["member_id"]): row for row in cur.fetchall()}
def fetch_members_as_of(cur, as_of: datetime) -> list[dict[str, object]]:
cur.execute(
"""
SELECT mv.member_id AS id,
mv.name,
COALESCE(m.employee_id, '') AS employee_id,
mv.company,
mv.rank,
mv.role,
mv.department,
mv.grp,
mv.division,
mv.team,
mv.cell,
mv.work_status,
mv.work_time,
mv.phone,
mv.email,
COALESCE(sav.seat_label, '') AS seat_label,
mv.photo_url,
COALESCE(m.sort_order, 2147483647) AS sort_order,
mv.created_at,
mv.valid_from AS updated_at,
mv.valid_to AS history_valid_to,
mv.revision_no,
hr.created_at AS revision_created_at
FROM member_versions mv
LEFT JOIN members m
ON m.id = mv.member_id
LEFT JOIN history_revisions hr
ON hr.id = mv.revision_no
LEFT JOIN seat_assignment_versions sav
ON sav.member_id = mv.member_id
AND sav.valid_from <= %s
AND (sav.valid_to IS NULL OR sav.valid_to > %s)
WHERE mv.valid_from <= %s
AND (mv.valid_to IS NULL OR mv.valid_to > %s)
ORDER BY COALESCE(m.sort_order, 2147483647) ASC, mv.member_id ASC
""",
(as_of, as_of, as_of, as_of),
)
return cur.fetchall()