| from __future__ import annotations |
|
|
| from sqlalchemy import delete, select, update |
| from sqlalchemy.orm import Session |
|
|
| from app.models.chat_session import ChatSession |
| from app.models.document import Document |
| from app.models.flashcard import FlashcardSet |
| from app.models.generation import Generation |
| from app.models.generation_cache import GenerationCache |
| from app.models.learning_state import GeneratedResource |
| from app.models.previous_paper import PreviousPaper |
| from app.models.quiz import Quiz |
| from app.models.study_profile import StudyProfile |
| from app.models.syllabus_item import SyllabusItem |
| from app.models.video_render_job import VideoRenderJob |
| from app.services.file_storage import delete_upload_file |
|
|
|
|
| def delete_document_and_derivatives(db: Session, document: Document) -> None: |
| """Delete one document and all account data derived directly from it. |
| |
| Callers must perform ownership checks before invoking this service. Database |
| changes are committed together, then the physical upload is removed. A |
| rendered video is allowed to outlive its source, but its source reference is |
| cleared so no stale document link remains. |
| """ |
|
|
| document_id = document.id |
| user_id = document.user_id |
| file_path = document.file_path |
|
|
| db.execute(delete(Generation).where(Generation.document_id == document_id)) |
| db.execute(delete(Quiz).where(Quiz.document_id == document_id)) |
| db.execute( |
| delete(FlashcardSet).where(FlashcardSet.document_id == document_id), |
| ) |
| db.execute( |
| delete(SyllabusItem) |
| .where(SyllabusItem.user_id == user_id) |
| .where(SyllabusItem.source_id == document_id), |
| ) |
| db.execute( |
| delete(GeneratedResource) |
| .where(GeneratedResource.user_id == user_id) |
| .where(GeneratedResource.source_id == document_id), |
| ) |
|
|
| |
| |
| |
| previous_papers = db.scalars( |
| select(PreviousPaper) |
| .where(PreviousPaper.user_id == user_id) |
| .where(PreviousPaper.file_path == file_path), |
| ).all() |
| for paper in previous_papers: |
| db.delete(paper) |
|
|
| linked_sessions = db.scalars( |
| select(ChatSession) |
| .where(ChatSession.user_id == user_id) |
| .where(ChatSession.source_id == document_id), |
| ).all() |
| for session in linked_sessions: |
| db.delete(session) |
|
|
| |
| |
| |
| for cache_row in db.scalars(select(GenerationCache)).all(): |
| metadata = cache_row.metadata_json or {} |
| if ( |
| metadata.get("document_id") == document_id |
| or document_id in cache_row.cache_key |
| ): |
| db.delete(cache_row) |
|
|
| db.execute( |
| update(VideoRenderJob) |
| .where(VideoRenderJob.source_document_id == document_id) |
| .values(source_document_id=None), |
| ) |
| db.execute( |
| update(StudyProfile) |
| .where(StudyProfile.uploaded_document_id == document_id) |
| .values(uploaded_document_id=None), |
| ) |
|
|
| db.delete(document) |
| db.commit() |
| delete_upload_file(file_path) |
|
|