use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::{FromRow, PgPool}; use uuid::Uuid; #[derive(Debug, Serialize, Deserialize, FromRow)] pub struct CompanyProfile { pub id: Uuid, pub user_id: Uuid, pub company_name: String, pub registration_number: Option, pub industry: Option, pub website_url: Option, pub employee_count: Option, pub business_type: Option, pub gst_number: Option, pub contact_name: Option, pub contact_email: Option, pub contact_phone: Option, pub address_line1: Option, pub city: Option, pub state: Option, pub country: String, pub postal_code: Option, pub status: String, pub free_job_slots: i32, pub purchased_job_slots: i32, pub free_contact_views: i32, pub purchased_contact_views: i32, pub created_at: DateTime, pub updated_at: DateTime, } #[derive(Debug, Serialize, Deserialize)] pub struct UpsertCompanyProfilePayload { pub company_name: String, pub registration_number: Option, pub industry: Option, pub website_url: Option, pub employee_count: Option, pub business_type: Option, pub gst_number: Option, pub contact_name: Option, pub contact_email: Option, pub contact_phone: Option, pub address_line1: Option, pub city: Option, pub state: Option, pub postal_code: Option, } pub struct CompanyRepository; impl CompanyRepository { pub async fn get_by_user_id( pool: &PgPool, user_id: Uuid, ) -> Result, sqlx::Error> { let profile = sqlx::query_as!( CompanyProfile, r#" SELECT id, user_id, company_name, registration_number, industry, website_url, employee_count, business_type, gst_number, contact_name, contact_email, contact_phone, address_line1, city, state, country, postal_code, status, free_job_slots, purchased_job_slots, free_contact_views, purchased_contact_views, created_at, updated_at FROM company_profiles WHERE user_id = $1 "#, user_id ) .fetch_optional(pool) .await?; Ok(profile) } pub async fn upsert( pool: &PgPool, user_id: Uuid, payload: UpsertCompanyProfilePayload, ) -> Result { let profile = sqlx::query_as!( CompanyProfile, r#" INSERT INTO company_profiles ( user_id, company_name, registration_number, industry, website_url, employee_count, business_type, gst_number, contact_name, contact_email, contact_phone, address_line1, city, state, postal_code, status ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, 'PENDING') ON CONFLICT (user_id) DO UPDATE SET company_name = EXCLUDED.company_name, registration_number = EXCLUDED.registration_number, industry = EXCLUDED.industry, website_url = EXCLUDED.website_url, employee_count = EXCLUDED.employee_count, business_type = EXCLUDED.business_type, gst_number = EXCLUDED.gst_number, contact_name = EXCLUDED.contact_name, contact_email = EXCLUDED.contact_email, contact_phone = EXCLUDED.contact_phone, address_line1 = EXCLUDED.address_line1, city = EXCLUDED.city, state = EXCLUDED.state, postal_code = EXCLUDED.postal_code, status = CASE WHEN company_profiles.status = 'APPROVED' THEN 'APPROVED' ELSE 'PENDING' END, updated_at = NOW() RETURNING id, user_id, company_name, registration_number, industry, website_url, employee_count, business_type, gst_number, contact_name, contact_email, contact_phone, address_line1, city, state, country, postal_code, status, free_job_slots, purchased_job_slots, free_contact_views, purchased_contact_views, created_at, updated_at "#, user_id, payload.company_name, payload.registration_number, payload.industry, payload.website_url, payload.employee_count, payload.business_type, payload.gst_number, payload.contact_name, payload.contact_email, payload.contact_phone, payload.address_line1, payload.city, payload.state, payload.postal_code ) .fetch_one(pool) .await?; Ok(profile) } pub async fn submit_for_verification( pool: &PgPool, user_id: Uuid, ) -> Result { let profile = sqlx::query_as!( CompanyProfile, r#" UPDATE company_profiles SET status = 'PENDING_REVIEW', updated_at = NOW() WHERE user_id = $1 RETURNING id, user_id, company_name, registration_number, industry, website_url, employee_count, business_type, gst_number, contact_name, contact_email, contact_phone, address_line1, city, state, country, postal_code, status, free_job_slots, purchased_job_slots, free_contact_views, purchased_contact_views, created_at, updated_at "#, user_id ) .fetch_one(pool) .await?; Ok(profile) } }