1use std::fmt;
2
3use crate::{
4 certificate_configuration_to_requirements::{
5 CertificateAllRequirements, get_all_requirements_for_certificate_configuration,
6 },
7 prelude::*,
8};
9
10#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy, sqlx::Type)]
11#[cfg_attr(feature = "ts_rs", derive(TS))]
12#[serde(rename_all = "kebab-case")]
13#[sqlx(type_name = "certificate_paper_size", rename_all = "kebab-case")]
14pub enum PaperSize {
15 HorizontalA4,
16 VerticalA4,
17}
18
19impl PaperSize {
20 pub fn width_px(&self) -> u32 {
21 match self {
22 PaperSize::HorizontalA4 => 3508,
23 PaperSize::VerticalA4 => 2480,
24 }
25 }
26 pub fn height_px(&self) -> u32 {
27 match self {
28 PaperSize::HorizontalA4 => 2480,
29 PaperSize::VerticalA4 => 3508,
30 }
31 }
32}
33
34#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy, sqlx::Type)]
36#[cfg_attr(feature = "ts_rs", derive(TS))]
37#[serde(rename_all = "kebab-case")]
38#[sqlx(type_name = "certificate_text_anchor", rename_all = "kebab-case")]
39pub enum CertificateTextAnchor {
40 Start,
41 Middle,
42 End,
43}
44
45impl fmt::Display for CertificateTextAnchor {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 match self {
48 Self::Start => f.write_str("start"),
49 Self::Middle => f.write_str("middle"),
50 Self::End => f.write_str("end"),
51 }
52 }
53}
54
55#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
56#[cfg_attr(feature = "ts_rs", derive(TS))]
57pub struct CertificateConfigurationAndRequirements {
58 pub certificate_configuration: CertificateConfiguration,
59 pub requirements: CertificateAllRequirements,
60}
61
62#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
63#[cfg_attr(feature = "ts_rs", derive(TS))]
64pub struct CertificateConfiguration {
65 pub id: Uuid,
66 pub created_at: DateTime<Utc>,
67 pub updated_at: DateTime<Utc>,
68 pub deleted_at: Option<DateTime<Utc>>,
69 pub certificate_owner_name_y_pos: String,
70 pub certificate_owner_name_x_pos: String,
71 pub certificate_owner_name_font_size: String,
72 pub certificate_owner_name_text_color: String,
73 pub certificate_owner_name_text_anchor: CertificateTextAnchor,
74 pub certificate_validate_url_y_pos: String,
75 pub certificate_validate_url_x_pos: String,
76 pub certificate_validate_url_font_size: String,
77 pub certificate_validate_url_text_color: String,
78 pub certificate_validate_url_text_anchor: CertificateTextAnchor,
79 pub certificate_date_y_pos: String,
80 pub certificate_date_x_pos: String,
81 pub certificate_date_font_size: String,
82 pub certificate_date_text_color: String,
83 pub certificate_date_text_anchor: CertificateTextAnchor,
84 pub certificate_locale: String,
85 pub paper_size: PaperSize,
86 pub background_svg_path: String,
87 pub background_svg_file_upload_id: Uuid,
88 pub overlay_svg_path: Option<String>,
89 pub overlay_svg_file_upload_id: Option<Uuid>,
90 pub render_certificate_grade: bool,
91 pub certificate_grade_y_pos: Option<String>,
92 pub certificate_grade_x_pos: Option<String>,
93 pub certificate_grade_font_size: Option<String>,
94 pub certificate_grade_text_color: Option<String>,
95 pub certificate_grade_text_anchor: Option<CertificateTextAnchor>,
96}
97
98pub async fn get_by_id(conn: &mut PgConnection, id: Uuid) -> ModelResult<CertificateConfiguration> {
99 let res = sqlx::query_as!(
100 CertificateConfiguration,
101 r#"
102SELECT cc.id,
103 cc.created_at,
104 cc.updated_at,
105 cc.deleted_at,
106 cc.certificate_owner_name_y_pos,
107 cc.certificate_owner_name_x_pos,
108 cc.certificate_owner_name_font_size,
109 cc.certificate_owner_name_text_color,
110 cc.certificate_owner_name_text_anchor AS "certificate_owner_name_text_anchor: _",
111 cc.certificate_validate_url_y_pos,
112 cc.certificate_validate_url_x_pos,
113 cc.certificate_validate_url_font_size,
114 cc.certificate_validate_url_text_color,
115 cc.certificate_validate_url_text_anchor AS "certificate_validate_url_text_anchor: _",
116 cc.certificate_date_y_pos,
117 cc.certificate_date_x_pos,
118 cc.certificate_date_font_size,
119 cc.certificate_date_text_color,
120 cc.certificate_date_text_anchor AS "certificate_date_text_anchor: _",
121 cc.certificate_locale,
122 cc.paper_size AS "paper_size: _",
123 cc.background_svg_path,
124 cc.background_svg_file_upload_id,
125 cc.overlay_svg_path,
126 cc.overlay_svg_file_upload_id,
127 cc.render_certificate_grade,
128 cc.certificate_grade_y_pos,
129 cc.certificate_grade_x_pos,
130 cc.certificate_grade_font_size,
131 cc.certificate_grade_text_color,
132 cc.certificate_grade_text_anchor AS "certificate_grade_text_anchor: _"
133FROM certificate_configurations cc
134WHERE id = $1
135 AND cc.deleted_at IS NULL "#,
136 id,
137 )
138 .fetch_one(&mut *conn)
139 .await?;
140 Ok(res)
141}
142
143pub async fn get_default_configuration_by_course_module(
144 conn: &mut PgConnection,
145 course_module_id: Uuid,
146) -> ModelResult<CertificateConfiguration> {
147 let all_certificate_configurations = sqlx::query_as!(
148 CertificateConfiguration,
149 r#"
150SELECT cc.id,
151 cc.created_at,
152 cc.updated_at,
153 cc.deleted_at,
154 cc.certificate_owner_name_y_pos,
155 cc.certificate_owner_name_x_pos,
156 cc.certificate_owner_name_font_size,
157 cc.certificate_owner_name_text_color,
158 cc.certificate_owner_name_text_anchor as "certificate_owner_name_text_anchor: _",
159 cc.certificate_validate_url_y_pos,
160 cc.certificate_validate_url_x_pos,
161 cc.certificate_validate_url_font_size,
162 cc.certificate_validate_url_text_color,
163 cc.certificate_validate_url_text_anchor as "certificate_validate_url_text_anchor: _",
164 cc.certificate_date_y_pos,
165 cc.certificate_date_x_pos,
166 cc.certificate_date_font_size,
167 cc.certificate_date_text_color,
168 cc.certificate_date_text_anchor as "certificate_date_text_anchor: _",
169 cc.certificate_locale,
170 cc.paper_size as "paper_size: _",
171 cc.background_svg_path,
172 cc.background_svg_file_upload_id,
173 cc.overlay_svg_path,
174 cc.overlay_svg_file_upload_id,
175 cc.render_certificate_grade,
176 cc.certificate_grade_y_pos,
177 cc.certificate_grade_x_pos,
178 cc.certificate_grade_font_size,
179 cc.certificate_grade_text_color,
180 cc.certificate_grade_text_anchor AS "certificate_grade_text_anchor: _"
181FROM certificate_configurations cc
182JOIN certificate_configuration_to_requirements cctr ON cc.id = cctr.certificate_configuration_id
183WHERE cctr.course_module_id = $1
184 AND cc.deleted_at IS NULL
185 AND cctr.deleted_at IS NULL
186 "#,
187 course_module_id,
188 )
189 .fetch_all(&mut *conn)
190 .await?;
191 if all_certificate_configurations.len() > 1 {
192 warn!(
193 "Multiple certificate configurations found for the course module: {:?}",
194 course_module_id
195 );
196 }
197 if !all_certificate_configurations.is_empty() {
198 return Ok(all_certificate_configurations[0].clone());
199 }
200
201 Err(ModelError::new(
202 ModelErrorType::RecordNotFound,
203 "No certificate configuration found for the course module".to_string(),
204 None,
205 ))
206}
207
208pub async fn get_default_certificate_configurations_and_requirements_by_course(
210 conn: &mut PgConnection,
211 course_id: Uuid,
212) -> ModelResult<Vec<CertificateConfigurationAndRequirements>> {
213 let mut res = Vec::new();
214 let all_certificate_configurations = sqlx::query_as!(
215 CertificateConfiguration,
216 r#"
217SELECT cc.id,
218 cc.created_at,
219 cc.updated_at,
220 cc.deleted_at,
221 cc.certificate_owner_name_y_pos,
222 cc.certificate_owner_name_x_pos,
223 cc.certificate_owner_name_font_size,
224 cc.certificate_owner_name_text_color,
225 cc.certificate_owner_name_text_anchor AS "certificate_owner_name_text_anchor: _",
226 cc.certificate_validate_url_y_pos,
227 cc.certificate_validate_url_x_pos,
228 cc.certificate_validate_url_font_size,
229 cc.certificate_validate_url_text_color,
230 cc.certificate_validate_url_text_anchor AS "certificate_validate_url_text_anchor: _",
231 cc.certificate_date_y_pos,
232 cc.certificate_date_x_pos,
233 cc.certificate_date_font_size,
234 cc.certificate_date_text_color,
235 cc.certificate_date_text_anchor AS "certificate_date_text_anchor: _",
236 cc.certificate_locale,
237 cc.paper_size AS "paper_size: _",
238 cc.background_svg_path,
239 cc.background_svg_file_upload_id,
240 cc.overlay_svg_path,
241 cc.overlay_svg_file_upload_id,
242 cc.render_certificate_grade,
243 cc.certificate_grade_y_pos,
244 cc.certificate_grade_x_pos,
245 cc.certificate_grade_font_size,
246 cc.certificate_grade_text_color,
247 cc.certificate_grade_text_anchor AS "certificate_grade_text_anchor: _"
248FROM certificate_configurations cc
249 JOIN certificate_configuration_to_requirements cctr ON cc.id = cctr.certificate_configuration_id
250WHERE cctr.course_module_id IN (
251 SELECT id
252 FROM course_modules
253 WHERE course_id = $1
254 AND deleted_at IS NULL
255 )
256 AND cc.deleted_at IS NULL
257 AND cctr.deleted_at IS NULL
258 "#,
259 course_id,
260 )
261 .fetch_all(&mut *conn)
262 .await?;
263 for certificate_configuration in &all_certificate_configurations {
265 let requirements =
266 get_all_requirements_for_certificate_configuration(conn, certificate_configuration.id)
267 .await?;
268 if requirements.is_default_certificate_configuration() {
269 res.push(CertificateConfigurationAndRequirements {
270 certificate_configuration: certificate_configuration.clone(),
271 requirements,
272 });
273 }
274 }
275 Ok(res)
276}
277
278#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
279#[cfg_attr(feature = "ts_rs", derive(TS))]
280pub struct DatabaseCertificateConfiguration {
281 pub id: Uuid,
282 pub certificate_owner_name_y_pos: Option<String>,
283 pub certificate_owner_name_x_pos: Option<String>,
284 pub certificate_owner_name_font_size: Option<String>,
285 pub certificate_owner_name_text_color: Option<String>,
286 pub certificate_owner_name_text_anchor: Option<CertificateTextAnchor>,
287 pub certificate_validate_url_y_pos: Option<String>,
288 pub certificate_validate_url_x_pos: Option<String>,
289 pub certificate_validate_url_font_size: Option<String>,
290 pub certificate_validate_url_text_color: Option<String>,
291 pub certificate_validate_url_text_anchor: Option<CertificateTextAnchor>,
292 pub certificate_date_y_pos: Option<String>,
293 pub certificate_date_x_pos: Option<String>,
294 pub certificate_date_font_size: Option<String>,
295 pub certificate_date_text_color: Option<String>,
296 pub certificate_date_text_anchor: Option<CertificateTextAnchor>,
297 pub certificate_locale: Option<String>,
298 pub paper_size: Option<PaperSize>,
299 pub background_svg_path: String,
300 pub background_svg_file_upload_id: Uuid,
301 pub overlay_svg_path: Option<String>,
302 pub overlay_svg_file_upload_id: Option<Uuid>,
303 pub render_certificate_grade: bool,
304 pub certificate_grade_y_pos: Option<String>,
305 pub certificate_grade_x_pos: Option<String>,
306 pub certificate_grade_font_size: Option<String>,
307 pub certificate_grade_text_color: Option<String>,
308 pub certificate_grade_text_anchor: Option<CertificateTextAnchor>,
309}
310
311impl DatabaseCertificateConfiguration {
312 fn build(&self) -> DatabaseCertificateConfigurationInner<'_> {
315 DatabaseCertificateConfigurationInner {
316 id: self.id,
317 certificate_owner_name_y_pos: self
318 .certificate_owner_name_y_pos
319 .as_deref()
320 .unwrap_or("70%"),
321 certificate_owner_name_x_pos: self
322 .certificate_owner_name_x_pos
323 .as_deref()
324 .unwrap_or("50%"),
325 certificate_owner_name_font_size: self
326 .certificate_owner_name_font_size
327 .as_deref()
328 .unwrap_or("150px"),
329 certificate_owner_name_text_color: self
330 .certificate_owner_name_text_color
331 .as_deref()
332 .unwrap_or("black"),
333 certificate_owner_name_text_anchor: self
334 .certificate_owner_name_text_anchor
335 .unwrap_or(CertificateTextAnchor::Middle),
336 certificate_validate_url_y_pos: self
337 .certificate_validate_url_y_pos
338 .as_deref()
339 .unwrap_or("80%"),
340 certificate_validate_url_x_pos: self
341 .certificate_validate_url_x_pos
342 .as_deref()
343 .unwrap_or("88.5%"),
344 certificate_validate_url_font_size: self
345 .certificate_validate_url_font_size
346 .as_deref()
347 .unwrap_or("30px"),
348 certificate_validate_url_text_color: self
349 .certificate_validate_url_text_color
350 .as_deref()
351 .unwrap_or("black"),
352 certificate_validate_url_text_anchor: self
353 .certificate_validate_url_text_anchor
354 .unwrap_or(CertificateTextAnchor::End),
355 certificate_date_y_pos: self.certificate_date_y_pos.as_deref().unwrap_or("88.5%"),
356 certificate_date_x_pos: self.certificate_date_x_pos.as_deref().unwrap_or("15%"),
357 certificate_date_font_size: self
358 .certificate_date_font_size
359 .as_deref()
360 .unwrap_or("30px"),
361 certificate_date_text_color: self
362 .certificate_date_text_color
363 .as_deref()
364 .unwrap_or("black"),
365 certificate_date_text_anchor: self
366 .certificate_date_text_anchor
367 .unwrap_or(CertificateTextAnchor::Start),
368 certificate_locale: self.certificate_locale.as_deref().unwrap_or("en"),
369 paper_size: self.paper_size.unwrap_or(PaperSize::HorizontalA4),
370 background_svg_path: &self.background_svg_path,
371 background_svg_file_upload_id: self.background_svg_file_upload_id,
372 overlay_svg_path: self.overlay_svg_path.as_deref(),
373 overlay_svg_file_upload_id: self.overlay_svg_file_upload_id,
374 render_certificate_grade: self.render_certificate_grade,
375 certificate_grade_y_pos: self.certificate_grade_y_pos.as_deref().unwrap_or(""),
376 certificate_grade_x_pos: self.certificate_grade_x_pos.as_deref().unwrap_or(""),
377 certificate_grade_font_size: self.certificate_grade_font_size.as_deref().unwrap_or(""),
378 certificate_grade_text_color: self
379 .certificate_grade_text_color
380 .as_deref()
381 .unwrap_or(""),
382 certificate_grade_text_anchor: self
383 .certificate_grade_text_anchor
384 .unwrap_or(CertificateTextAnchor::Middle),
385 }
386 }
387}
388
389#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy)]
390struct DatabaseCertificateConfigurationInner<'a> {
391 pub id: Uuid,
392 pub certificate_owner_name_y_pos: &'a str,
393 pub certificate_owner_name_x_pos: &'a str,
394 pub certificate_owner_name_font_size: &'a str,
395 pub certificate_owner_name_text_color: &'a str,
396 pub certificate_owner_name_text_anchor: CertificateTextAnchor,
397 pub certificate_validate_url_y_pos: &'a str,
398 pub certificate_validate_url_x_pos: &'a str,
399 pub certificate_validate_url_font_size: &'a str,
400 pub certificate_validate_url_text_color: &'a str,
401 pub certificate_validate_url_text_anchor: CertificateTextAnchor,
402 pub certificate_date_y_pos: &'a str,
403 pub certificate_date_x_pos: &'a str,
404 pub certificate_date_font_size: &'a str,
405 pub certificate_date_text_color: &'a str,
406 pub certificate_date_text_anchor: CertificateTextAnchor,
407 pub certificate_locale: &'a str,
408 pub paper_size: PaperSize,
409 pub background_svg_path: &'a str,
410 pub background_svg_file_upload_id: Uuid,
411 pub overlay_svg_path: Option<&'a str>,
412 pub overlay_svg_file_upload_id: Option<Uuid>,
413 pub render_certificate_grade: bool,
414 pub certificate_grade_y_pos: &'a str,
415 pub certificate_grade_x_pos: &'a str,
416 pub certificate_grade_font_size: &'a str,
417 pub certificate_grade_text_color: &'a str,
418 pub certificate_grade_text_anchor: CertificateTextAnchor,
419}
420
421pub async fn insert(
422 conn: &mut PgConnection,
423 conf: &DatabaseCertificateConfiguration,
424) -> ModelResult<CertificateConfiguration> {
425 let conf = conf.build();
426 let configuration = sqlx::query_as!(
427 CertificateConfiguration,
428 r#"
429INSERT INTO public.certificate_configurations (
430 certificate_owner_name_y_pos,
431 certificate_owner_name_x_pos,
432 certificate_owner_name_font_size,
433 certificate_owner_name_text_color,
434 certificate_owner_name_text_anchor,
435 certificate_validate_url_y_pos,
436 certificate_validate_url_x_pos,
437 certificate_validate_url_font_size,
438 certificate_validate_url_text_color,
439 certificate_validate_url_text_anchor,
440 certificate_date_y_pos,
441 certificate_date_x_pos,
442 certificate_date_font_size,
443 certificate_date_text_color,
444 certificate_date_text_anchor,
445 certificate_locale,
446 paper_size,
447 background_svg_path,
448 background_svg_file_upload_id,
449 overlay_svg_path,
450 overlay_svg_file_upload_id,
451 render_certificate_grade,
452 certificate_grade_y_pos,
453 certificate_grade_x_pos,
454 certificate_grade_font_size,
455 certificate_grade_text_color,
456 certificate_grade_text_anchor
457 )
458VALUES (
459 $1,
460 $2,
461 $3,
462 $4,
463 $5,
464 $6,
465 $7,
466 $8,
467 $9,
468 $10,
469 $11,
470 $12,
471 $13,
472 $14,
473 $15,
474 $16,
475 $17,
476 $18,
477 $19,
478 $20,
479 $21,
480 $22,
481 $23,
482 $24,
483 $25,
484 $26,
485 $27
486 )
487RETURNING id,
488 created_at,
489 updated_at,
490 deleted_at,
491 certificate_owner_name_y_pos,
492 certificate_owner_name_x_pos,
493 certificate_owner_name_font_size,
494 certificate_owner_name_text_color,
495 certificate_owner_name_text_anchor as "certificate_owner_name_text_anchor: _",
496 certificate_validate_url_y_pos,
497 certificate_validate_url_x_pos,
498 certificate_validate_url_font_size,
499 certificate_validate_url_text_color,
500 certificate_validate_url_text_anchor as "certificate_validate_url_text_anchor: _",
501 certificate_date_y_pos,
502 certificate_date_x_pos,
503 certificate_date_font_size,
504 certificate_date_text_color,
505 certificate_date_text_anchor as "certificate_date_text_anchor: _",
506 certificate_locale,
507 paper_size as "paper_size: _",
508 background_svg_path,
509 background_svg_file_upload_id,
510 overlay_svg_path,
511 overlay_svg_file_upload_id,
512 render_certificate_grade,
513 certificate_grade_y_pos,
514 certificate_grade_x_pos,
515 certificate_grade_font_size,
516 certificate_grade_text_color,
517 certificate_grade_text_anchor as "certificate_grade_text_anchor: _"
518"#,
519 conf.certificate_owner_name_y_pos,
520 conf.certificate_owner_name_x_pos,
521 conf.certificate_owner_name_font_size,
522 conf.certificate_owner_name_text_color,
523 conf.certificate_owner_name_text_anchor as CertificateTextAnchor,
524 conf.certificate_validate_url_y_pos,
525 conf.certificate_validate_url_x_pos,
526 conf.certificate_validate_url_font_size,
527 conf.certificate_validate_url_text_color,
528 conf.certificate_validate_url_text_anchor as CertificateTextAnchor,
529 conf.certificate_date_y_pos,
530 conf.certificate_date_x_pos,
531 conf.certificate_date_font_size,
532 conf.certificate_date_text_color,
533 conf.certificate_date_text_anchor as CertificateTextAnchor,
534 conf.certificate_locale,
535 conf.paper_size as PaperSize,
536 conf.background_svg_path,
537 conf.background_svg_file_upload_id,
538 conf.overlay_svg_path,
539 conf.overlay_svg_file_upload_id,
540 conf.render_certificate_grade,
541 conf.certificate_grade_y_pos,
542 conf.certificate_grade_x_pos,
543 conf.certificate_grade_font_size,
544 conf.certificate_grade_text_color,
545 conf.certificate_grade_text_anchor as CertificateTextAnchor
546 )
547 .fetch_one(conn)
548 .await?;
549 Ok(configuration)
550}
551
552pub async fn update(
553 conn: &mut PgConnection,
554 id: Uuid,
555 conf: &DatabaseCertificateConfiguration,
556) -> ModelResult<()> {
557 let conf = conf.build();
558 sqlx::query!(
559 r#"
560UPDATE public.certificate_configurations
561SET certificate_owner_name_y_pos = $1,
562 certificate_owner_name_x_pos = $2,
563 certificate_owner_name_font_size = $3,
564 certificate_owner_name_text_color = $4,
565 certificate_owner_name_text_anchor = $5,
566 certificate_validate_url_y_pos = $6,
567 certificate_validate_url_x_pos = $7,
568 certificate_validate_url_font_size = $8,
569 certificate_validate_url_text_color = $9,
570 certificate_validate_url_text_anchor = $10,
571 certificate_date_y_pos = $11,
572 certificate_date_x_pos = $12,
573 certificate_date_font_size = $13,
574 certificate_date_text_color = $14,
575 certificate_date_text_anchor = $15,
576 certificate_locale = $16,
577 paper_size = $17,
578 background_svg_path = $18,
579 background_svg_file_upload_id = $19,
580 overlay_svg_path = $20,
581 overlay_svg_file_upload_id = $21,
582 render_certificate_grade = $22,
583 certificate_grade_y_pos = $23,
584 certificate_grade_x_pos = $24,
585 certificate_grade_font_size = $25,
586 certificate_grade_text_color = $26,
587 certificate_grade_text_anchor = $27
588WHERE id = $28
589"#,
590 conf.certificate_owner_name_y_pos,
591 conf.certificate_owner_name_x_pos,
592 conf.certificate_owner_name_font_size,
593 conf.certificate_owner_name_text_color,
594 conf.certificate_owner_name_text_anchor as CertificateTextAnchor,
595 conf.certificate_validate_url_y_pos,
596 conf.certificate_validate_url_x_pos,
597 conf.certificate_validate_url_font_size,
598 conf.certificate_validate_url_text_color,
599 conf.certificate_validate_url_text_anchor as CertificateTextAnchor,
600 conf.certificate_date_y_pos,
601 conf.certificate_date_x_pos,
602 conf.certificate_date_font_size,
603 conf.certificate_date_text_color,
604 conf.certificate_date_text_anchor as CertificateTextAnchor,
605 conf.certificate_locale,
606 conf.paper_size as PaperSize,
607 conf.background_svg_path,
608 conf.background_svg_file_upload_id,
609 conf.overlay_svg_path,
610 conf.overlay_svg_file_upload_id,
611 conf.render_certificate_grade,
612 conf.certificate_grade_y_pos,
613 conf.certificate_grade_x_pos,
614 conf.certificate_grade_font_size,
615 conf.certificate_grade_text_color,
616 conf.certificate_grade_text_anchor as CertificateTextAnchor,
617 id
618 )
619 .execute(conn)
620 .await?;
621 Ok(())
622}
623
624pub async fn delete(conn: &mut PgConnection, id: Uuid) -> ModelResult<()> {
625 sqlx::query!(
626 "
627UPDATE certificate_configurations
628SET deleted_at = now()
629WHERE id = $1
630",
631 id
632 )
633 .execute(conn)
634 .await?;
635 Ok(())
636}