backend/model/entity/
seed_impl.rs1use diesel::pg::Pg;
4use diesel::{debug_query, BoolExpressionMethods, ExpressionMethods, QueryDsl, QueryResult};
5use diesel_async::{AsyncPgConnection, RunQueryDsl};
6use log::debug;
7use uuid::Uuid;
8
9use crate::db::{
10 function::{array_to_string, greatest4, similarity},
11 pagination::Paginate,
12};
13use crate::model::dto::{Page, PageParameters, SeedSearchParameters};
14use crate::{
15 model::dto::SeedDto,
16 schema::{
17 plants::{self, common_name_de, common_name_en, unique_name},
18 seeds::{self, all_columns, created_by, harvest_year, name, use_by},
19 },
20};
21
22use crate::model::r#enum::include_archived_seeds::IncludeArchivedSeeds;
23use chrono::NaiveDateTime;
24use diesel::dsl::sql;
25use diesel::sql_types::Float;
26
27use super::{NewSeed, Seed};
28
29impl Seed {
30 pub async fn find(
46 search_parameters: SeedSearchParameters,
47 user_id: Uuid,
48 page_parameters: PageParameters,
49 conn: &mut AsyncPgConnection,
50 ) -> QueryResult<Page<SeedDto>> {
51 let search_query = search_parameters.name.as_deref().unwrap_or("");
55
56 let mut query = seeds::table
57 .inner_join(plants::table)
58 .select((
59 greatest4(
60 similarity(name, search_query),
61 similarity(unique_name, search_query),
62 similarity(array_to_string(common_name_de, " "), search_query),
63 similarity(array_to_string(common_name_en, " "), search_query),
64 ),
65 all_columns,
66 ))
67 .into_boxed();
68
69 if let Some(harvest_year_search) = search_parameters.harvest_year {
70 query = query.filter(harvest_year.eq(harvest_year_search));
71 }
72
73 if search_parameters.name.is_some() {
74 query = query
75 .filter(
76 similarity(name, search_query)
77 .gt(0.1)
78 .or(similarity(array_to_string(common_name_de, " "), search_query).gt(0.1))
79 .or(similarity(array_to_string(common_name_en, " "), search_query).gt(0.1))
80 .or(similarity(unique_name, search_query).gt(0.1)),
81 )
82 .order(sql::<Float>("1").desc());
85 } else {
86 query = query.order((harvest_year.asc(), use_by.asc()));
88 }
89
90 let include_archived = search_parameters
91 .archived
92 .unwrap_or(IncludeArchivedSeeds::NotArchived);
93
94 if include_archived == IncludeArchivedSeeds::Archived {
96 query = query.filter(seeds::archived_at.is_not_null());
97 } else if include_archived == IncludeArchivedSeeds::NotArchived {
98 query = query.filter(seeds::archived_at.is_null());
99 }
100
101 query = query.filter(created_by.eq(user_id));
103
104 let query = query
105 .paginate(page_parameters.page)
106 .per_page(page_parameters.per_page);
107 debug!("{}", debug_query::<Pg, _>(&query));
108 query
109 .load_page::<(f32, Self)>(conn)
110 .await
111 .map(Page::from_entity)
112 }
113
114 pub async fn find_by_id(
119 id: i64,
120 user_id: Uuid,
121 conn: &mut AsyncPgConnection,
122 ) -> QueryResult<SeedDto> {
123 let mut query = seeds::table.select(all_columns).into_boxed();
124
125 query = query.filter(created_by.eq(user_id).and(seeds::id.eq(id)));
127
128 debug!("{}", debug_query::<Pg, _>(&query));
129 query.first::<Self>(conn).await.map(Into::into)
130 }
131
132 pub async fn create(new_seed: NewSeed, conn: &mut AsyncPgConnection) -> QueryResult<SeedDto> {
137 let query = diesel::insert_into(seeds::table).values(&new_seed);
138 debug!("{}", debug_query::<Pg, _>(&query));
139 query.get_result::<Self>(conn).await.map(Into::into)
140 }
141
142 pub async fn edit(
147 id: i64,
148 new_seed: NewSeed,
149 conn: &mut AsyncPgConnection,
150 ) -> QueryResult<SeedDto> {
151 let query_result = diesel::update(seeds::table.filter(seeds::id.eq(id)))
152 .set((
153 seeds::name.eq(new_seed.name),
154 seeds::harvest_year.eq(new_seed.harvest_year),
155 seeds::plant_id.eq(new_seed.plant_id),
156 seeds::use_by.eq(new_seed.use_by),
157 seeds::origin.eq(new_seed.origin),
158 seeds::taste.eq(new_seed.taste),
159 seeds::yield_.eq(new_seed.yield_),
160 seeds::generation.eq(new_seed.generation),
161 seeds::price.eq(new_seed.price),
162 seeds::notes.eq(new_seed.notes),
163 seeds::quantity.eq(new_seed.quantity),
164 seeds::quality.eq(new_seed.quality),
165 ))
166 .get_result::<Self>(conn)
167 .await;
168 query_result.map(Into::into)
169 }
170
171 pub async fn delete_by_id(
176 id: i64,
177 user_id: Uuid,
178 conn: &mut AsyncPgConnection,
179 ) -> QueryResult<usize> {
180 let source = seeds::table.filter(created_by.eq(user_id).and(seeds::id.eq(id)));
182
183 let query = diesel::delete(source);
184 debug!("{}", debug_query::<Pg, _>(&query));
185 query.execute(conn).await
186 }
187
188 pub async fn archive(
193 id: i64,
194 archived_at: Option<NaiveDateTime>,
195 user_id: Uuid,
196 conn: &mut AsyncPgConnection,
197 ) -> QueryResult<SeedDto> {
198 let source = seeds::table.filter(created_by.eq(user_id).and(seeds::id.eq(id)));
199
200 let query_result = diesel::update(source)
201 .set(seeds::archived_at.eq(archived_at))
202 .get_result::<Self>(conn)
203 .await;
204 query_result.map(Into::into)
205 }
206}