Task 008 implement boundary questions loop
This commit is contained in:
@@ -14,6 +14,7 @@ from src.domain.contracts import (
|
||||
AgentJobSummary,
|
||||
AgentJobType,
|
||||
ArticleSummary,
|
||||
BoundaryQuestionSummary,
|
||||
PublishingRules,
|
||||
PublishingStatus,
|
||||
ArticleWorkflowStatus,
|
||||
@@ -40,6 +41,7 @@ class BackendRepository:
|
||||
self.users = UsersRepository(self)
|
||||
self.target_sites = TargetSitesRepository(self)
|
||||
self.articles = ArticlesRepository(self)
|
||||
self.boundary_questions = BoundaryQuestionsRepository(self)
|
||||
self.agent_jobs = AgentJobsRepository(self)
|
||||
self.script_config_versions = ScriptConfigVersionsRepository(self)
|
||||
self.script_config_version_events = ScriptConfigVersionAuditEventsRepository(self)
|
||||
@@ -519,6 +521,26 @@ class ArticlesRepository:
|
||||
raise LookupError(f"Article not found: {article_id}")
|
||||
return _article_summary_from_row(row)
|
||||
|
||||
def update_status(
|
||||
self,
|
||||
*,
|
||||
article_id: UUID,
|
||||
status: ArticleWorkflowStatus,
|
||||
updated_at: datetime,
|
||||
) -> ArticleSummary:
|
||||
placeholder = self._repository.placeholder()
|
||||
with self._repository.connection() as connection:
|
||||
connection.execute(
|
||||
f"""
|
||||
UPDATE articles
|
||||
SET status = {placeholder}, updated_at = {placeholder}
|
||||
WHERE id = {placeholder}
|
||||
""",
|
||||
(status.value, _datetime_value(updated_at), str(article_id)),
|
||||
)
|
||||
|
||||
return self.get(article_id)
|
||||
|
||||
def create_workflow_event(
|
||||
self,
|
||||
*,
|
||||
@@ -593,6 +615,141 @@ class ArticlesRepository:
|
||||
return [_workflow_event_from_row(row) for row in rows]
|
||||
|
||||
|
||||
class BoundaryQuestionsRepository:
|
||||
def __init__(self, repository: BackendRepository) -> None:
|
||||
self._repository = repository
|
||||
|
||||
def replace_for_article(
|
||||
self,
|
||||
*,
|
||||
article_id: UUID,
|
||||
questions: list[JsonObject],
|
||||
created_at: datetime,
|
||||
) -> list[BoundaryQuestionSummary]:
|
||||
placeholder = self._repository.placeholder()
|
||||
with self._repository.connection() as connection:
|
||||
connection.execute(
|
||||
f"DELETE FROM boundary_questions WHERE article_id = {placeholder}",
|
||||
(str(article_id),),
|
||||
)
|
||||
for question in questions:
|
||||
connection.execute(
|
||||
f"""
|
||||
INSERT INTO boundary_questions (
|
||||
id,
|
||||
article_id,
|
||||
sort_order,
|
||||
category,
|
||||
question,
|
||||
answer,
|
||||
is_required,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (
|
||||
{placeholder},
|
||||
{placeholder},
|
||||
{placeholder},
|
||||
{placeholder},
|
||||
{placeholder},
|
||||
{placeholder},
|
||||
{placeholder},
|
||||
{placeholder},
|
||||
{placeholder}
|
||||
)
|
||||
""",
|
||||
(
|
||||
str(uuid4()),
|
||||
str(article_id),
|
||||
question["sort_order"],
|
||||
question["category"],
|
||||
question["question"],
|
||||
question.get("answer"),
|
||||
_bool_value(question.get("is_required", True)),
|
||||
_datetime_value(created_at),
|
||||
_datetime_value(created_at),
|
||||
),
|
||||
)
|
||||
|
||||
return self.list_for_article(article_id)
|
||||
|
||||
def list_for_article(self, article_id: UUID) -> list[BoundaryQuestionSummary]:
|
||||
placeholder = self._repository.placeholder()
|
||||
with self._repository.connection() as connection:
|
||||
rows = connection.execute(
|
||||
f"""
|
||||
SELECT
|
||||
id,
|
||||
article_id,
|
||||
sort_order,
|
||||
category,
|
||||
question,
|
||||
answer,
|
||||
is_required,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM boundary_questions
|
||||
WHERE article_id = {placeholder}
|
||||
ORDER BY sort_order
|
||||
""",
|
||||
(str(article_id),),
|
||||
).fetchall()
|
||||
|
||||
return [_boundary_question_from_row(row) for row in rows]
|
||||
|
||||
def get(self, *, article_id: UUID, question_id: UUID) -> BoundaryQuestionSummary:
|
||||
placeholder = self._repository.placeholder()
|
||||
with self._repository.connection() as connection:
|
||||
row = connection.execute(
|
||||
f"""
|
||||
SELECT
|
||||
id,
|
||||
article_id,
|
||||
sort_order,
|
||||
category,
|
||||
question,
|
||||
answer,
|
||||
is_required,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM boundary_questions
|
||||
WHERE article_id = {placeholder} AND id = {placeholder}
|
||||
""",
|
||||
(str(article_id), str(question_id)),
|
||||
).fetchone()
|
||||
|
||||
if row is None:
|
||||
raise LookupError(f"Boundary question not found: {question_id}")
|
||||
return _boundary_question_from_row(row)
|
||||
|
||||
def update_answer(
|
||||
self,
|
||||
*,
|
||||
article_id: UUID,
|
||||
question_id: UUID,
|
||||
answer: str | None,
|
||||
updated_at: datetime,
|
||||
) -> BoundaryQuestionSummary:
|
||||
self.get(article_id=article_id, question_id=question_id)
|
||||
placeholder = self._repository.placeholder()
|
||||
with self._repository.connection() as connection:
|
||||
connection.execute(
|
||||
f"""
|
||||
UPDATE boundary_questions
|
||||
SET answer = {placeholder}, updated_at = {placeholder}
|
||||
WHERE article_id = {placeholder} AND id = {placeholder}
|
||||
""",
|
||||
(
|
||||
answer,
|
||||
_datetime_value(updated_at),
|
||||
str(article_id),
|
||||
str(question_id),
|
||||
),
|
||||
)
|
||||
|
||||
return self.get(article_id=article_id, question_id=question_id)
|
||||
|
||||
|
||||
class AgentJobsRepository:
|
||||
def __init__(self, repository: BackendRepository) -> None:
|
||||
self._repository = repository
|
||||
@@ -1247,6 +1404,20 @@ def _workflow_event_from_row(row: Any) -> WorkflowEventSummary:
|
||||
)
|
||||
|
||||
|
||||
def _boundary_question_from_row(row: Any) -> BoundaryQuestionSummary:
|
||||
return BoundaryQuestionSummary(
|
||||
id=_row_value(row, "id"),
|
||||
article_id=_row_value(row, "article_id"),
|
||||
sort_order=_row_value(row, "sort_order"),
|
||||
category=_row_value(row, "category"),
|
||||
question=_row_value(row, "question"),
|
||||
answer=_row_value(row, "answer"),
|
||||
is_required=bool(_row_value(row, "is_required")),
|
||||
created_at=_row_value(row, "created_at"),
|
||||
updated_at=_row_value(row, "updated_at"),
|
||||
)
|
||||
|
||||
|
||||
def _agent_job_summary_from_row(row: Any) -> AgentJobSummary:
|
||||
return AgentJobSummary(
|
||||
id=_row_value(row, "id"),
|
||||
@@ -1331,6 +1502,10 @@ def _datetime_value(value: datetime | None) -> str | None:
|
||||
return value.isoformat()
|
||||
|
||||
|
||||
def _bool_value(value: bool) -> bool:
|
||||
return bool(value)
|
||||
|
||||
|
||||
def _article_status_value(value: ArticleWorkflowStatus | None) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user