headless_lms_models/
credit_registration_daily_snapshots.rs1use chrono::NaiveDate;
6use utoipa::ToSchema;
7
8use crate::credit_registrations::CreditRegistrationState;
9use crate::prelude::*;
10
11#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, ToSchema)]
12pub struct CreditRegistrationDailySnapshot {
13 pub id: Uuid,
14 pub created_at: DateTime<Utc>,
15 pub updated_at: DateTime<Utc>,
16 pub deleted_at: Option<DateTime<Utc>>,
17 pub snapshot_date: NaiveDate,
18 pub state: CreditRegistrationState,
19 pub count: i32,
20 pub entered_count: i32,
21 pub left_count: i32,
22}
23
24#[derive(Debug, Clone, PartialEq)]
25pub struct DailyStateCounts {
26 pub state: CreditRegistrationState,
27 pub count: i32,
28 pub entered_count: i32,
29 pub left_count: i32,
30}
31
32pub async fn write_snapshot_for_date(
34 conn: &mut PgConnection,
35 snapshot_date: NaiveDate,
36 counts: &[DailyStateCounts],
37) -> ModelResult<()> {
38 for row in counts {
39 sqlx::query!(
40 r#"
41INSERT INTO credit_registration_daily_snapshots (
42 snapshot_date,
43 state,
44 count,
45 entered_count,
46 left_count
47 )
48VALUES ($1, $2, $3, $4, $5) ON CONFLICT (snapshot_date, state, deleted_at) DO
49UPDATE
50SET count = $3,
51 entered_count = $4,
52 left_count = $5
53 "#,
54 snapshot_date,
55 row.state as CreditRegistrationState,
56 row.count,
57 row.entered_count,
58 row.left_count,
59 )
60 .execute(&mut *conn)
61 .await?;
62 }
63 Ok(())
64}
65
66pub async fn get_between(
67 conn: &mut PgConnection,
68 from: NaiveDate,
69 to: NaiveDate,
70) -> ModelResult<Vec<CreditRegistrationDailySnapshot>> {
71 let res = sqlx::query_as!(
72 CreditRegistrationDailySnapshot,
73 r#"
74SELECT *
75FROM credit_registration_daily_snapshots
76WHERE snapshot_date BETWEEN $1 AND $2
77 AND deleted_at IS NULL
78ORDER BY snapshot_date,
79 state
80 "#,
81 from,
82 to,
83 )
84 .fetch_all(conn)
85 .await?;
86 Ok(res)
87}
88
89pub async fn get_series_for_state(
90 conn: &mut PgConnection,
91 state: CreditRegistrationState,
92 from: NaiveDate,
93 to: NaiveDate,
94) -> ModelResult<Vec<CreditRegistrationDailySnapshot>> {
95 let res = sqlx::query_as!(
96 CreditRegistrationDailySnapshot,
97 r#"
98SELECT *
99FROM credit_registration_daily_snapshots
100WHERE state = $1
101 AND snapshot_date BETWEEN $2 AND $3
102 AND deleted_at IS NULL
103ORDER BY snapshot_date
104 "#,
105 state as CreditRegistrationState,
106 from,
107 to,
108 )
109 .fetch_all(conn)
110 .await?;
111 Ok(res)
112}