headless_lms_models/library/agent_changesets/
summary.rs1use std::collections::HashMap;
4
5use utoipa::ToSchema;
6
7use crate::{
8 agent_changeset_entities::{self, ChangesetEntitySummary},
9 agent_changesets::{self, AgentChangeset},
10 prelude::*,
11};
12
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
16pub struct ChangesetSummary {
17 pub changeset: AgentChangeset,
18 pub entities: Vec<ChangesetEntitySummary>,
19 pub has_risky_changes: bool,
20 pub is_expiring_soon: bool,
21}
22
23pub async fn get_summaries(
25 conn: &mut PgConnection,
26 changesets: Vec<AgentChangeset>,
27) -> ModelResult<Vec<ChangesetSummary>> {
28 let ids: Vec<Uuid> = changesets.iter().map(|changeset| changeset.id).collect();
29 let mut entities_by_changeset: HashMap<Uuid, Vec<ChangesetEntitySummary>> = HashMap::new();
30 for (changeset_id, entity) in
31 agent_changeset_entities::get_summaries_by_changeset_ids(conn, &ids).await?
32 {
33 entities_by_changeset
34 .entry(changeset_id)
35 .or_default()
36 .push(entity);
37 }
38 let now = Utc::now();
39 Ok(changesets
40 .into_iter()
41 .map(|changeset| {
42 let entities = entities_by_changeset
43 .remove(&changeset.id)
44 .unwrap_or_default();
45 ChangesetSummary {
46 has_risky_changes: entities.iter().any(|e| !e.risk_reasons.is_empty()),
47 is_expiring_soon: changeset.is_expiring_soon(now),
48 changeset,
49 entities,
50 }
51 })
52 .collect())
53}
54
55pub async fn get_summaries_for_user(
57 conn: &mut PgConnection,
58 user_id: Uuid,
59 course_id: Uuid,
60) -> ModelResult<Vec<ChangesetSummary>> {
61 let changesets = agent_changesets::get_by_user_and_course(conn, user_id, course_id).await?;
62 get_summaries(conn, changesets).await
63}