109 lines
3.6 KiB
Python
109 lines
3.6 KiB
Python
import uuid
|
|
from datetime import date
|
|
from typing import Sequence
|
|
|
|
from sqlalchemy import select, update as sa_update
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.models.subject import Subject
|
|
from app.models.verification import VerificationProgress
|
|
from app.schemas.verification import VerificationCreate, VerificationUpdate
|
|
|
|
|
|
async def _validate_site_subject(db: AsyncSession, study_id: uuid.UUID, site_id: uuid.UUID, subject_id: uuid.UUID):
|
|
result = await db.execute(select(Subject).where(Subject.id == subject_id))
|
|
subj = result.scalar_one_or_none()
|
|
if not subj or subj.study_id != study_id:
|
|
raise ValueError("Subject not found in study")
|
|
if subj.site_id != site_id:
|
|
raise ValueError("Site does not match subject")
|
|
|
|
|
|
async def upsert_progress(
|
|
db: AsyncSession,
|
|
study_id: uuid.UUID,
|
|
data: VerificationCreate,
|
|
) -> VerificationProgress:
|
|
await _validate_site_subject(db, study_id, data.site_id, data.subject_id)
|
|
|
|
result = await db.execute(
|
|
select(VerificationProgress).where(
|
|
VerificationProgress.study_id == study_id,
|
|
VerificationProgress.subject_id == data.subject_id,
|
|
VerificationProgress.level == data.level,
|
|
)
|
|
)
|
|
existing = result.scalar_one_or_none()
|
|
if existing:
|
|
update_data = data.model_dump()
|
|
await db.execute(
|
|
sa_update(VerificationProgress)
|
|
.where(VerificationProgress.id == existing.id)
|
|
.values(**update_data)
|
|
)
|
|
await db.commit()
|
|
await db.refresh(existing)
|
|
return existing
|
|
|
|
vp = VerificationProgress(
|
|
study_id=study_id,
|
|
site_id=data.site_id,
|
|
subject_id=data.subject_id,
|
|
level=data.level,
|
|
percent=data.percent,
|
|
last_verified_at=data.last_verified_at,
|
|
verifier_id=data.verifier_id,
|
|
notes=data.notes,
|
|
)
|
|
db.add(vp)
|
|
await db.commit()
|
|
await db.refresh(vp)
|
|
return vp
|
|
|
|
|
|
async def get_progress(db: AsyncSession, study_id: uuid.UUID, subject_id: uuid.UUID, level: str) -> VerificationProgress | None:
|
|
result = await db.execute(
|
|
select(VerificationProgress).where(
|
|
VerificationProgress.study_id == study_id,
|
|
VerificationProgress.subject_id == subject_id,
|
|
VerificationProgress.level == level,
|
|
)
|
|
)
|
|
return result.scalar_one_or_none()
|
|
|
|
|
|
async def get_by_id(db: AsyncSession, verification_id: uuid.UUID) -> VerificationProgress | None:
|
|
result = await db.execute(select(VerificationProgress).where(VerificationProgress.id == verification_id))
|
|
return result.scalar_one_or_none()
|
|
|
|
|
|
async def list_progress(
|
|
db: AsyncSession,
|
|
study_id: uuid.UUID,
|
|
site_id: uuid.UUID | None = None,
|
|
subject_id: uuid.UUID | None = None,
|
|
level: str | None = None,
|
|
) -> Sequence[VerificationProgress]:
|
|
stmt = select(VerificationProgress).where(VerificationProgress.study_id == study_id)
|
|
if site_id:
|
|
stmt = stmt.where(VerificationProgress.site_id == site_id)
|
|
if subject_id:
|
|
stmt = stmt.where(VerificationProgress.subject_id == subject_id)
|
|
if level:
|
|
stmt = stmt.where(VerificationProgress.level == level)
|
|
result = await db.execute(stmt)
|
|
return result.scalars().all()
|
|
|
|
|
|
async def update_progress(db: AsyncSession, vp: VerificationProgress, data: VerificationUpdate) -> VerificationProgress:
|
|
update_data = data.model_dump(exclude_unset=True)
|
|
if update_data:
|
|
await db.execute(
|
|
sa_update(VerificationProgress)
|
|
.where(VerificationProgress.id == vp.id)
|
|
.values(**update_data)
|
|
)
|
|
await db.commit()
|
|
await db.refresh(vp)
|
|
return vp
|