hostbasket/actix_mvc_app/src/db/registration.rs
Mahmoud-Emad d3a66d4fc8 feat: Add initial production deployment support
- Add .env.example file for environment variable setup
- Add .gitignore to manage sensitive files and directories
- Add Dockerfile.prod for production-ready Docker image
- Add PRODUCTION_CHECKLIST.md for pre/post deployment steps
- Add PRODUCTION_DEPLOYMENT.md for deployment instructions
- Add STRIPE_SETUP.md for Stripe payment configuration
- Add config/default.toml for default configuration settings
- Add config/local.toml.example for local configuration template
2025-06-25 18:32:20 +03:00

273 lines
8.8 KiB
Rust

#![allow(dead_code)] // Database utility functions may not all be used yet
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs;
use std::path::Path;
/// Stored registration data linked to payment intent
/// This preserves all user form data until company creation after payment success
/// NOTE: This uses file-based storage until we can add the model to heromodels
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredRegistrationData {
pub payment_intent_id: String,
pub company_name: String,
pub company_type: String,
pub company_email: String,
pub company_phone: String,
pub company_website: Option<String>,
pub company_address: String,
pub company_industry: Option<String>,
pub company_purpose: Option<String>,
pub fiscal_year_end: Option<String>,
pub shareholders: String, // JSON string of shareholders array
pub payment_plan: String,
pub created_at: i64,
}
/// File path for storing registration data
const REGISTRATION_DATA_FILE: &str = "data/registration_data.json";
/// Ensure data directory exists
fn ensure_data_directory() -> Result<(), String> {
let data_dir = Path::new("data");
if !data_dir.exists() {
fs::create_dir_all(data_dir)
.map_err(|e| format!("Failed to create data directory: {}", e))?;
}
Ok(())
}
/// Load all registration data from file
fn load_registration_data() -> Result<HashMap<String, StoredRegistrationData>, String> {
if !Path::new(REGISTRATION_DATA_FILE).exists() {
return Ok(HashMap::new());
}
let content = fs::read_to_string(REGISTRATION_DATA_FILE)
.map_err(|e| format!("Failed to read registration data file: {}", e))?;
let data: HashMap<String, StoredRegistrationData> = serde_json::from_str(&content)
.map_err(|e| format!("Failed to parse registration data: {}", e))?;
Ok(data)
}
/// Save all registration data to file
fn save_registration_data(data: &HashMap<String, StoredRegistrationData>) -> Result<(), String> {
ensure_data_directory()?;
let content = serde_json::to_string_pretty(data)
.map_err(|e| format!("Failed to serialize registration data: {}", e))?;
fs::write(REGISTRATION_DATA_FILE, content)
.map_err(|e| format!("Failed to write registration data file: {}", e))?;
Ok(())
}
impl StoredRegistrationData {
/// Create new stored registration data
pub fn new(
payment_intent_id: String,
company_name: String,
company_type: String,
company_email: String,
company_phone: String,
company_website: Option<String>,
company_address: String,
company_industry: Option<String>,
company_purpose: Option<String>,
fiscal_year_end: Option<String>,
shareholders: String,
payment_plan: String,
) -> Self {
Self {
payment_intent_id,
company_name,
company_type,
company_email,
company_phone,
company_website,
company_address,
company_industry,
company_purpose,
fiscal_year_end,
shareholders,
payment_plan,
created_at: chrono::Utc::now().timestamp(),
}
}
}
/// Store registration data linked to payment intent
pub fn store_registration_data(
payment_intent_id: String,
data: crate::controllers::payment::CompanyRegistrationData,
) -> Result<(u32, StoredRegistrationData), String> {
// Create stored registration data
let stored_data = StoredRegistrationData::new(
payment_intent_id.clone(),
data.company_name,
data.company_type,
data.company_email
.unwrap_or_else(|| "noemail@example.com".to_string()),
data.company_phone
.unwrap_or_else(|| "+1234567890".to_string()),
data.company_website,
data.company_address
.unwrap_or_else(|| "No address provided".to_string()),
data.company_industry,
data.company_purpose,
data.fiscal_year_end,
data.shareholders,
data.payment_plan,
);
// Load existing data
let mut all_data = load_registration_data()?;
// Add new data
all_data.insert(payment_intent_id.clone(), stored_data.clone());
// Save to file
save_registration_data(&all_data)?;
log::info!(
"Stored registration data for payment intent {}",
payment_intent_id
);
// Return with a generated ID (timestamp-based)
let id = chrono::Utc::now().timestamp() as u32;
Ok((id, stored_data))
}
/// Retrieve registration data by payment intent ID
pub fn get_registration_data(
payment_intent_id: &str,
) -> Result<Option<StoredRegistrationData>, String> {
let all_data = load_registration_data()?;
Ok(all_data.get(payment_intent_id).cloned())
}
/// Get all stored registration data
pub fn get_all_registration_data() -> Result<Vec<StoredRegistrationData>, String> {
let all_data = load_registration_data()?;
Ok(all_data.into_values().collect())
}
/// Delete registration data by payment intent ID
pub fn delete_registration_data(payment_intent_id: &str) -> Result<bool, String> {
let mut all_data = load_registration_data()?;
if all_data.remove(payment_intent_id).is_some() {
save_registration_data(&all_data)?;
log::info!(
"Deleted registration data for payment intent: {}",
payment_intent_id
);
Ok(true)
} else {
log::warn!(
"Registration data not found for payment intent: {}",
payment_intent_id
);
Ok(false)
}
}
/// Update registration data
pub fn update_registration_data(
payment_intent_id: &str,
updated_data: StoredRegistrationData,
) -> Result<Option<StoredRegistrationData>, String> {
let mut all_data = load_registration_data()?;
all_data.insert(payment_intent_id.to_string(), updated_data.clone());
save_registration_data(&all_data)?;
log::info!(
"Updated registration data for payment intent: {}",
payment_intent_id
);
Ok(Some(updated_data))
}
/// Convert StoredRegistrationData back to CompanyRegistrationData for processing
pub fn stored_to_registration_data(
stored: &StoredRegistrationData,
) -> crate::controllers::payment::CompanyRegistrationData {
crate::controllers::payment::CompanyRegistrationData {
company_name: stored.company_name.clone(),
company_type: stored.company_type.clone(),
company_email: Some(stored.company_email.clone()),
company_phone: Some(stored.company_phone.clone()),
company_website: stored.company_website.clone(),
company_address: Some(stored.company_address.clone()),
company_industry: stored.company_industry.clone(),
company_purpose: stored.company_purpose.clone(),
fiscal_year_end: stored.fiscal_year_end.clone(),
shareholders: stored.shareholders.clone(),
payment_plan: stored.payment_plan.clone(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_stored_registration_data_creation() {
let data = StoredRegistrationData::new(
"pi_test123".to_string(),
"Test Company".to_string(),
"Single FZC".to_string(),
"test@example.com".to_string(),
"+1234567890".to_string(),
Some("https://example.com".to_string()),
"123 Test St".to_string(),
Some("Technology".to_string()),
Some("Software development".to_string()),
Some("December".to_string()),
"[]".to_string(),
"monthly".to_string(),
);
assert_eq!(data.payment_intent_id, "pi_test123");
assert_eq!(data.company_name, "Test Company");
assert_eq!(data.company_type, "Single FZC");
assert_eq!(data.company_email, "test@example.com");
assert!(data.created_at > 0);
}
#[test]
fn test_stored_to_registration_data_conversion() {
let stored = StoredRegistrationData::new(
"pi_test123".to_string(),
"Test Company".to_string(),
"Single FZC".to_string(),
"test@example.com".to_string(),
"+1234567890".to_string(),
Some("https://example.com".to_string()),
"123 Test St".to_string(),
Some("Technology".to_string()),
Some("Software development".to_string()),
Some("December".to_string()),
"[]".to_string(),
"monthly".to_string(),
);
let registration_data = stored_to_registration_data(&stored);
assert_eq!(registration_data.company_name, "Test Company");
assert_eq!(registration_data.company_type, "Single FZC");
assert_eq!(
registration_data.company_email,
Some("test@example.com".to_string())
);
assert_eq!(registration_data.payment_plan, "monthly");
}
}