amazon-transcreation/backend/app/services/output_service.py
DJP 8b07a59da0 fix: persist feedback/comments across page reloads on review page
Feedback was saving to DB but never loaded back on page revisit.
Three-point fix:
- Backend schema: add feedback list to OutputRowResponse
- Backend service: eagerly load feedback relationship in preview query
- Frontend mapper: map latest feedback entry to OutputRow.feedback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 16:54:49 -04:00

105 lines
3.1 KiB
Python

from uuid import UUID
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from app.models.job import LocaleInstance
from app.models.output import OutputRow
from app.models.source import SourceLine
from app.schemas.output import (
OutputPreviewResponse,
OutputRowResponse,
SourceLinePreview,
)
class OutputService:
"""Service for assembling output preview data and triggering exports."""
async def get_preview(
self,
db: AsyncSession,
job_id: UUID,
locale_code: str,
) -> OutputPreviewResponse | None:
"""Assemble output preview data for a specific locale instance."""
# Get the locale instance
result = await db.execute(
select(LocaleInstance)
.where(
LocaleInstance.job_id == job_id,
LocaleInstance.locale_code == locale_code,
)
)
instance = result.scalar_one_or_none()
if instance is None:
return None
# Get source lines
source_result = await db.execute(
select(SourceLine)
.where(SourceLine.job_id == job_id)
.order_by(SourceLine.row_order)
)
source_lines = [
SourceLinePreview.model_validate(sl)
for sl in source_result.scalars().all()
]
# Get output rows with feedback eagerly loaded
output_result = await db.execute(
select(OutputRow)
.where(OutputRow.instance_id == instance.id)
.order_by(OutputRow.row_order)
.options(selectinload(OutputRow.feedback))
)
output_rows = [
OutputRowResponse.model_validate(row)
for row in output_result.scalars().all()
]
return OutputPreviewResponse(
locale_code=locale_code,
instance_id=instance.id,
source_lines=source_lines,
output_rows=output_rows,
total_rows=len(output_rows),
)
async def get_output_rows(
self,
db: AsyncSession,
instance_id: UUID,
) -> list[OutputRow]:
"""Get all output rows for a locale instance."""
result = await db.execute(
select(OutputRow)
.where(OutputRow.instance_id == instance_id)
.order_by(OutputRow.row_order)
)
return list(result.scalars().all())
async def trigger_export(
self,
db: AsyncSession,
job_id: UUID,
locale_code: str,
) -> str | None:
"""Trigger export generation for a locale and return the file path."""
result = await db.execute(
select(LocaleInstance)
.where(
LocaleInstance.job_id == job_id,
LocaleInstance.locale_code == locale_code,
)
)
instance = result.scalar_one_or_none()
if instance is None:
return None
if instance.output_file_path:
return instance.output_file_path
# Export would be triggered here; for now return None indicating no export yet
return None