headless_lms_server/programs/seed/builder/
certificate.rs

1use anyhow::{Context, Result};
2use sqlx::PgConnection;
3use uuid::Uuid;
4
5use certificate_configurations::get_default_configuration_by_course_module;
6use headless_lms_models::certificate_configurations;
7use headless_lms_models::generated_certificates::{find_existing, insert_raw};
8use headless_lms_utils as utils;
9
10#[derive(Debug, Clone)]
11pub struct CertificateBuilder {
12    user_id: Uuid,
13    name_on_certificate: String,
14    config_id: Option<Uuid>,
15    default_for_module_id: Option<Uuid>,
16}
17
18impl CertificateBuilder {
19    pub fn new(user_id: Uuid) -> Self {
20        Self {
21            user_id,
22            name_on_certificate: "Example User".into(),
23            config_id: None,
24            default_for_module_id: None,
25        }
26    }
27
28    pub fn name_on_certificate(mut self, name: impl Into<String>) -> Self {
29        self.name_on_certificate = name.into();
30        self
31    }
32
33    /// Use a specific certificate_configuration.id
34    pub fn configuration_id(mut self, id: Uuid) -> Self {
35        self.config_id = Some(id);
36        self
37    }
38
39    /// Use the default certificate configuration for this module
40    pub fn default_configuration_for_module(mut self, module_id: Uuid) -> Self {
41        self.default_for_module_id = Some(module_id);
42        self
43    }
44
45    pub async fn seed(self, conn: &mut PgConnection) -> Result<Uuid> {
46        // Resolve configuration id (explicit or default for a module)
47        let config_id = if let Some(id) = self.config_id {
48            id
49        } else if let Some(module_id) = self.default_for_module_id {
50            let conf = get_default_configuration_by_course_module(conn, module_id)
51                .await
52                .context("get_default_configuration_by_course_module")?;
53
54            conf.id
55        } else {
56            anyhow::bail!(
57                "CertificateBuilder: provide configuration_id or default_configuration_for_module"
58            );
59        };
60
61        // 1) Check if certificate already exists
62        if let Some(existing_id) = find_existing(conn, self.user_id, config_id).await? {
63            return Ok(existing_id);
64        }
65
66        // 2) Insert new certificate
67        let verification_id = utils::strings::generate_easily_writable_random_string(15);
68
69        let inserted_id = insert_raw(
70            conn,
71            self.user_id,
72            config_id,
73            &self.name_on_certificate,
74            &verification_id,
75        )
76        .await
77        .context("insert generated_certificate")?;
78        Ok(inserted_id)
79    }
80}