sqlx_ledger/account/
repo.rs1use serde::Serialize;
2use sqlx::{Pool, Postgres, Transaction};
3use tracing::instrument;
4
5use super::entity::*;
6use crate::{error::*, primitives::*};
7
8#[derive(Debug, Clone)]
10pub struct Accounts {
11 pool: Pool<Postgres>,
12}
13
14impl Accounts {
15 pub fn new(pool: &Pool<Postgres>) -> Self {
16 Self { pool: pool.clone() }
17 }
18
19 pub async fn create(&self, new_account: NewAccount) -> Result<AccountId, SqlxLedgerError> {
20 let mut tx = self.pool.begin().await?;
21 let res = self.create_in_tx(&mut tx, new_account).await?;
22 tx.commit().await?;
23 Ok(res)
24 }
25
26 #[instrument(name = "sqlx_ledger.accounts.create", skip(self, tx))]
27 pub async fn create_in_tx<'a>(
28 &self,
29 tx: &mut Transaction<'a, Postgres>,
30 new_account: NewAccount,
31 ) -> Result<AccountId, SqlxLedgerError> {
32 let NewAccount {
33 id,
34 code,
35 name,
36 normal_balance_type,
37 description,
38 status,
39 metadata,
40 } = new_account;
41 let record = sqlx::query!(
42 r#"INSERT INTO sqlx_ledger_accounts (id, code, name, normal_balance_type, description, status, metadata)
43 VALUES ($1, $2, $3, $4, $5, $6, $7)
44 RETURNING id, version, created_at"#,
45 id as AccountId,
46 code,
47 name,
48 normal_balance_type as DebitOrCredit,
49 description,
50 status as Status,
51 metadata
52 )
53 .fetch_one(&mut **tx)
54 .await?;
55 Ok(AccountId::from(record.id))
56 }
57
58 #[instrument(name = "sqlx_ledger.accounts.update", skip(self))]
59 pub async fn update<T: Serialize + std::fmt::Debug>(
60 &self,
61 id: AccountId,
62 description: Option<String>,
63 metadata: Option<T>,
64 ) -> Result<AccountId, SqlxLedgerError> {
65 let metadata_json = match metadata {
66 Some(m) => Some(serde_json::to_value(m)?),
67 None => None,
68 };
69 sqlx::query_file!(
70 "src/account/sql/update-account.sql",
71 id as AccountId,
72 description,
73 metadata_json
74 )
75 .execute(&self.pool)
76 .await?;
77 Ok(id)
78 }
79
80 #[instrument(name = "sqlx_ledger.accounts.find_by_code", skip(self))]
81 pub async fn find_by_code(&self, code: &str) -> Result<Option<AccountId>, SqlxLedgerError> {
82 let record = sqlx::query!(
83 r#"SELECT id FROM sqlx_ledger_accounts WHERE code = $1 LIMIT 1"#,
84 code
85 )
86 .fetch_optional(&self.pool)
87 .await?;
88 Ok(record.map(|r| AccountId::from(r.id)))
89 }
90}