backend/model/entity/
guided_tour_impl.rs1use diesel::dsl::now;
4use diesel::ExpressionMethods;
5use diesel::OptionalExtension;
6use diesel::{debug_query, pg::Pg, QueryDsl, QueryResult};
7use diesel_async::{AsyncPgConnection, RunQueryDsl};
8use log::debug;
9use uuid::Uuid;
10
11use crate::{
12 model::{
13 dto::GuidedTourDto,
14 entity::{GuidedTourProgress, GuidedTourState, NewGuidedTourProgress},
15 },
16 schema::{guided_tour_progress, guided_tour_states},
17};
18
19pub struct GuidedTour;
20
21impl GuidedTour {
22 pub async fn find_by_user(
29 user_id: Uuid,
30 conn: &mut AsyncPgConnection,
31 ) -> QueryResult<GuidedTourDto> {
32 let progress_query =
34 guided_tour_progress::table.filter(guided_tour_progress::user_id.eq(user_id));
35 debug!("{}", debug_query::<Pg, _>(&progress_query));
36 let progress_rows = progress_query.load::<GuidedTourProgress>(conn).await?;
37
38 let state_query = guided_tour_states::table.find(user_id);
40 debug!("{}", debug_query::<Pg, _>(&state_query));
41 let state_opt = state_query
42 .first::<GuidedTourState>(conn)
43 .await
44 .optional()?;
45
46 Ok(GuidedTourDto::from((progress_rows, state_opt)))
47 }
48
49 pub async fn complete_step(
54 user_id: Uuid,
55 step_key: String,
56 conn: &mut AsyncPgConnection,
57 ) -> QueryResult<()> {
58 let row = NewGuidedTourProgress { user_id, step_key };
59
60 let query = diesel::insert_into(guided_tour_progress::table)
61 .values(&row)
62 .on_conflict((
63 guided_tour_progress::user_id,
64 guided_tour_progress::step_key,
65 ))
66 .do_nothing();
67
68 debug!("{}", debug_query::<Pg, _>(&query));
69 query.execute(conn).await.map(|_| ())
70 }
71
72 pub async fn complete_steps(
77 user_id: Uuid,
78 step_keys: Vec<String>,
79 conn: &mut AsyncPgConnection,
80 ) -> QueryResult<()> {
81 if step_keys.is_empty() {
82 return Ok(());
83 }
84
85 let rows: Vec<NewGuidedTourProgress> = step_keys
86 .into_iter()
87 .map(|step_key| NewGuidedTourProgress { user_id, step_key })
88 .collect();
89
90 let query = diesel::insert_into(guided_tour_progress::table)
91 .values(&rows)
92 .on_conflict((
93 guided_tour_progress::user_id,
94 guided_tour_progress::step_key,
95 ))
96 .do_nothing();
97
98 debug!("{}", debug_query::<Pg, _>(&query));
99 query.execute(conn).await.map(|_| ())
100 }
101
102 pub async fn pause(user_id: Uuid, conn: &mut AsyncPgConnection) -> QueryResult<()> {
109 let query = diesel::insert_into(guided_tour_states::table)
110 .values((
111 guided_tour_states::user_id.eq(user_id),
112 guided_tour_states::paused_at.eq(now),
113 guided_tour_states::pause_count.eq(1),
114 ))
115 .on_conflict(guided_tour_states::user_id)
116 .do_update()
117 .set((
118 guided_tour_states::paused_at.eq(now),
119 guided_tour_states::pause_count.eq(guided_tour_states::pause_count + 1),
120 ));
121
122 debug!("{}", debug_query::<Pg, _>(&query));
123 query.execute(conn).await.map(|_| ())
124 }
125}