sqlx_ledger/account/
entity.rs

1use chrono::{DateTime, Utc};
2use derive_builder::Builder;
3
4use crate::primitives::*;
5
6/// Representation of a ledger account entity.
7pub struct Account<M> {
8    pub id: AccountId,
9    pub code: String,
10    pub name: String,
11    pub normal_balance_type: DebitOrCredit,
12    pub description: Option<String>,
13    pub status: Status,
14    pub metadata: Option<M>,
15    pub version: u32,
16    pub modified_at: DateTime<Utc>,
17    pub created_at: DateTime<Utc>,
18}
19
20/// Representation of a ***new*** ledger account entity with required/optional properties and a builder.
21#[derive(Builder, Debug)]
22pub struct NewAccount {
23    #[builder(setter(into))]
24    pub id: AccountId,
25    #[builder(setter(into))]
26    pub(super) code: String,
27    #[builder(setter(into))]
28    pub(super) name: String,
29    #[builder(default)]
30    pub(super) normal_balance_type: DebitOrCredit,
31    #[builder(setter(strip_option, into), default)]
32    pub(super) description: Option<String>,
33    #[builder(default)]
34    pub(super) status: Status,
35    #[builder(setter(custom), default)]
36    pub(super) metadata: Option<serde_json::Value>,
37}
38
39impl NewAccount {
40    pub fn builder() -> NewAccountBuilder {
41        NewAccountBuilder::default()
42    }
43}
44
45impl NewAccountBuilder {
46    pub fn metadata<T: serde::Serialize>(
47        &mut self,
48        metadata: T,
49    ) -> Result<&mut Self, serde_json::Error> {
50        self.metadata = Some(Some(serde_json::to_value(metadata)?));
51        Ok(self)
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[test]
60    fn it_builds() {
61        let new_account = NewAccount::builder()
62            .id(uuid::Uuid::new_v4())
63            .code("code")
64            .name("name")
65            .build()
66            .unwrap();
67        assert_eq!(new_account.code, "code");
68        assert_eq!(new_account.name, "name");
69        assert_eq!(new_account.normal_balance_type, DebitOrCredit::Credit);
70        assert_eq!(new_account.description, None);
71        assert_eq!(new_account.status, Status::Active);
72        assert_eq!(new_account.metadata, None);
73    }
74
75    #[test]
76    fn fails_when_mandatory_fields_are_missing() {
77        let new_account = NewAccount::builder().build();
78        assert!(new_account.is_err());
79    }
80
81    #[test]
82    fn accepts_metadata() {
83        use serde_json::json;
84        let new_account = NewAccount::builder()
85            .id(uuid::Uuid::new_v4())
86            .code("code")
87            .name("name")
88            .metadata(json!({"foo": "bar"}))
89            .unwrap()
90            .build()
91            .unwrap();
92        assert_eq!(new_account.metadata, Some(json!({"foo": "bar"})));
93    }
94}