use sqlx::{PgPool, Row};
use uuid::Uuid;
use backbone_orm::company_scope::fetch_all_rows_scoped;
use crate::domain::repositories::hierarchy_repository::{
HierarchyNode, HierarchyRepository, HierarchyTable,
};
pub struct SqlxHierarchyRepository {
pool: PgPool,
}
impl SqlxHierarchyRepository {
pub fn new(pool: PgPool) -> Self {
Self { pool }
}
}
#[async_trait::async_trait]
impl HierarchyRepository for SqlxHierarchyRepository {
async fn ancestors(
&self,
table: HierarchyTable,
id: Uuid,
) -> anyhow::Result<Vec<HierarchyNode>> {
let sql = format!(
r#"WITH RECURSIVE chain AS (
SELECT id, parent_id, {code} AS code, name, level, 0 AS depth
FROM {table}
WHERE id = $1 AND (metadata->>'deleted_at') IS NULL
UNION ALL
SELECT t.id, t.parent_id, t.{code}, t.name, t.level, c.depth + 1
FROM {table} t JOIN chain c ON t.id = c.parent_id
WHERE (t.metadata->>'deleted_at') IS NULL
)
SELECT id, parent_id, code, name, level FROM chain ORDER BY depth DESC"#,
table = table.table(),
code = table.code_column(),
);
let rows = fetch_all_rows_scoped(&self.pool, sqlx::query(&sql).bind(id)).await?;
Ok(rows
.iter()
.map(|r| HierarchyNode {
id: r.get("id"),
parent_id: r.get("parent_id"),
code: r.get("code"),
name: r.get("name"),
level: r.get("level"),
})
.collect())
}
}