decision_cockpit 0.1.0

Layer — product decision memory with MCP tools and an embedded review dashboard
Documentation
use sqlx::PgPool;
use uuid::Uuid;

use crate::domain::memos::Memo;

pub struct NewMemo<'a> {
    pub title: &'a str,
    pub memo_type: &'a str,
    pub body_markdown: &'a str,
    pub status: &'a str,
}

pub struct MemoUpdate<'a> {
    pub title: &'a str,
    pub memo_type: &'a str,
    pub body_markdown: &'a str,
    pub status: &'a str,
}

pub async fn create(pool: &PgPool, new: NewMemo<'_>) -> Result<Memo, sqlx::Error> {
    let id = Uuid::new_v4();
    sqlx::query_as::<_, Memo>(
        r#"
        INSERT INTO memos (id, title, memo_type, body_markdown, status)
        VALUES ($1, $2, $3, $4, $5)
        RETURNING id, title, memo_type, body_markdown, status, created_at
        "#,
    )
    .bind(id)
    .bind(new.title)
    .bind(new.memo_type)
    .bind(new.body_markdown)
    .bind(new.status)
    .fetch_one(pool)
    .await
}

pub async fn update(
    pool: &PgPool,
    id: Uuid,
    upd: MemoUpdate<'_>,
) -> Result<Option<Memo>, sqlx::Error> {
    sqlx::query_as::<_, Memo>(
        r#"
        UPDATE memos
        SET title = $2, memo_type = $3, body_markdown = $4, status = $5
        WHERE id = $1
        RETURNING id, title, memo_type, body_markdown, status, created_at
        "#,
    )
    .bind(id)
    .bind(upd.title)
    .bind(upd.memo_type)
    .bind(upd.body_markdown)
    .bind(upd.status)
    .fetch_optional(pool)
    .await
}

pub async fn get(pool: &PgPool, id: Uuid) -> Result<Option<Memo>, sqlx::Error> {
    sqlx::query_as::<_, Memo>(
        r#"
        SELECT id, title, memo_type, body_markdown, status, created_at
        FROM memos
        WHERE id = $1
        "#,
    )
    .bind(id)
    .fetch_optional(pool)
    .await
}

pub async fn list(pool: &PgPool, limit: i64) -> Result<Vec<Memo>, sqlx::Error> {
    sqlx::query_as::<_, Memo>(
        r#"
        SELECT id, title, memo_type, body_markdown, status, created_at
        FROM memos
        ORDER BY created_at DESC
        LIMIT $1
        "#,
    )
    .bind(limit)
    .fetch_all(pool)
    .await
}