현재 작업 전체 반영
This commit is contained in:
parent
5560638e54
commit
c0dddab594
85 changed files with 11322 additions and 539 deletions
|
|
@ -60,6 +60,12 @@ class PersonaReviewItem:
|
|||
approved_at: str | None
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class PersonaDraftRecord:
|
||||
review: PersonaReviewItem
|
||||
card: PersonaCard
|
||||
|
||||
|
||||
def seed_persona_id(code: str) -> str:
|
||||
return str(uuid.uuid5(uuid.NAMESPACE_URL, f"vignette:persona:{code.upper()}"))
|
||||
|
||||
|
|
@ -143,6 +149,13 @@ def persona_review_item_from_row(row: Any) -> PersonaReviewItem:
|
|||
)
|
||||
|
||||
|
||||
def persona_draft_record_from_row(row: Any) -> PersonaDraftRecord:
|
||||
return PersonaDraftRecord(
|
||||
review=persona_review_item_from_row(row),
|
||||
card=card_from_row(row),
|
||||
)
|
||||
|
||||
|
||||
def seed_fallback_persona(code: str) -> CatalogPersona | None:
|
||||
card = get_seed_persona(code)
|
||||
if card is None:
|
||||
|
|
@ -300,6 +313,187 @@ async def list_persona_review_queue(
|
|||
return [persona_review_item_from_row(row) for row in rows]
|
||||
|
||||
|
||||
async def get_persona_draft_record(
|
||||
*,
|
||||
persona_id: str,
|
||||
role: str,
|
||||
) -> PersonaDraftRecord | None:
|
||||
if role not in {"teacher", "admin"}:
|
||||
raise ValueError("persona draft read requires teacher or admin role")
|
||||
|
||||
get_pool()
|
||||
async with acquire(role=role) as conn:
|
||||
row = await conn.fetchrow(
|
||||
f"""
|
||||
SELECT {_CARD_COLUMNS}, created_at, approved_at
|
||||
FROM app.persona_card
|
||||
WHERE persona_id = $1::uuid
|
||||
AND status IN ('draft', 'review')
|
||||
LIMIT 1
|
||||
""",
|
||||
persona_id,
|
||||
)
|
||||
return persona_draft_record_from_row(row) if row is not None else None
|
||||
|
||||
|
||||
async def create_persona_draft(
|
||||
*,
|
||||
card: PersonaCard,
|
||||
author_id: str,
|
||||
role: str,
|
||||
submit_for_review: bool = False,
|
||||
) -> PersonaReviewItem:
|
||||
if role not in {"teacher", "admin"}:
|
||||
raise ValueError("persona draft creation requires teacher or admin role")
|
||||
|
||||
next_status = "review" if submit_for_review else "draft"
|
||||
persona_id = str(uuid.uuid4())
|
||||
get_pool()
|
||||
async with acquire(role=role, user_id=author_id) as conn:
|
||||
version = await conn.fetchval(
|
||||
"""
|
||||
SELECT COALESCE(MAX(version), 0) + 1
|
||||
FROM app.persona_card
|
||||
WHERE upper(code) = upper($1)
|
||||
""",
|
||||
card.code,
|
||||
)
|
||||
row = await conn.fetchrow(
|
||||
f"""
|
||||
INSERT INTO app.persona_card (
|
||||
persona_id, code, version, status, display_name, difficulty,
|
||||
theory_target, demographics, presenting, history, big5,
|
||||
resistance, speech_style, affect_baseline, ccd,
|
||||
dsm5_dimensional, source_provenance, is_synthetic, created_by
|
||||
)
|
||||
VALUES (
|
||||
$1::uuid, $2, $3, $4, $5, $6,
|
||||
$7::text[], $8::jsonb, $9::jsonb, $10::jsonb, $11::jsonb,
|
||||
$12::jsonb, $13::jsonb, $14::jsonb, $15::jsonb,
|
||||
$16::jsonb, $17, $18, $19::uuid
|
||||
)
|
||||
RETURNING {_REVIEW_COLUMNS}
|
||||
""",
|
||||
persona_id,
|
||||
card.code,
|
||||
int(version or 1),
|
||||
next_status,
|
||||
card.display_name,
|
||||
card.difficulty,
|
||||
card.theory_target,
|
||||
card.demographics,
|
||||
card.presenting,
|
||||
card.history,
|
||||
card.big5,
|
||||
card.resistance,
|
||||
card.speech_style,
|
||||
card.affect_baseline,
|
||||
card.ccd,
|
||||
card.dsm5_dimensional,
|
||||
card.source_provenance,
|
||||
card.is_synthetic,
|
||||
author_id,
|
||||
)
|
||||
await conn.execute(
|
||||
"""
|
||||
INSERT INTO audit.audit_log (
|
||||
actor_uid, action, target_kind, target_id, detail
|
||||
)
|
||||
VALUES ($1::uuid, $2, $3, $4, $5::jsonb)
|
||||
""",
|
||||
author_id,
|
||||
"persona_draft_create",
|
||||
"persona_card",
|
||||
persona_id,
|
||||
{
|
||||
"next_status": next_status,
|
||||
"code": card.code,
|
||||
"version": int(row["version"]),
|
||||
},
|
||||
)
|
||||
return persona_review_item_from_row(row)
|
||||
|
||||
|
||||
async def update_persona_draft(
|
||||
*,
|
||||
persona_id: str,
|
||||
card: PersonaCard,
|
||||
author_id: str,
|
||||
role: str,
|
||||
submit_for_review: bool = False,
|
||||
) -> PersonaReviewItem | None:
|
||||
if role not in {"teacher", "admin"}:
|
||||
raise ValueError("persona draft update requires teacher or admin role")
|
||||
|
||||
next_status = "review" if submit_for_review else "draft"
|
||||
get_pool()
|
||||
async with acquire(role=role, user_id=author_id) as conn:
|
||||
row = await conn.fetchrow(
|
||||
f"""
|
||||
UPDATE app.persona_card
|
||||
SET
|
||||
code = $2,
|
||||
status = $3,
|
||||
display_name = $4,
|
||||
difficulty = $5,
|
||||
theory_target = $6::text[],
|
||||
demographics = $7::jsonb,
|
||||
presenting = $8::jsonb,
|
||||
history = $9::jsonb,
|
||||
big5 = $10::jsonb,
|
||||
resistance = $11::jsonb,
|
||||
speech_style = $12::jsonb,
|
||||
affect_baseline = $13::jsonb,
|
||||
ccd = $14::jsonb,
|
||||
dsm5_dimensional = $15::jsonb,
|
||||
source_provenance = $16,
|
||||
is_synthetic = $17,
|
||||
approved_by = NULL,
|
||||
approved_at = NULL
|
||||
WHERE persona_id = $1::uuid
|
||||
AND status IN ('draft', 'review')
|
||||
RETURNING {_REVIEW_COLUMNS}
|
||||
""",
|
||||
persona_id,
|
||||
card.code,
|
||||
next_status,
|
||||
card.display_name,
|
||||
card.difficulty,
|
||||
card.theory_target,
|
||||
card.demographics,
|
||||
card.presenting,
|
||||
card.history,
|
||||
card.big5,
|
||||
card.resistance,
|
||||
card.speech_style,
|
||||
card.affect_baseline,
|
||||
card.ccd,
|
||||
card.dsm5_dimensional,
|
||||
card.source_provenance,
|
||||
card.is_synthetic,
|
||||
)
|
||||
if row is None:
|
||||
return None
|
||||
await conn.execute(
|
||||
"""
|
||||
INSERT INTO audit.audit_log (
|
||||
actor_uid, action, target_kind, target_id, detail
|
||||
)
|
||||
VALUES ($1::uuid, $2, $3, $4, $5::jsonb)
|
||||
""",
|
||||
author_id,
|
||||
"persona_draft_update",
|
||||
"persona_card",
|
||||
persona_id,
|
||||
{
|
||||
"next_status": next_status,
|
||||
"code": str(row["code"]).upper(),
|
||||
"version": int(row["version"]),
|
||||
},
|
||||
)
|
||||
return persona_review_item_from_row(row)
|
||||
|
||||
|
||||
async def update_persona_review_status(
|
||||
*,
|
||||
persona_id: str,
|
||||
|
|
@ -375,21 +569,26 @@ async def get_catalog_persona(code: str) -> CatalogPersona | None:
|
|||
|
||||
__all__ = [
|
||||
"CatalogPersona",
|
||||
"PersonaDraftRecord",
|
||||
"PersonaReviewItem",
|
||||
"PersonaReviewAction",
|
||||
"PersonaStatus",
|
||||
"SEED_VERSION",
|
||||
"card_from_row",
|
||||
"catalog_persona_from_row",
|
||||
"create_persona_draft",
|
||||
"get_approved_persona",
|
||||
"get_catalog_persona",
|
||||
"get_persona_draft_record",
|
||||
"list_approved_personas",
|
||||
"list_catalog_personas",
|
||||
"list_persona_review_queue",
|
||||
"materialize_seed_personas",
|
||||
"persona_draft_record_from_row",
|
||||
"persona_review_item_from_row",
|
||||
"seed_fallback_persona",
|
||||
"seed_fallback_personas",
|
||||
"seed_persona_id",
|
||||
"update_persona_draft",
|
||||
"update_persona_review_status",
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue