use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::{FromRow, PgPool}; use uuid::Uuid; #[derive(Debug, Serialize, Deserialize, FromRow)] pub struct DeveloperProfile { pub id: Uuid, pub user_id: Uuid, pub bio: Option, pub experience_years: Option, pub custom_data: Option, pub created_at: DateTime, pub updated_at: DateTime, } #[derive(Debug, Serialize, Deserialize)] pub struct UpsertDeveloperProfilePayload { pub bio: Option, pub experience_years: Option, pub custom_data: Option, } pub struct DeveloperRepository; impl DeveloperRepository { pub async fn get_by_user_id( pool: &PgPool, user_id: Uuid, ) -> Result, sqlx::Error> { let profile = sqlx::query_as!( DeveloperProfile, r#" SELECT id, user_id, bio, experience_years, custom_data, created_at, updated_at FROM developer_profiles WHERE user_id = $1 "#, user_id ) .fetch_optional(pool) .await?; Ok(profile) } pub async fn upsert( pool: &PgPool, user_id: Uuid, payload: UpsertDeveloperProfilePayload, ) -> Result { let profile = sqlx::query_as!( DeveloperProfile, r#" INSERT INTO developer_profiles ( user_id, bio, experience_years, custom_data ) VALUES ($1, $2, $3, $4) ON CONFLICT (user_id) DO UPDATE SET bio = EXCLUDED.bio, experience_years = EXCLUDED.experience_years, custom_data = EXCLUDED.custom_data, updated_at = NOW() RETURNING id, user_id, bio, experience_years, custom_data, created_at, updated_at "#, user_id, payload.bio, payload.experience_years, payload.custom_data ) .fetch_one(pool) .await?; Ok(profile) } }