1use crate::prelude::*;
2use utoipa::ToSchema;
3
4#[derive(Debug, Serialize, ToSchema)]
5
6pub struct Term {
7 pub id: Uuid,
8 pub created_at: DateTime<Utc>,
9 pub updated_at: DateTime<Utc>,
10 pub deleted_at: Option<DateTime<Utc>>,
11 pub term: String,
12 pub definition: String,
13 pub course_id: Uuid,
14}
15
16#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, ToSchema)]
17pub struct GlossaryTerm {
18 pub id: Uuid,
19 pub created_at: DateTime<Utc>,
20 pub updated_at: DateTime<Utc>,
21 pub deleted_at: Option<DateTime<Utc>>,
22 pub term: String,
23 pub definition: String,
24 pub course_id: Uuid,
25}
26
27#[derive(Debug, Deserialize, ToSchema)]
28
29pub struct TermUpdate {
30 pub term: String,
31 pub definition: String,
32}
33
34pub async fn insert(
35 conn: &mut PgConnection,
36 term: &str,
37 definition: &str,
38 course_id: Uuid,
39) -> ModelResult<Uuid> {
40 let res = sqlx::query!(
41 "
42INSERT INTO glossary (term, definition, course_id)
43SELECT $1, $2, $3
44RETURNING *
45",
46 term,
47 definition,
48 course_id
49 )
50 .fetch_one(conn)
51 .await?;
52 Ok(res.id)
53}
54
55pub async fn update(
56 conn: &mut PgConnection,
57 id: Uuid,
58 term: &str,
59 definition: &str,
60) -> ModelResult<()> {
61 sqlx::query!(
62 "
63UPDATE glossary
64SET term = $1,
65 definition = $2
66WHERE id = $3
67",
68 term,
69 definition,
70 id
71 )
72 .execute(conn)
73 .await?;
74 Ok(())
75}
76
77pub async fn get_term_by_id(conn: &mut PgConnection, id: Uuid) -> ModelResult<GlossaryTerm> {
78 let res = sqlx::query_as!(
79 GlossaryTerm,
80 "
81SELECT *
82FROM glossary
83WHERE id = $1
84 AND deleted_at IS NULL
85 ",
86 id
87 )
88 .fetch_one(conn)
89 .await?;
90 Ok(res)
91}
92
93pub async fn update_term_by_id_and_course_id(
94 conn: &mut PgConnection,
95 id: Uuid,
96 course_id: Uuid,
97 term: &str,
98 definition: &str,
99) -> ModelResult<GlossaryTerm> {
100 let res = sqlx::query_as!(
101 GlossaryTerm,
102 "
103UPDATE glossary
104SET term = $1,
105 definition = $2
106WHERE id = $3
107 AND course_id = $4
108 AND deleted_at IS NULL
109RETURNING *
110 ",
111 term,
112 definition,
113 id,
114 course_id
115 )
116 .fetch_one(conn)
117 .await?;
118 Ok(res)
119}
120
121pub async fn delete(conn: &mut PgConnection, id: Uuid) -> ModelResult<()> {
122 sqlx::query!(
123 "
124UPDATE glossary
125SET deleted_at = now()
126WHERE id = $1
127AND deleted_at IS NULL
128",
129 id
130 )
131 .execute(conn)
132 .await?;
133 Ok(())
134}
135
136pub async fn delete_term_by_id_and_course_id(
137 conn: &mut PgConnection,
138 id: Uuid,
139 course_id: Uuid,
140) -> ModelResult<GlossaryTerm> {
141 let res = sqlx::query_as!(
142 GlossaryTerm,
143 "
144UPDATE glossary
145SET deleted_at = now()
146WHERE id = $1
147 AND course_id = $2
148 AND deleted_at IS NULL
149RETURNING *
150 ",
151 id,
152 course_id
153 )
154 .fetch_one(conn)
155 .await?;
156 Ok(res)
157}
158
159pub async fn fetch_for_course(conn: &mut PgConnection, course_id: Uuid) -> ModelResult<Vec<Term>> {
160 let res = sqlx::query_as!(
161 Term,
162 "
163SELECT *
164FROM glossary
165WHERE glossary.course_id = $1
166AND deleted_at IS NULL
167",
168 course_id
169 )
170 .fetch_all(conn)
171 .await?;
172 Ok(res)
173}
174
175pub async fn get_by_ids(conn: &mut PgConnection, ids: &[Uuid]) -> ModelResult<Vec<Term>> {
177 let res = sqlx::query_as!(
178 Term,
179 "
180SELECT *
181FROM glossary
182WHERE id = ANY($1)
183 AND deleted_at IS NULL
184",
185 ids
186 )
187 .fetch_all(conn)
188 .await?;
189 Ok(res)
190}
191
192pub async fn upsert_from_snapshot(
195 conn: &mut PgConnection,
196 snapshot: &crate::library::entity_snapshots::GlossaryTermSnapshot,
197) -> ModelResult<()> {
198 sqlx::query!(
199 "
200INSERT INTO glossary (id, course_id, term, definition)
201VALUES ($1, $2, $3, $4) ON CONFLICT (id) DO
202UPDATE
203SET term = EXCLUDED.term,
204 definition = EXCLUDED.definition,
205 deleted_at = NULL
206WHERE glossary.course_id = EXCLUDED.course_id
207",
208 snapshot.id,
209 snapshot.course_id,
210 snapshot.term,
211 snapshot.definition,
212 )
213 .execute(conn)
214 .await?;
215 Ok(())
216}