diff --git a/Cargo.toml b/Cargo.toml index ea73af6..47da750 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ tokio = { version = "1", features = ["macros", "rt-multi-thread"] } tokio-cron-scheduler = { version = "0" } uuid = { version = "0", features = ["serde", "v4", "v5"] } -beteran-protobuf-rust = { git = "https://gitlab.loafle.net/bet/beteran-protobuf-rust.git", tag = "v0.1.96-snapshot" } -beteran-common-rust = { git = "https://gitlab.loafle.net/bet/beteran-common-rust.git", tag = "v0.1.82-snapshot" } +beteran-protobuf-rust = { git = "https://gitlab.loafle.net/bet/beteran-protobuf-rust.git", tag = "v0.1.97-snapshot" } +beteran-common-rust = { git = "https://gitlab.loafle.net/bet/beteran-common-rust.git", tag = "v0.1.83-snapshot" } [build-dependencies] diff --git a/src/compositions/member/composition.rs b/src/compositions/member/composition.rs index 827822f..8dd7e18 100644 --- a/src/compositions/member/composition.rs +++ b/src/compositions/member/composition.rs @@ -7,6 +7,31 @@ use beteran_common_rust as bcr; use diesel::{result::Error, sql_query, RunQueryDsl}; use std::fmt::Write; +static MEMBER_CHILDREN_COUNT_QUERY: &str = " +WITH RECURSIVE cte AS ( + SELECT + id, parent_member_id, 1::integer recursion_level + FROM + members + WHERE + parent_member_id = $1 + UNION ALL + SELECT + m.id, m.parent_member_id, cte.recursion_level +1 + FROM + members m + JOIN cte ON cte.id = m.parent_member_id + ) + SELECT + count(recursion_level) AS count_of_children + FROM + cte + group by + recursion_level + order by + recursion_level asc +"; + static MEMBER_PARENTS_QUERY: &str = " WITH RECURSIVE rec AS ( @@ -548,6 +573,7 @@ impl Composition { Ok(Some(models::from_member_model( &_m, self.select_parent(conn, _m.parent_member_id)?, + self.select_children_count(conn, _m.parent_member_id)?, ))) } @@ -584,9 +610,63 @@ impl Composition { Ok(Some(models::from_member_model( &_m, self.select_parent(conn, _m.parent_member_id)?, + self.select_children_count(conn, _m.parent_member_id)?, ))) } + /// + pub fn select_children_count( + &self, + conn: &diesel::PgConnection, + parent_member_id: Option, + ) -> Result, Error> { + use diesel::sql_types::BigInt; + + #[derive(QueryableByName)] + struct Count { + #[sql_type = "BigInt"] + count_of_children: i64, + } + + let parent_member_id = match parent_member_id { + Some(i) => i, + None => { + return Ok(vec![]); + } + }; + + let query = format!( + " + {} + ", + MEMBER_CHILDREN_COUNT_QUERY + ); + + let count_of_children = match sql_query(query) + .bind::(parent_member_id) + .get_results::(conn) + { + Ok(m) => m, + Err(e) => match e { + diesel::result::Error::NotFound => vec![], + _ => { + return Err(e); + } + }, + }; + + if count_of_children.is_empty() { + return Ok(vec![]); + } + + let mut p: Vec = vec![]; + for c in count_of_children { + p.push(c.count_of_children); + } + + Ok(p) + } + /// pub fn select_parent( &self, @@ -626,7 +706,11 @@ impl Composition { let mut p: Option = None; for m in members { - p = Some(models::from_member_model(&m, p)); + p = Some(models::from_member_model( + &m, + p, + self.select_children_count(conn, m.parent_member_id)?, + )); } Ok(p) @@ -920,6 +1004,7 @@ impl Composition { list.push(models::from_member_model( &_m, self.select_parent(conn, _m.parent_member_id)?, + self.select_children_count(conn, _m.parent_member_id)?, )); } diff --git a/src/compositions/member/models.rs b/src/compositions/member/models.rs index 47bca25..4b69667 100644 --- a/src/compositions/member/models.rs +++ b/src/compositions/member/models.rs @@ -212,6 +212,8 @@ pub struct MemberModel { /// pub parent_member: Option>, /// + pub children_count: Vec, + /// pub child_member_count: i64, /// pub mobile_phone_number: Option, @@ -235,7 +237,7 @@ pub struct MemberModel { pub deleted_at: Option, } -pub fn from_member_model(_m: &_MemberModel, p: Option) -> MemberModel { +pub fn from_member_model(_m: &_MemberModel, p: Option, c: Vec) -> MemberModel { MemberModel { id: _m.id, site: _m.site.clone(), @@ -246,6 +248,7 @@ pub fn from_member_model(_m: &_MemberModel, p: Option) -> MemberMod password: _m.password.clone(), nickname: _m.nickname.clone(), parent_member: p.map(Box::new), + children_count: c, child_member_count: _m.child_member_count, mobile_phone_number: _m.mobile_phone_number.clone(), state: _m.state, diff --git a/src/services/member/models.rs b/src/services/member/models.rs index a935f1e..15017bd 100644 --- a/src/services/member/models.rs +++ b/src/services/member/models.rs @@ -71,6 +71,7 @@ impl From<&compositions::member::models::MemberModel> for bpr::models::member::M .as_ref() .map(|v| Box::::from(v)), child_member_count: d.child_member_count as u64, + children_count: d.children_count.iter().map(|v| *v as u64).collect(), username: d.username.clone(), nickname: d.nickname.clone(), mobile_phone_number: d.mobile_phone_number.clone(), @@ -115,6 +116,7 @@ impl From<&Box> .as_ref() .map(|v| Box::::from(v)), child_member_count: d.child_member_count as u64, + children_count: d.children_count.iter().map(|v| *v as u64).collect(), username: d.username.clone(), nickname: d.nickname.clone(), mobile_phone_number: d.mobile_phone_number.clone(),