//! Ensures the built-in alternative display currencies always exist. //! //! EUR is the base currency and is never stored. For now the only alternative is //! the Czech koruna (CZK); the admin sets its exchange rate and can disable it. //! We insert each one only when its `code` is missing, so an admin's rate/enabled //! changes are never overwritten on the next boot. use async_trait::async_trait; use loco_rs::prelude::*; use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, Set}; use crate::models::currencies; use crate::shared::currency::SCALE; /// `(code, symbol, default_rate_e4)` — default rate is a placeholder the admin /// is expected to update from the live FX rate. const BUILTINS: [(&str, &str, i64); 1] = [("CZK", "Kč", 25 * SCALE)]; pub struct CurrencySeeder; #[async_trait] impl Initializer for CurrencySeeder { fn name(&self) -> String { "currency-seeder".to_string() } async fn before_run(&self, ctx: &AppContext) -> Result<()> { for (code, symbol, rate_e4) in BUILTINS { let exists = currencies::Entity::find() .filter(currencies::Column::Code.eq(code)) .count(&ctx.db) .await? > 0; if exists { continue; } currencies::ActiveModel { code: Set(code.to_string()), symbol: Set(symbol.to_string()), rate_e4: Set(rate_e4), enabled: Set(true), ..Default::default() } .insert(&ctx.db) .await?; tracing::info!(currency = code, "seeded display currency"); } Ok(()) } }