From 83c62a1c5e71f2bc3ff4a81be350383953d81969 Mon Sep 17 00:00:00 2001 From: Ashwin Kumar Date: Thu, 9 Apr 2026 07:40:15 +0200 Subject: [PATCH] fix: convert all SQLx macros to runtime API, remove SQLX_OFFLINE requirement --- apps/catering_services/Dockerfile | 1 - apps/catering_services/src/admin.rs | 10 +- apps/companies/Dockerfile | 1 - apps/cron/Dockerfile | 1 - apps/customers/Dockerfile | 1 - apps/customers/src/admin.rs | 5 +- apps/developers/Dockerfile | 1 - apps/developers/src/admin.rs | 10 +- apps/employees/Dockerfile | 1 - apps/fitness_trainers/Dockerfile | 1 - apps/fitness_trainers/src/admin.rs | 10 +- apps/gateway/Dockerfile | 1 - apps/graphic_designers/Dockerfile | 1 - apps/graphic_designers/src/admin.rs | 10 +- apps/job_seekers/Dockerfile | 1 - apps/makeup_artists/Dockerfile | 1 - apps/makeup_artists/src/admin.rs | 10 +- apps/payments/Dockerfile | 1 - apps/payments/src/main.rs | 71 +++++++------ apps/photographers/Dockerfile | 1 - apps/photographers/src/admin.rs | 10 +- apps/social_media_managers/Dockerfile | 1 - apps/social_media_managers/src/admin.rs | 10 +- apps/tutors/Dockerfile | 1 - apps/tutors/src/admin.rs | 10 +- apps/ugc_content_creators/Dockerfile | 1 - apps/users/Dockerfile | 1 - apps/video_editors/Dockerfile | 1 - apps/video_editors/src/admin.rs | 10 +- crates/db/src/models/application.rs | 47 ++++----- crates/db/src/models/catering_service.rs | 22 ++-- crates/db/src/models/company.rs | 59 +++++------ crates/db/src/models/config.rs | 101 +++++++++---------- crates/db/src/models/customer.rs | 53 +++++----- crates/db/src/models/developer.rs | 22 ++-- crates/db/src/models/employee.rs | 3 +- crates/db/src/models/fitness_trainer.rs | 22 ++-- crates/db/src/models/graphic_designer.rs | 22 ++-- crates/db/src/models/job.rs | 95 +++++++++-------- crates/db/src/models/job_seeker.rs | 58 +++++------ crates/db/src/models/lead_request.rs | 36 ++++--- crates/db/src/models/makeup_artist.rs | 22 ++-- crates/db/src/models/onboarding_state.rs | 31 +++--- crates/db/src/models/photographer.rs | 22 ++-- crates/db/src/models/professional.rs | 41 ++++---- crates/db/src/models/requirement.rs | 85 ++++++++-------- crates/db/src/models/role.rs | 19 ++-- crates/db/src/models/social_media_manager.rs | 22 ++-- crates/db/src/models/tutor.rs | 22 ++-- crates/db/src/models/ugc_content_creator.rs | 22 ++-- crates/db/src/models/user.rs | 93 ++++++++--------- crates/db/src/models/video_editor.rs | 22 ++-- 52 files changed, 553 insertions(+), 572 deletions(-) diff --git a/apps/catering_services/Dockerfile b/apps/catering_services/Dockerfile index 72f3196..570cbbe 100644 --- a/apps/catering_services/Dockerfile +++ b/apps/catering_services/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin catering_services diff --git a/apps/catering_services/src/admin.rs b/apps/catering_services/src/admin.rs index ae8e7bf..e065c42 100644 --- a/apps/catering_services/src/admin.rs +++ b/apps/catering_services/src/admin.rs @@ -40,14 +40,13 @@ pub fn router() -> Router { async fn list_catering_services( State(state): State, ) -> Result { - let services = sqlx::query_as!( - CateringServiceProfile, + let services = sqlx::query_as::<_, CateringServiceProfile>( r#" SELECT id, user_id, business_name, bio, location, custom_data, status, created_at, updated_at FROM catering_service_profiles ORDER BY created_at DESC LIMIT 100 - "# + "#, ) .fetch_all(&state.pool) .await @@ -61,15 +60,14 @@ async fn get_catering_service( State(state): State, Path(id): Path, ) -> Result { - let service = sqlx::query_as!( - CateringServiceProfile, + let service = sqlx::query_as::<_, CateringServiceProfile>( r#" SELECT id, user_id, business_name, bio, location, custom_data, status, created_at, updated_at FROM catering_service_profiles WHERE id = $1 "#, - id ) + .bind(id) .fetch_optional(&state.pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?; diff --git a/apps/companies/Dockerfile b/apps/companies/Dockerfile index b54bd05..da287d2 100644 --- a/apps/companies/Dockerfile +++ b/apps/companies/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin companies diff --git a/apps/cron/Dockerfile b/apps/cron/Dockerfile index 35c5f59..93a29cd 100644 --- a/apps/cron/Dockerfile +++ b/apps/cron/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin cron diff --git a/apps/customers/Dockerfile b/apps/customers/Dockerfile index ae22b52..20dd572 100644 --- a/apps/customers/Dockerfile +++ b/apps/customers/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin customers diff --git a/apps/customers/src/admin.rs b/apps/customers/src/admin.rs index 1055395..18b07f4 100644 --- a/apps/customers/src/admin.rs +++ b/apps/customers/src/admin.rs @@ -40,8 +40,7 @@ pub fn router() -> Router { async fn list_leads( State(state): State, ) -> Result { - let requirements = sqlx::query_as!( - Requirement, + let requirements = sqlx::query_as::<_, Requirement>( r#" SELECT id, customer_id, profession_key, title, description, location, budget, preferred_date, extra_data_json, status, rejection_reason, request_count, accepted_count, @@ -49,7 +48,7 @@ async fn list_leads( FROM requirements ORDER BY created_at DESC LIMIT 100 - "# + "#, ) .fetch_all(&state.pool) .await diff --git a/apps/developers/Dockerfile b/apps/developers/Dockerfile index c60d498..ec39515 100644 --- a/apps/developers/Dockerfile +++ b/apps/developers/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin developers diff --git a/apps/developers/src/admin.rs b/apps/developers/src/admin.rs index 28cf770..e7a43a6 100644 --- a/apps/developers/src/admin.rs +++ b/apps/developers/src/admin.rs @@ -40,14 +40,13 @@ pub fn router() -> Router { async fn list_developers( State(state): State, ) -> Result { - let developers = sqlx::query_as!( - DeveloperProfile, + let developers = sqlx::query_as::<_, DeveloperProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM developer_profiles ORDER BY created_at DESC LIMIT 100 - "# + "#, ) .fetch_all(&state.pool) .await @@ -61,15 +60,14 @@ async fn get_developer( State(state): State, Path(id): Path, ) -> Result { - let developer = sqlx::query_as!( - DeveloperProfile, + let developer = sqlx::query_as::<_, DeveloperProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM developer_profiles WHERE id = $1 "#, - id ) + .bind(id) .fetch_optional(&state.pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?; diff --git a/apps/employees/Dockerfile b/apps/employees/Dockerfile index fec2a45..22b99ca 100644 --- a/apps/employees/Dockerfile +++ b/apps/employees/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin employees diff --git a/apps/fitness_trainers/Dockerfile b/apps/fitness_trainers/Dockerfile index 59aa22a..40a936d 100644 --- a/apps/fitness_trainers/Dockerfile +++ b/apps/fitness_trainers/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin fitness_trainers diff --git a/apps/fitness_trainers/src/admin.rs b/apps/fitness_trainers/src/admin.rs index 16b393a..415aa46 100644 --- a/apps/fitness_trainers/src/admin.rs +++ b/apps/fitness_trainers/src/admin.rs @@ -40,14 +40,13 @@ pub fn router() -> Router { async fn list_fitness_trainers( State(state): State, ) -> Result { - let trainers = sqlx::query_as!( - FitnessTrainerProfile, + let trainers = sqlx::query_as::<_, FitnessTrainerProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM fitness_trainer_profiles ORDER BY created_at DESC LIMIT 100 - "# + "#, ) .fetch_all(&state.pool) .await @@ -61,15 +60,14 @@ async fn get_fitness_trainer( State(state): State, Path(id): Path, ) -> Result { - let trainer = sqlx::query_as!( - FitnessTrainerProfile, + let trainer = sqlx::query_as::<_, FitnessTrainerProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM fitness_trainer_profiles WHERE id = $1 "#, - id ) + .bind(id) .fetch_optional(&state.pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?; diff --git a/apps/gateway/Dockerfile b/apps/gateway/Dockerfile index cb03a5a..7a13570 100644 --- a/apps/gateway/Dockerfile +++ b/apps/gateway/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin gateway diff --git a/apps/graphic_designers/Dockerfile b/apps/graphic_designers/Dockerfile index dbbada2..fc7faf5 100644 --- a/apps/graphic_designers/Dockerfile +++ b/apps/graphic_designers/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin graphic_designers diff --git a/apps/graphic_designers/src/admin.rs b/apps/graphic_designers/src/admin.rs index 18faf78..30c0959 100644 --- a/apps/graphic_designers/src/admin.rs +++ b/apps/graphic_designers/src/admin.rs @@ -40,14 +40,13 @@ pub fn router() -> Router { async fn list_graphic_designers( State(state): State, ) -> Result { - let designers = sqlx::query_as!( - GraphicDesignerProfile, + let designers = sqlx::query_as::<_, GraphicDesignerProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM graphic_designer_profiles ORDER BY created_at DESC LIMIT 100 - "# + "#, ) .fetch_all(&state.pool) .await @@ -61,15 +60,14 @@ async fn get_graphic_designer( State(state): State, Path(id): Path, ) -> Result { - let designer = sqlx::query_as!( - GraphicDesignerProfile, + let designer = sqlx::query_as::<_, GraphicDesignerProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM graphic_designer_profiles WHERE id = $1 "#, - id ) + .bind(id) .fetch_optional(&state.pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?; diff --git a/apps/job_seekers/Dockerfile b/apps/job_seekers/Dockerfile index e071528..db6ca93 100644 --- a/apps/job_seekers/Dockerfile +++ b/apps/job_seekers/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin job_seekers diff --git a/apps/makeup_artists/Dockerfile b/apps/makeup_artists/Dockerfile index d7876ce..f9cd75b 100644 --- a/apps/makeup_artists/Dockerfile +++ b/apps/makeup_artists/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin makeup_artists diff --git a/apps/makeup_artists/src/admin.rs b/apps/makeup_artists/src/admin.rs index a924473..704440d 100644 --- a/apps/makeup_artists/src/admin.rs +++ b/apps/makeup_artists/src/admin.rs @@ -40,14 +40,13 @@ pub fn router() -> Router { async fn list_makeup_artists( State(state): State, ) -> Result { - let artists = sqlx::query_as!( - MakeupArtistProfile, + let artists = sqlx::query_as::<_, MakeupArtistProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM makeup_artist_profiles ORDER BY created_at DESC LIMIT 100 - "# + "#, ) .fetch_all(&state.pool) .await @@ -61,15 +60,14 @@ async fn get_makeup_artist( State(state): State, Path(id): Path, ) -> Result { - let artist = sqlx::query_as!( - MakeupArtistProfile, + let artist = sqlx::query_as::<_, MakeupArtistProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM makeup_artist_profiles WHERE id = $1 "#, - id ) + .bind(id) .fetch_optional(&state.pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?; diff --git a/apps/payments/Dockerfile b/apps/payments/Dockerfile index 7a67a95..226a3b9 100644 --- a/apps/payments/Dockerfile +++ b/apps/payments/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin payments diff --git a/apps/payments/src/main.rs b/apps/payments/src/main.rs index bb7ad66..60d5e38 100644 --- a/apps/payments/src/main.rs +++ b/apps/payments/src/main.rs @@ -10,6 +10,7 @@ use std::net::SocketAddr; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; use uuid::Uuid; use sqlx::postgres::PgPool; +use sqlx::FromRow; #[derive(Clone)] struct AppState { @@ -57,6 +58,18 @@ struct PaymentStatusResponse { currency: String, } +#[derive(Debug, FromRow)] +struct PricingPackageRow { + tracecoins_amount: i32, +} + +#[derive(Debug, FromRow)] +struct PaymentRow { + id: Uuid, + user_id: Uuid, + tracecoins_credited: i32, +} + async fn create_order( auth: AuthUser, State(state): State, @@ -69,10 +82,10 @@ async fn create_order( let package_id = Uuid::parse_str(package_id_str).map_err(|_| (StatusCode::BAD_REQUEST, "Invalid package id".to_string()))?; // Fetch package to get tracecoins amount - let package = sqlx::query!( + let package = sqlx::query_as::<_, PricingPackageRow>( "SELECT tracecoins_amount FROM pricing_packages WHERE id = $1 AND is_active = true", - package_id ) + .bind(package_id) .fetch_optional(&state.pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?; @@ -118,14 +131,14 @@ async fn create_order( .to_string(); // Insert payment record - sqlx::query!( + sqlx::query( "INSERT INTO payments (user_id, package_id, razorpay_order_id, amount_inr, tracecoins_credited, status) VALUES ($1, $2, $3, $4, $5, 'PENDING')", - auth.user_id, - package_id, - order_id, - payload.amount as i64, - tracecoins_credited ) + .bind(auth.user_id) + .bind(package_id) + .bind(&order_id) + .bind(payload.amount as i64) + .bind(tracecoins_credited) .execute(&state.pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?; @@ -173,10 +186,10 @@ async fn verify_payment( } // Find pending payment by razorpay_order_id - let payment = sqlx::query!( + let payment = sqlx::query_as::<_, PaymentRow>( "SELECT id, user_id, tracecoins_credited FROM payments WHERE razorpay_order_id = $1 AND status = 'PENDING'", - payload.order_id ) + .bind(&payload.order_id) .fetch_optional(&state.pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?; @@ -192,41 +205,41 @@ async fn verify_payment( } // Update payment status to SUCCESS - sqlx::query!( + sqlx::query( "UPDATE payments SET status = 'SUCCESS', verified_at = NOW(), razorpay_payment_id = $1 WHERE id = $2", - payload.payment_id, - payment.id ) + .bind(&payload.payment_id) + .bind(payment.id) .execute(&state.pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?; // Credit wallet (increase balance) - sqlx::query!( + sqlx::query( "INSERT INTO tracecoin_wallets (user_id, balance, reserved) VALUES ($1, $2, 0) ON CONFLICT (user_id) DO UPDATE SET balance = tracecoin_wallets.balance + excluded.balance", - payment.user_id, - payment.tracecoins_credited ) + .bind(payment.user_id) + .bind(payment.tracecoins_credited) .execute(&state.pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?; // Get wallet id for ledger - match sqlx::query_scalar!( + match sqlx::query_scalar::<_, Uuid>( "SELECT id FROM tracecoin_wallets WHERE user_id = $1", - payment.user_id ) + .bind(payment.user_id) .fetch_optional(&state.pool) .await { Ok(Some(wallet_id)) => { - sqlx::query!( + sqlx::query( "INSERT INTO tracecoin_ledger (wallet_id, type, amount, reason, reference_id) VALUES ($1, 'CREDIT', $2, $3, $4)", - wallet_id, - payment.tracecoins_credited as i64, - "PURCHASE", - payment.id ) + .bind(wallet_id) + .bind(payment.tracecoins_credited as i64) + .bind("PURCHASE") + .bind(payment.id) .execute(&state.pool) .await .ok(); @@ -235,17 +248,17 @@ async fn verify_payment( } // Send notification to user about successful purchase - let _ = sqlx::query!( + let _ = sqlx::query( r#" INSERT INTO notifications (user_id, title, body, type, reference_id) VALUES ($1, $2, $3, $4, $5) "#, - payment.user_id, - "Tracecoins Purchased Successfully", - format!("Your {} Tracecoin package has been credited to your wallet.", payment.tracecoins_credited), - "PAYMENT", - payment.id ) + .bind(payment.user_id) + .bind("Tracecoins Purchased Successfully") + .bind(format!("Your {} Tracecoin package has been credited to your wallet.", payment.tracecoins_credited)) + .bind("PAYMENT") + .bind(payment.id) .execute(&state.pool) .await .ok(); diff --git a/apps/photographers/Dockerfile b/apps/photographers/Dockerfile index 9e1467a..e31c3e7 100644 --- a/apps/photographers/Dockerfile +++ b/apps/photographers/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin photographers diff --git a/apps/photographers/src/admin.rs b/apps/photographers/src/admin.rs index d4b2416..2375b0e 100644 --- a/apps/photographers/src/admin.rs +++ b/apps/photographers/src/admin.rs @@ -40,14 +40,13 @@ pub fn router() -> Router { async fn list_photographers( State(state): State, ) -> Result { - let photographers = sqlx::query_as!( - PhotographerProfile, + let photographers = sqlx::query_as::<_, PhotographerProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM photographer_profiles ORDER BY created_at DESC LIMIT 100 - "# + "#, ) .fetch_all(&state.pool) .await @@ -61,15 +60,14 @@ async fn get_photographer( State(state): State, Path(id): Path, ) -> Result { - let photographer = sqlx::query_as!( - PhotographerProfile, + let photographer = sqlx::query_as::<_, PhotographerProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM photographer_profiles WHERE id = $1 "#, - id ) + .bind(id) .fetch_optional(&state.pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?; diff --git a/apps/social_media_managers/Dockerfile b/apps/social_media_managers/Dockerfile index b3313c3..0606a06 100644 --- a/apps/social_media_managers/Dockerfile +++ b/apps/social_media_managers/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin social_media_managers diff --git a/apps/social_media_managers/src/admin.rs b/apps/social_media_managers/src/admin.rs index d674627..8c357d8 100644 --- a/apps/social_media_managers/src/admin.rs +++ b/apps/social_media_managers/src/admin.rs @@ -40,14 +40,13 @@ pub fn router() -> Router { async fn list_social_media_managers( State(state): State, ) -> Result { - let managers = sqlx::query_as!( - SocialMediaManagerProfile, + let managers = sqlx::query_as::<_, SocialMediaManagerProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM social_media_manager_profiles ORDER BY created_at DESC LIMIT 100 - "# + "#, ) .fetch_all(&state.pool) .await @@ -61,15 +60,14 @@ async fn get_social_media_manager( State(state): State, Path(id): Path, ) -> Result { - let manager = sqlx::query_as!( - SocialMediaManagerProfile, + let manager = sqlx::query_as::<_, SocialMediaManagerProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM social_media_manager_profiles WHERE id = $1 "#, - id ) + .bind(id) .fetch_optional(&state.pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?; diff --git a/apps/tutors/Dockerfile b/apps/tutors/Dockerfile index 69c02ec..8906777 100644 --- a/apps/tutors/Dockerfile +++ b/apps/tutors/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin tutors diff --git a/apps/tutors/src/admin.rs b/apps/tutors/src/admin.rs index 3df9b41..f0ed453 100644 --- a/apps/tutors/src/admin.rs +++ b/apps/tutors/src/admin.rs @@ -43,14 +43,13 @@ pub fn router() -> Router { async fn list_tutors( State(state): State, ) -> Result { - let tutors = sqlx::query_as!( - TutorProfile, + let tutors = sqlx::query_as::<_, TutorProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM tutor_profiles ORDER BY created_at DESC LIMIT 100 - "# + "#, ) .fetch_all(&state.pool) .await @@ -64,15 +63,14 @@ async fn get_tutor( State(state): State, Path(id): Path, ) -> Result { - let tutor = sqlx::query_as!( - TutorProfile, + let tutor = sqlx::query_as::<_, TutorProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM tutor_profiles WHERE id = $1 "#, - id ) + .bind(id) .fetch_optional(&state.pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?; diff --git a/apps/ugc_content_creators/Dockerfile b/apps/ugc_content_creators/Dockerfile index cd3bfa1..a1e598b 100644 --- a/apps/ugc_content_creators/Dockerfile +++ b/apps/ugc_content_creators/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin ugc_content_creators diff --git a/apps/users/Dockerfile b/apps/users/Dockerfile index 6784eb4..9bea215 100644 --- a/apps/users/Dockerfile +++ b/apps/users/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin users diff --git a/apps/video_editors/Dockerfile b/apps/video_editors/Dockerfile index 4b353d5..deff729 100644 --- a/apps/video_editors/Dockerfile +++ b/apps/video_editors/Dockerfile @@ -11,7 +11,6 @@ COPY Cargo.toml Cargo.lock ./ COPY crates ./crates COPY apps ./apps -ENV SQLX_OFFLINE=true ENV CARGO_BUILD_JOBS=2 RUN cargo build --release --bin video_editors diff --git a/apps/video_editors/src/admin.rs b/apps/video_editors/src/admin.rs index 04bd56f..9853946 100644 --- a/apps/video_editors/src/admin.rs +++ b/apps/video_editors/src/admin.rs @@ -40,14 +40,13 @@ pub fn router() -> Router { async fn list_video_editors( State(state): State, ) -> Result { - let editors = sqlx::query_as!( - VideoEditorProfile, + let editors = sqlx::query_as::<_, VideoEditorProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM video_editor_profiles ORDER BY created_at DESC LIMIT 100 - "# + "#, ) .fetch_all(&state.pool) .await @@ -61,15 +60,14 @@ async fn get_video_editor( State(state): State, Path(id): Path, ) -> Result { - let editor = sqlx::query_as!( - VideoEditorProfile, + let editor = sqlx::query_as::<_, VideoEditorProfile>( r#" SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM video_editor_profiles WHERE id = $1 "#, - id ) + .bind(id) .fetch_optional(&state.pool) .await .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, format!("DB error: {e}")))?; diff --git a/crates/db/src/models/application.rs b/crates/db/src/models/application.rs index ca1b8bd..136573e 100644 --- a/crates/db/src/models/application.rs +++ b/crates/db/src/models/application.rs @@ -31,18 +31,17 @@ impl ApplicationRepository { pool: &PgPool, payload: CreateApplicationPayload, ) -> Result { - let app = sqlx::query_as!( - Application, + let app = sqlx::query_as::<_, Application>( r#" INSERT INTO applications (job_id, job_seeker_id, cover_letter, resume_url) VALUES ($1, $2, $3, $4) RETURNING * "#, - payload.job_id, - payload.job_seeker_id, - payload.cover_letter, - payload.resume_url ) + .bind(payload.job_id) + .bind(payload.job_seeker_id) + .bind(payload.cover_letter) + .bind(payload.resume_url) .fetch_one(pool) .await?; @@ -50,7 +49,8 @@ impl ApplicationRepository { } pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!(Application, "SELECT * FROM applications WHERE id = $1", id) + sqlx::query_as::<_, Application>("SELECT * FROM applications WHERE id = $1") + .bind(id) .fetch_optional(pool) .await } @@ -63,19 +63,18 @@ impl ApplicationRepository { limit: i64, ) -> Result, sqlx::Error> { let offset = (page - 1) * limit; - let apps = sqlx::query_as!( - Application, + let apps = sqlx::query_as::<_, Application>( r#" - SELECT * FROM applications + SELECT * FROM applications WHERE job_id = $1 AND ($2::VARCHAR IS NULL OR status = $2) ORDER BY applied_at DESC LIMIT $3 OFFSET $4 "#, - job_id, - status, - limit, - offset ) + .bind(job_id) + .bind(status) + .bind(limit) + .bind(offset) .fetch_all(pool) .await?; @@ -89,18 +88,17 @@ impl ApplicationRepository { limit: i64, ) -> Result, sqlx::Error> { let offset = (page - 1) * limit; - let apps = sqlx::query_as!( - Application, + let apps = sqlx::query_as::<_, Application>( r#" SELECT * FROM applications WHERE job_seeker_id = $1 ORDER BY applied_at DESC LIMIT $2 OFFSET $3 "#, - job_seeker_id, - limit, - offset ) + .bind(job_seeker_id) + .bind(limit) + .bind(offset) .fetch_all(pool) .await?; Ok(apps) @@ -111,22 +109,21 @@ impl ApplicationRepository { id: Uuid, status: &str, ) -> Result { - let app = sqlx::query_as!( - Application, + let app = sqlx::query_as::<_, Application>( "UPDATE applications SET status = $1, updated_at = NOW() WHERE id = $2 RETURNING *", - status, - id ) + .bind(status) + .bind(id) .fetch_one(pool) .await?; Ok(app) } pub async fn mark_contact_viewed(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> { - sqlx::query!( + sqlx::query( "UPDATE applications SET contact_viewed = true WHERE id = $1", - id ) + .bind(id) .execute(pool) .await?; Ok(()) diff --git a/crates/db/src/models/catering_service.rs b/crates/db/src/models/catering_service.rs index fd37afc..57e812a 100644 --- a/crates/db/src/models/catering_service.rs +++ b/crates/db/src/models/catering_service.rs @@ -30,19 +30,19 @@ pub struct CateringServiceRepository; impl CateringServiceRepository { pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!( - CateringServiceProfile, + sqlx::query_as::<_, CateringServiceProfile>( r#"SELECT id, user_id, business_name, bio, location, custom_data, status, created_at, updated_at FROM catering_service_profiles WHERE user_id = $1"#, - user_id - ).fetch_optional(pool).await + ) + .bind(user_id) + .fetch_optional(pool) + .await } pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertCateringServiceProfilePayload) -> Result { - sqlx::query_as!( - CateringServiceProfile, + sqlx::query_as::<_, CateringServiceProfile>( r#"INSERT INTO catering_service_profiles (user_id, business_name, bio, location, custom_data) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (user_id) DO UPDATE SET @@ -54,7 +54,13 @@ impl CateringServiceRepository { RETURNING id, user_id, business_name, bio, location, custom_data, status, created_at, updated_at"#, - user_id, p.business_name, p.bio, p.location, p.custom_data - ).fetch_one(pool).await + ) + .bind(user_id) + .bind(p.business_name) + .bind(p.bio) + .bind(p.location) + .bind(p.custom_data) + .fetch_one(pool) + .await } } diff --git a/crates/db/src/models/company.rs b/crates/db/src/models/company.rs index 883177a..728c374 100644 --- a/crates/db/src/models/company.rs +++ b/crates/db/src/models/company.rs @@ -56,11 +56,10 @@ impl CompanyRepository { pool: &PgPool, user_id: Uuid, ) -> Result, sqlx::Error> { - let profile = sqlx::query_as!( - CompanyProfile, + let profile = sqlx::query_as::<_, CompanyProfile>( r#" - SELECT - id, user_id, company_name, registration_number, industry, + 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, @@ -69,8 +68,8 @@ impl CompanyRepository { FROM company_profiles WHERE user_id = $1 "#, - user_id ) + .bind(user_id) .fetch_optional(pool) .await?; @@ -82,12 +81,11 @@ impl CompanyRepository { user_id: Uuid, payload: UpsertCompanyProfilePayload, ) -> Result { - let profile = sqlx::query_as!( - CompanyProfile, + 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, + 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') @@ -111,30 +109,30 @@ impl CompanyRepository { ELSE 'PENDING' END, updated_at = NOW() - RETURNING - id, user_id, company_name, registration_number, industry, + 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 ) + .bind(user_id) + .bind(payload.company_name) + .bind(payload.registration_number) + .bind(payload.industry) + .bind(payload.website_url) + .bind(payload.employee_count) + .bind(payload.business_type) + .bind(payload.gst_number) + .bind(payload.contact_name) + .bind(payload.contact_email) + .bind(payload.contact_phone) + .bind(payload.address_line1) + .bind(payload.city) + .bind(payload.state) + .bind(payload.postal_code) .fetch_one(pool) .await?; @@ -145,22 +143,21 @@ impl CompanyRepository { pool: &PgPool, user_id: Uuid, ) -> Result { - let profile = sqlx::query_as!( - CompanyProfile, + 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, + 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 ) + .bind(user_id) .fetch_one(pool) .await?; diff --git a/crates/db/src/models/config.rs b/crates/db/src/models/config.rs index b9460a4..b6f3fd7 100644 --- a/crates/db/src/models/config.rs +++ b/crates/db/src/models/config.rs @@ -82,33 +82,32 @@ impl ConfigRepository { payload: CreateOnboardingConfigPayload, ) -> Result { // Soft-disable previous active configs for this role - sqlx::query!( + sqlx::query( r#" UPDATE onboarding_configs SET is_active = false WHERE role_id = $1 AND is_active = true "#, - payload.role_id ) + .bind(payload.role_id) .execute(pool) .await?; // Insert new config - let config = sqlx::query_as!( - OnboardingConfig, + let config = sqlx::query_as::<_, OnboardingConfig>( r#" INSERT INTO onboarding_configs (role_id, schema_json, version, is_active) VALUES ( - $1, - $2, + $1, + $2, COALESCE((SELECT MAX(version) FROM onboarding_configs WHERE role_id = $1), 0) + 1, true ) RETURNING id, role_id, schema_json, version, is_active, updated_at "#, - payload.role_id, - payload.schema_json ) + .bind(payload.role_id) + .bind(payload.schema_json) .fetch_one(pool) .await?; @@ -119,15 +118,14 @@ impl ConfigRepository { pool: &PgPool, role_id: Uuid, ) -> Result { - let config = sqlx::query_as!( - OnboardingConfig, + let config = sqlx::query_as::<_, OnboardingConfig>( r#" SELECT id, role_id, schema_json, version, is_active, updated_at FROM onboarding_configs WHERE role_id = $1 AND is_active = true "#, - role_id ) + .bind(role_id) .fetch_one(pool) .await?; @@ -137,16 +135,15 @@ impl ConfigRepository { pub async fn get_all_onboarding_configs( pool: &PgPool, ) -> Result, sqlx::Error> { - let configs = sqlx::query_as!( - OnboardingConfigListItem, + let configs = sqlx::query_as::<_, OnboardingConfigListItem>( r#" - SELECT - c.id, c.role_id, r.key as role_key, + SELECT + c.id, c.role_id, r.key as role_key, c.version, c.is_active, c.updated_at FROM onboarding_configs c JOIN roles r ON c.role_id = r.id ORDER BY c.updated_at DESC - "# + "#, ) .fetch_all(pool) .await?; @@ -158,16 +155,15 @@ impl ConfigRepository { pool: &PgPool, role_key: &str, ) -> Result { - let config = sqlx::query_as!( - OnboardingConfig, + let config = sqlx::query_as::<_, OnboardingConfig>( r#" SELECT c.id, c.role_id, c.schema_json, c.version, c.is_active, c.updated_at FROM onboarding_configs c JOIN roles r ON c.role_id = r.id WHERE r.key = $1 AND c.is_active = true "#, - role_key.to_uppercase() ) + .bind(role_key.to_uppercase()) .fetch_one(pool) .await?; @@ -179,36 +175,35 @@ impl ConfigRepository { payload: CreateDashboardConfigPayload, ) -> Result { // Soft-disable previous active configs for this role - sqlx::query!( + sqlx::query( r#" UPDATE dashboard_configs SET is_active = false WHERE role_id = $1 AND audience = $2::text AND is_active = true "#, - payload.role_id, - payload.audience ) + .bind(payload.role_id) + .bind(&payload.audience) .execute(pool) .await?; // Insert new config - let config = sqlx::query_as!( - DashboardConfig, + let config = sqlx::query_as::<_, DashboardConfig>( r#" INSERT INTO dashboard_configs (role_id, audience, config_json, version, is_active) VALUES ( - $1, - $2::text, + $1, + $2::text, $3, COALESCE((SELECT MAX(version) FROM dashboard_configs WHERE role_id = $1 AND audience = $2::text), 0) + 1, true ) RETURNING id, role_id, audience, config_json, version, is_active, updated_at "#, - payload.role_id, - payload.audience, - payload.config_json ) + .bind(payload.role_id) + .bind(&payload.audience) + .bind(payload.config_json) .fetch_one(pool) .await?; @@ -220,16 +215,15 @@ impl ConfigRepository { role_id: Uuid, audience: &str, ) -> Result { - let config = sqlx::query_as!( - DashboardConfig, + let config = sqlx::query_as::<_, DashboardConfig>( r#" SELECT id, role_id, audience, config_json, version, is_active, updated_at FROM dashboard_configs WHERE role_id = $1 AND audience = $2 AND is_active = true "#, - role_id, - audience ) + .bind(role_id) + .bind(audience) .fetch_one(pool) .await?; @@ -239,16 +233,15 @@ impl ConfigRepository { pub async fn get_all_dashboard_configs( pool: &PgPool, ) -> Result, sqlx::Error> { - let configs = sqlx::query_as!( - DashboardConfigListItem, + let configs = sqlx::query_as::<_, DashboardConfigListItem>( r#" - SELECT - c.id, c.role_id, r.key as role_key, c.audience, + SELECT + c.id, c.role_id, r.key as role_key, c.audience, c.version, c.is_active, c.updated_at FROM dashboard_configs c JOIN roles r ON c.role_id = r.id ORDER BY c.updated_at DESC - "# + "#, ) .fetch_all(pool) .await?; @@ -261,17 +254,16 @@ impl ConfigRepository { role_key: &str, audience: &str, ) -> Result { - let config = sqlx::query_as!( - DashboardConfig, + let config = sqlx::query_as::<_, DashboardConfig>( r#" SELECT c.id, c.role_id, c.audience, c.config_json, c.version, c.is_active, c.updated_at FROM dashboard_configs c JOIN roles r ON c.role_id = r.id WHERE r.key = $1 AND c.audience = $2 AND c.is_active = true "#, - role_key.to_uppercase(), - audience ) + .bind(role_key.to_uppercase()) + .bind(audience) .fetch_one(pool) .await?; @@ -283,33 +275,32 @@ impl ConfigRepository { payload: CreateRuntimeConfigPayload, ) -> Result { // Soft-disable previous active configs for this role - sqlx::query!( + sqlx::query( r#" UPDATE runtime_configs SET is_active = false WHERE role_id = $1 AND is_active = true "#, - payload.role_id ) + .bind(payload.role_id) .execute(pool) .await?; // Insert new config - let config = sqlx::query_as!( - RuntimeConfig, + let config = sqlx::query_as::<_, RuntimeConfig>( r#" INSERT INTO runtime_configs (role_id, config_json, version, is_active) VALUES ( - $1, - $2, + $1, + $2, COALESCE((SELECT MAX(version) FROM runtime_configs WHERE role_id = $1), 0) + 1, true ) RETURNING id, role_id, config_json, version, is_active, updated_at "#, - payload.role_id, - payload.config_json ) + .bind(payload.role_id) + .bind(payload.config_json) .fetch_one(pool) .await?; @@ -320,15 +311,14 @@ impl ConfigRepository { pool: &PgPool, role_id: Uuid, ) -> Result { - let config = sqlx::query_as!( - RuntimeConfig, + let config = sqlx::query_as::<_, RuntimeConfig>( r#" SELECT id, role_id, config_json, version, is_active, updated_at FROM runtime_configs WHERE role_id = $1 AND is_active = true "#, - role_id ) + .bind(role_id) .fetch_one(pool) .await?; @@ -339,16 +329,15 @@ impl ConfigRepository { pool: &PgPool, role_key: &str, ) -> Result { - let config = sqlx::query_as!( - RuntimeConfig, + let config = sqlx::query_as::<_, RuntimeConfig>( r#" SELECT rc.id, rc.role_id, rc.config_json, rc.version, rc.is_active, rc.updated_at FROM runtime_configs rc JOIN roles r ON rc.role_id = r.id WHERE r.key = $1 AND rc.is_active = true "#, - role_key.to_uppercase() ) + .bind(role_key.to_uppercase()) .fetch_one(pool) .await?; diff --git a/crates/db/src/models/customer.rs b/crates/db/src/models/customer.rs index 6012f1a..0f3a5c4 100644 --- a/crates/db/src/models/customer.rs +++ b/crates/db/src/models/customer.rs @@ -39,18 +39,17 @@ impl CustomerRepository { pool: &PgPool, user_id: Uuid, ) -> Result, sqlx::Error> { - let profile = sqlx::query_as!( - CustomerProfile, + let profile = sqlx::query_as::<_, CustomerProfile>( r#" - SELECT - id, user_id, full_name, phone, city, area, preferred_professions, - active_requirement_count, status, bio, experience_years, custom_data, + SELECT + id, user_id, full_name, phone, city, area, preferred_professions, + active_requirement_count, status, bio, experience_years, custom_data, created_at, updated_at FROM customer_profiles WHERE user_id = $1 "#, - user_id ) + .bind(user_id) .fetch_optional(pool) .await?; @@ -62,8 +61,7 @@ impl CustomerRepository { user_id: Uuid, payload: UpsertCustomerProfilePayload, ) -> Result { - let profile = sqlx::query_as!( - CustomerProfile, + let profile = sqlx::query_as::<_, CustomerProfile>( r#" INSERT INTO customer_profiles ( user_id, full_name, phone, city, area, preferred_professions, bio, custom_data, status @@ -82,20 +80,20 @@ impl CustomerRepository { ELSE 'PENDING' END, updated_at = NOW() - RETURNING - id, user_id, full_name, phone, city, area, preferred_professions, - active_requirement_count, status, bio, experience_years, custom_data, + RETURNING + id, user_id, full_name, phone, city, area, preferred_professions, + active_requirement_count, status, bio, experience_years, custom_data, created_at, updated_at "#, - user_id, - payload.full_name, - payload.phone, - payload.city, - payload.area, - &payload.preferred_professions.unwrap_or_default(), - payload.bio, - payload.custom_data ) + .bind(user_id) + .bind(payload.full_name) + .bind(payload.phone) + .bind(payload.city) + .bind(payload.area) + .bind(payload.preferred_professions.unwrap_or_default()) + .bind(payload.bio) + .bind(payload.custom_data) .fetch_one(pool) .await?; @@ -107,11 +105,11 @@ impl CustomerRepository { id: Uuid, delta: i32, ) -> Result<(), sqlx::Error> { - sqlx::query!( + sqlx::query( "UPDATE customer_profiles SET active_requirement_count = active_requirement_count + $1 WHERE id = $2", - delta, - id ) + .bind(delta) + .bind(id) .execute(pool) .await?; Ok(()) @@ -121,19 +119,18 @@ impl CustomerRepository { pool: &PgPool, user_id: Uuid, ) -> Result { - let profile = sqlx::query_as!( - CustomerProfile, + let profile = sqlx::query_as::<_, CustomerProfile>( r#" UPDATE customer_profiles SET status = 'PENDING_REVIEW', updated_at = NOW() WHERE user_id = $1 - RETURNING - id, user_id, full_name, phone, city, area, preferred_professions, - active_requirement_count, status, bio, experience_years, custom_data, + RETURNING + id, user_id, full_name, phone, city, area, preferred_professions, + active_requirement_count, status, bio, experience_years, custom_data, created_at, updated_at "#, - user_id ) + .bind(user_id) .fetch_one(pool) .await?; diff --git a/crates/db/src/models/developer.rs b/crates/db/src/models/developer.rs index 054c570..2ac2c82 100644 --- a/crates/db/src/models/developer.rs +++ b/crates/db/src/models/developer.rs @@ -28,19 +28,19 @@ pub struct DeveloperRepository; impl DeveloperRepository { pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!( - DeveloperProfile, + sqlx::query_as::<_, DeveloperProfile>( r#"SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM developer_profiles WHERE user_id = $1"#, - user_id - ).fetch_optional(pool).await + ) + .bind(user_id) + .fetch_optional(pool) + .await } pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertDeveloperProfilePayload) -> Result { - sqlx::query_as!( - DeveloperProfile, + sqlx::query_as::<_, DeveloperProfile>( r#"INSERT INTO developer_profiles (user_id, display_name, bio, location, custom_data) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (user_id) DO UPDATE SET @@ -52,7 +52,13 @@ impl DeveloperRepository { RETURNING id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at"#, - user_id, p.display_name, p.bio, p.location, p.custom_data - ).fetch_one(pool).await + ) + .bind(user_id) + .bind(p.display_name) + .bind(p.bio) + .bind(p.location) + .bind(p.custom_data) + .fetch_one(pool) + .await } } diff --git a/crates/db/src/models/employee.rs b/crates/db/src/models/employee.rs index 232d4dd..1076b4e 100644 --- a/crates/db/src/models/employee.rs +++ b/crates/db/src/models/employee.rs @@ -104,7 +104,8 @@ impl EmployeeRepository { } pub async fn delete(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> { - sqlx::query!("DELETE FROM employees WHERE id = $1", id) + sqlx::query("DELETE FROM employees WHERE id = $1") + .bind(id) .execute(pool) .await?; Ok(()) diff --git a/crates/db/src/models/fitness_trainer.rs b/crates/db/src/models/fitness_trainer.rs index f57b99e..6100dfc 100644 --- a/crates/db/src/models/fitness_trainer.rs +++ b/crates/db/src/models/fitness_trainer.rs @@ -28,19 +28,19 @@ pub struct FitnessTrainerRepository; impl FitnessTrainerRepository { pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!( - FitnessTrainerProfile, + sqlx::query_as::<_, FitnessTrainerProfile>( r#"SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM fitness_trainer_profiles WHERE user_id = $1"#, - user_id - ).fetch_optional(pool).await + ) + .bind(user_id) + .fetch_optional(pool) + .await } pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertFitnessTrainerProfilePayload) -> Result { - sqlx::query_as!( - FitnessTrainerProfile, + sqlx::query_as::<_, FitnessTrainerProfile>( r#"INSERT INTO fitness_trainer_profiles (user_id, display_name, bio, location, custom_data) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (user_id) DO UPDATE SET @@ -52,7 +52,13 @@ impl FitnessTrainerRepository { RETURNING id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at"#, - user_id, p.display_name, p.bio, p.location, p.custom_data - ).fetch_one(pool).await + ) + .bind(user_id) + .bind(p.display_name) + .bind(p.bio) + .bind(p.location) + .bind(p.custom_data) + .fetch_one(pool) + .await } } diff --git a/crates/db/src/models/graphic_designer.rs b/crates/db/src/models/graphic_designer.rs index 0fb1712..1dc169b 100644 --- a/crates/db/src/models/graphic_designer.rs +++ b/crates/db/src/models/graphic_designer.rs @@ -28,19 +28,19 @@ pub struct GraphicDesignerRepository; impl GraphicDesignerRepository { pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!( - GraphicDesignerProfile, + sqlx::query_as::<_, GraphicDesignerProfile>( r#"SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM graphic_designer_profiles WHERE user_id = $1"#, - user_id - ).fetch_optional(pool).await + ) + .bind(user_id) + .fetch_optional(pool) + .await } pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertGraphicDesignerProfilePayload) -> Result { - sqlx::query_as!( - GraphicDesignerProfile, + sqlx::query_as::<_, GraphicDesignerProfile>( r#"INSERT INTO graphic_designer_profiles (user_id, display_name, bio, location, custom_data) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (user_id) DO UPDATE SET @@ -52,7 +52,13 @@ impl GraphicDesignerRepository { RETURNING id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at"#, - user_id, p.display_name, p.bio, p.location, p.custom_data - ).fetch_one(pool).await + ) + .bind(user_id) + .bind(p.display_name) + .bind(p.bio) + .bind(p.location) + .bind(p.custom_data) + .fetch_one(pool) + .await } } diff --git a/crates/db/src/models/job.rs b/crates/db/src/models/job.rs index 37ecad8..a6d6a2e 100644 --- a/crates/db/src/models/job.rs +++ b/crates/db/src/models/job.rs @@ -56,27 +56,26 @@ pub struct JobRepository; impl JobRepository { pub async fn create(pool: &PgPool, payload: CreateJobPayload) -> Result { - let job = sqlx::query_as!( - Job, + let job = sqlx::query_as::<_, Job>( r#" INSERT INTO jobs ( - company_id, title, category, description, location, + company_id, title, category, description, location, job_type, salary_min, salary_max, experience_years, skills ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING * "#, - payload.company_id, - payload.title, - payload.category, - payload.description, - payload.location, - payload.job_type.unwrap_or_else(|| "FULL_TIME".to_string()), - payload.salary_min, - payload.salary_max, - payload.experience_years, - &payload.skills.unwrap_or_default() ) + .bind(payload.company_id) + .bind(payload.title) + .bind(payload.category) + .bind(payload.description) + .bind(payload.location) + .bind(payload.job_type.unwrap_or_else(|| "FULL_TIME".to_string())) + .bind(payload.salary_min) + .bind(payload.salary_max) + .bind(payload.experience_years) + .bind(payload.skills.unwrap_or_default()) .fetch_one(pool) .await?; @@ -84,7 +83,8 @@ impl JobRepository { } pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!(Job, "SELECT * FROM jobs WHERE id = $1", id) + sqlx::query_as::<_, Job>("SELECT * FROM jobs WHERE id = $1") + .bind(id) .fetch_optional(pool) .await } @@ -97,19 +97,18 @@ impl JobRepository { limit: i64, ) -> Result, sqlx::Error> { let offset = (page - 1) * limit; - let jobs = sqlx::query_as!( - Job, + let jobs = sqlx::query_as::<_, Job>( r#" - SELECT * FROM jobs + SELECT * FROM jobs WHERE company_id = $1 AND ($2::VARCHAR IS NULL OR status = $2) ORDER BY created_at DESC LIMIT $3 OFFSET $4 "#, - company_id, - status, - limit, - offset ) + .bind(company_id) + .bind(status) + .bind(limit) + .bind(offset) .fetch_all(pool) .await?; @@ -121,8 +120,7 @@ impl JobRepository { id: Uuid, payload: UpdateJobPayload, ) -> Result { - let job = sqlx::query_as!( - Job, + let job = sqlx::query_as::<_, Job>( r#" UPDATE jobs SET title = COALESCE($1, title), @@ -138,17 +136,17 @@ impl JobRepository { WHERE id = $10 RETURNING * "#, - payload.title, - payload.category, - payload.description, - payload.location, - payload.job_type, - payload.salary_min, - payload.salary_max, - payload.experience_years, - payload.skills.as_deref(), - id ) + .bind(payload.title) + .bind(payload.category) + .bind(payload.description) + .bind(payload.location) + .bind(payload.job_type) + .bind(payload.salary_min) + .bind(payload.salary_max) + .bind(payload.experience_years) + .bind(payload.skills) + .bind(id) .fetch_one(pool) .await?; @@ -160,12 +158,11 @@ impl JobRepository { id: Uuid, status: &str, ) -> Result { - let job = sqlx::query_as!( - Job, + let job = sqlx::query_as::<_, Job>( "UPDATE jobs SET status = $1, updated_at = NOW() WHERE id = $2 RETURNING *", - status, - id ) + .bind(status) + .bind(id) .fetch_one(pool) .await?; Ok(job) @@ -176,17 +173,16 @@ impl JobRepository { id: Uuid, admin_user_id: Uuid, ) -> Result { - let job = sqlx::query_as!( - Job, + let job = sqlx::query_as::<_, Job>( r#" UPDATE jobs SET status = 'LIVE', approved_at = NOW(), approved_by = $1, rejection_reason = NULL, updated_at = NOW() WHERE id = $2 RETURNING * "#, - admin_user_id, - id ) + .bind(admin_user_id) + .bind(id) .fetch_one(pool) .await?; Ok(job) @@ -197,17 +193,16 @@ impl JobRepository { id: Uuid, reason: Option, ) -> Result { - let job = sqlx::query_as!( - Job, + let job = sqlx::query_as::<_, Job>( r#" UPDATE jobs SET status = 'REJECTED', rejection_reason = $1, approved_at = NULL, approved_by = NULL, updated_at = NOW() WHERE id = $2 RETURNING * "#, - reason, - id ) + .bind(reason) + .bind(id) .fetch_one(pool) .await?; Ok(job) @@ -217,19 +212,19 @@ impl JobRepository { pool: &PgPool, company_id: Uuid, ) -> Result { - let count = sqlx::query!( + let count = sqlx::query_scalar::<_, i64>( r#" - SELECT COUNT(*) as "count!" + SELECT COUNT(*) FROM jobs - WHERE company_id = $1 + WHERE company_id = $1 AND created_at >= date_trunc('month', now()) AND status != 'REJECTED' "#, - company_id ) + .bind(company_id) .fetch_one(pool) .await?; - Ok(count.count) + Ok(count) } } diff --git a/crates/db/src/models/job_seeker.rs b/crates/db/src/models/job_seeker.rs index 33b1050..90bc991 100644 --- a/crates/db/src/models/job_seeker.rs +++ b/crates/db/src/models/job_seeker.rs @@ -40,18 +40,17 @@ impl JobSeekerRepository { pool: &PgPool, user_id: Uuid, ) -> Result, sqlx::Error> { - let profile = sqlx::query_as!( - JobSeekerProfile, + let profile = sqlx::query_as::<_, JobSeekerProfile>( r#" - SELECT - id, user_id, full_name, location, summary, experience_years, - skills, resume_url, active_application_count, status, bio, custom_data, + SELECT + id, user_id, full_name, location, summary, experience_years, + skills, resume_url, active_application_count, status, bio, custom_data, created_at, updated_at FROM job_seeker_profiles WHERE user_id = $1 "#, - user_id ) + .bind(user_id) .fetch_optional(pool) .await?; @@ -63,11 +62,10 @@ impl JobSeekerRepository { user_id: Uuid, payload: UpsertJobSeekerProfilePayload, ) -> Result { - let profile = sqlx::query_as!( - JobSeekerProfile, + let profile = sqlx::query_as::<_, JobSeekerProfile>( r#" INSERT INTO job_seeker_profiles ( - user_id, full_name, location, summary, experience_years, + user_id, full_name, location, summary, experience_years, skills, resume_url, bio, custom_data ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) @@ -81,21 +79,21 @@ impl JobSeekerRepository { bio = EXCLUDED.bio, custom_data = EXCLUDED.custom_data, updated_at = NOW() - RETURNING - id, user_id, full_name, location, summary, experience_years, - skills, resume_url, active_application_count, status, bio, custom_data, + RETURNING + id, user_id, full_name, location, summary, experience_years, + skills, resume_url, active_application_count, status, bio, custom_data, created_at, updated_at "#, - user_id, - payload.full_name, - payload.location, - payload.summary, - payload.experience_years.unwrap_or(0), - &payload.skills.unwrap_or_default(), - payload.resume_url, - payload.bio, - payload.custom_data ) + .bind(user_id) + .bind(payload.full_name) + .bind(payload.location) + .bind(payload.summary) + .bind(payload.experience_years.unwrap_or(0)) + .bind(payload.skills.unwrap_or_default()) + .bind(payload.resume_url) + .bind(payload.bio) + .bind(payload.custom_data) .fetch_one(pool) .await?; @@ -107,11 +105,11 @@ impl JobSeekerRepository { id: Uuid, delta: i32, ) -> Result<(), sqlx::Error> { - sqlx::query!( + sqlx::query( "UPDATE job_seeker_profiles SET active_application_count = active_application_count + $1 WHERE id = $2", - delta, - id ) + .bind(delta) + .bind(id) .execute(pool) .await?; Ok(()) @@ -121,23 +119,21 @@ impl JobSeekerRepository { pool: &PgPool, user_id: Uuid, ) -> Result { - let profile = sqlx::query_as!( - JobSeekerProfile, + let profile = sqlx::query_as::<_, JobSeekerProfile>( r#" UPDATE job_seeker_profiles SET status = 'PENDING_REVIEW', updated_at = NOW() WHERE user_id = $1 - RETURNING - id, user_id, full_name, location, summary, experience_years, - skills, resume_url, active_application_count, status, bio, custom_data, + RETURNING + id, user_id, full_name, location, summary, experience_years, + skills, resume_url, active_application_count, status, bio, custom_data, created_at, updated_at "#, - user_id ) + .bind(user_id) .fetch_one(pool) .await?; Ok(profile) } } - diff --git a/crates/db/src/models/lead_request.rs b/crates/db/src/models/lead_request.rs index c033d7b..9de8a4a 100644 --- a/crates/db/src/models/lead_request.rs +++ b/crates/db/src/models/lead_request.rs @@ -31,17 +31,16 @@ impl LeadRequestRepository { pool: &PgPool, payload: CreateLeadRequestPayload, ) -> Result { - let req = sqlx::query_as!( - LeadRequest, + let req = sqlx::query_as::<_, LeadRequest>( r#" INSERT INTO lead_requests (requirement_id, professional_id, expires_at) VALUES ($1, $2, $3) RETURNING * "#, - payload.requirement_id, - payload.professional_id, - payload.expires_at ) + .bind(payload.requirement_id) + .bind(payload.professional_id) + .bind(payload.expires_at) .fetch_one(pool) .await?; @@ -49,7 +48,8 @@ impl LeadRequestRepository { } pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!(LeadRequest, "SELECT * FROM lead_requests WHERE id = $1", id) + sqlx::query_as::<_, LeadRequest>("SELECT * FROM lead_requests WHERE id = $1") + .bind(id) .fetch_optional(pool) .await } @@ -61,18 +61,17 @@ impl LeadRequestRepository { limit: i64, ) -> Result, sqlx::Error> { let offset = (page - 1) * limit; - let reqs = sqlx::query_as!( - LeadRequest, + let reqs = sqlx::query_as::<_, LeadRequest>( r#" - SELECT * FROM lead_requests + SELECT * FROM lead_requests WHERE requirement_id = $1 ORDER BY requested_at DESC LIMIT $2 OFFSET $3 "#, - requirement_id, - limit, - offset ) + .bind(requirement_id) + .bind(limit) + .bind(offset) .fetch_all(pool) .await?; @@ -84,17 +83,16 @@ impl LeadRequestRepository { id: Uuid, status: &str, ) -> Result { - let req = sqlx::query_as!( - LeadRequest, + let req = sqlx::query_as::<_, LeadRequest>( r#" - UPDATE lead_requests - SET status = $1, resolved_at = NOW(), updated_at = NOW() - WHERE id = $2 + UPDATE lead_requests + SET status = $1, resolved_at = NOW(), updated_at = NOW() + WHERE id = $2 RETURNING * "#, - status, - id ) + .bind(status) + .bind(id) .fetch_one(pool) .await?; Ok(req) diff --git a/crates/db/src/models/makeup_artist.rs b/crates/db/src/models/makeup_artist.rs index 10724cc..dbcca26 100644 --- a/crates/db/src/models/makeup_artist.rs +++ b/crates/db/src/models/makeup_artist.rs @@ -28,19 +28,19 @@ pub struct MakeupArtistRepository; impl MakeupArtistRepository { pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!( - MakeupArtistProfile, + sqlx::query_as::<_, MakeupArtistProfile>( r#"SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM makeup_artist_profiles WHERE user_id = $1"#, - user_id - ).fetch_optional(pool).await + ) + .bind(user_id) + .fetch_optional(pool) + .await } pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertMakeupArtistProfilePayload) -> Result { - sqlx::query_as!( - MakeupArtistProfile, + sqlx::query_as::<_, MakeupArtistProfile>( r#"INSERT INTO makeup_artist_profiles (user_id, display_name, bio, location, custom_data) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (user_id) DO UPDATE SET @@ -52,7 +52,13 @@ impl MakeupArtistRepository { RETURNING id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at"#, - user_id, p.display_name, p.bio, p.location, p.custom_data - ).fetch_one(pool).await + ) + .bind(user_id) + .bind(p.display_name) + .bind(p.bio) + .bind(p.location) + .bind(p.custom_data) + .fetch_one(pool) + .await } } diff --git a/crates/db/src/models/onboarding_state.rs b/crates/db/src/models/onboarding_state.rs index 5b5cbb3..fea4e0a 100644 --- a/crates/db/src/models/onboarding_state.rs +++ b/crates/db/src/models/onboarding_state.rs @@ -41,17 +41,16 @@ impl OnboardingStateRepository { user_id: Uuid, role_id: Uuid, ) -> Result, sqlx::Error> { - sqlx::query_as!( - OnboardingState, + sqlx::query_as::<_, OnboardingState>( r#" SELECT id, user_id, role_id, status, progress_json, completed_at, created_at, updated_at FROM onboarding_states WHERE user_id = $1 AND role_id = $2 "#, - user_id, - role_id, ) + .bind(user_id) + .bind(role_id) .fetch_optional(pool) .await } @@ -63,8 +62,7 @@ impl OnboardingStateRepository { role_id: Uuid, progress: &Value, ) -> Result { - sqlx::query_as!( - OnboardingState, + sqlx::query_as::<_, OnboardingState>( r#" INSERT INTO onboarding_states (user_id, role_id, status, progress_json) VALUES ($1, $2, 'IN_PROGRESS', $3) @@ -78,10 +76,10 @@ impl OnboardingStateRepository { RETURNING id, user_id, role_id, status, progress_json, completed_at, created_at, updated_at "#, - user_id, - role_id, - progress, ) + .bind(user_id) + .bind(role_id) + .bind(progress) .fetch_one(pool) .await } @@ -93,8 +91,7 @@ impl OnboardingStateRepository { role_id: Uuid, final_answers: &Value, ) -> Result { - sqlx::query_as!( - OnboardingState, + sqlx::query_as::<_, OnboardingState>( r#" INSERT INTO onboarding_states (user_id, role_id, status, progress_json, completed_at) VALUES ($1, $2, 'COMPLETED', $3, NOW()) @@ -106,10 +103,10 @@ impl OnboardingStateRepository { RETURNING id, user_id, role_id, status, progress_json, completed_at, created_at, updated_at "#, - user_id, - role_id, - final_answers, ) + .bind(user_id) + .bind(role_id) + .bind(final_answers) .fetch_one(pool) .await } @@ -120,14 +117,14 @@ impl OnboardingStateRepository { user_id: Uuid, role_id: Uuid, ) -> Result { - let status = sqlx::query_scalar!( + let status = sqlx::query_scalar::<_, String>( r#" SELECT status FROM onboarding_states WHERE user_id = $1 AND role_id = $2 "#, - user_id, - role_id, ) + .bind(user_id) + .bind(role_id) .fetch_optional(pool) .await?; Ok(status.map(|s| s == "COMPLETED").unwrap_or(false)) diff --git a/crates/db/src/models/photographer.rs b/crates/db/src/models/photographer.rs index c5caee0..7a25bcb 100644 --- a/crates/db/src/models/photographer.rs +++ b/crates/db/src/models/photographer.rs @@ -28,19 +28,19 @@ pub struct PhotographerRepository; impl PhotographerRepository { pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!( - PhotographerProfile, + sqlx::query_as::<_, PhotographerProfile>( r#"SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM photographer_profiles WHERE user_id = $1"#, - user_id - ).fetch_optional(pool).await + ) + .bind(user_id) + .fetch_optional(pool) + .await } pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertPhotographerProfilePayload) -> Result { - sqlx::query_as!( - PhotographerProfile, + sqlx::query_as::<_, PhotographerProfile>( r#"INSERT INTO photographer_profiles (user_id, display_name, bio, location, custom_data) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (user_id) DO UPDATE SET @@ -52,7 +52,13 @@ impl PhotographerRepository { RETURNING id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at"#, - user_id, p.display_name, p.bio, p.location, p.custom_data - ).fetch_one(pool).await + ) + .bind(user_id) + .bind(p.display_name) + .bind(p.bio) + .bind(p.location) + .bind(p.custom_data) + .fetch_one(pool) + .await } } diff --git a/crates/db/src/models/professional.rs b/crates/db/src/models/professional.rs index 51baf49..9cd8d31 100644 --- a/crates/db/src/models/professional.rs +++ b/crates/db/src/models/professional.rs @@ -116,11 +116,10 @@ pub struct ProfessionalRepository; impl ProfessionalRepository { pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result { - sqlx::query_as!( - Professional, + sqlx::query_as::<_, Professional>( "SELECT * FROM professionals WHERE user_id = $1", - user_id ) + .bind(user_id) .fetch_one(pool) .await } @@ -132,48 +131,44 @@ impl ProfessionalRepository { limit: i64, ) -> Result, sqlx::Error> { let offset = (page - 1) * limit; - sqlx::query_as!( - Requirement, + sqlx::query_as::<_, Requirement>( r#" - SELECT * FROM requirements + SELECT * FROM requirements WHERE profession_key = $1 AND status = 'OPEN' AND (expires_at IS NULL OR expires_at > NOW()) ORDER BY created_at DESC LIMIT $2 OFFSET $3 "#, - profession_key, - limit, - offset ) + .bind(profession_key) + .bind(limit) + .bind(offset) .fetch_all(pool) .await } pub async fn get_portfolio(pool: &PgPool, professional_id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!( - PortfolioItem, + sqlx::query_as::<_, PortfolioItem>( "SELECT * FROM portfolio_items WHERE professional_id = $1 ORDER BY created_at DESC", - professional_id ) + .bind(professional_id) .fetch_all(pool) .await } pub async fn get_services(pool: &PgPool, professional_id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!( - Service, + sqlx::query_as::<_, Service>( "SELECT * FROM services WHERE professional_id = $1 AND is_active = true ORDER BY name ASC", - professional_id ) + .bind(professional_id) .fetch_all(pool) .await } pub async fn get_wallet(pool: &PgPool, user_id: Uuid) -> Result { - sqlx::query_as!( - Wallet, + sqlx::query_as::<_, Wallet>( "SELECT * FROM tracecoin_wallets WHERE user_id = $1", - user_id ) + .bind(user_id) .fetch_one(pool) .await } @@ -566,11 +561,10 @@ impl ProfessionalRepository { pool: &PgPool, user_id: Uuid, ) -> Result { - let prof = sqlx::query_as!( - Professional, + let prof = sqlx::query_as::<_, Professional>( "SELECT * FROM professionals WHERE user_id = $1", - user_id ) + .bind(user_id) .fetch_one(pool) .await?; @@ -578,16 +572,15 @@ impl ProfessionalRepository { return Err(sqlx::Error::Protocol(format!("Professional profile is already {}", prof.status).into())); } - let prof = sqlx::query_as!( - Professional, + let prof = sqlx::query_as::<_, Professional>( r#" UPDATE professionals SET status = 'PENDING_REVIEW', updated_at = NOW() WHERE user_id = $1 RETURNING * "#, - user_id ) + .bind(user_id) .fetch_one(pool) .await?; diff --git a/crates/db/src/models/requirement.rs b/crates/db/src/models/requirement.rs index 22c6467..9898161 100644 --- a/crates/db/src/models/requirement.rs +++ b/crates/db/src/models/requirement.rs @@ -54,25 +54,24 @@ impl RequirementRepository { pool: &PgPool, payload: CreateRequirementPayload, ) -> Result { - let req = sqlx::query_as!( - Requirement, + let req = sqlx::query_as::<_, Requirement>( r#" INSERT INTO requirements ( - customer_id, profession_key, title, description, location, + customer_id, profession_key, title, description, location, budget, preferred_date, extra_data_json ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING * "#, - payload.customer_id, - payload.profession_key, - payload.title, - payload.description, - payload.location, - payload.budget, - payload.preferred_date, - payload.extra_data_json ) + .bind(payload.customer_id) + .bind(payload.profession_key) + .bind(payload.title) + .bind(payload.description) + .bind(payload.location) + .bind(payload.budget) + .bind(payload.preferred_date) + .bind(payload.extra_data_json) .fetch_one(pool) .await?; @@ -80,7 +79,8 @@ impl RequirementRepository { } pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!(Requirement, "SELECT * FROM requirements WHERE id = $1", id) + sqlx::query_as::<_, Requirement>("SELECT * FROM requirements WHERE id = $1") + .bind(id) .fetch_optional(pool) .await } @@ -92,18 +92,17 @@ impl RequirementRepository { limit: i64, ) -> Result, sqlx::Error> { let offset = (page - 1) * limit; - let reqs = sqlx::query_as!( - Requirement, + let reqs = sqlx::query_as::<_, Requirement>( r#" - SELECT * FROM requirements + SELECT * FROM requirements WHERE customer_id = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3 "#, - customer_id, - limit, - offset ) + .bind(customer_id) + .bind(limit) + .bind(offset) .fetch_all(pool) .await?; @@ -115,8 +114,7 @@ impl RequirementRepository { id: Uuid, payload: UpdateRequirementPayload, ) -> Result { - let req = sqlx::query_as!( - Requirement, + let req = sqlx::query_as::<_, Requirement>( r#" UPDATE requirements SET title = COALESCE($1, title), @@ -129,14 +127,14 @@ impl RequirementRepository { WHERE id = $7 RETURNING * "#, - payload.title, - payload.description, - payload.location, - payload.budget, - payload.preferred_date, - payload.extra_data_json, - id ) + .bind(payload.title) + .bind(payload.description) + .bind(payload.location) + .bind(payload.budget) + .bind(payload.preferred_date) + .bind(payload.extra_data_json) + .bind(id) .fetch_one(pool) .await?; @@ -148,29 +146,29 @@ impl RequirementRepository { id: Uuid, status: &str, ) -> Result { - let req = sqlx::query_as!( - Requirement, + let req = sqlx::query_as::<_, Requirement>( "UPDATE requirements SET status = $1, updated_at = NOW() WHERE id = $2 RETURNING *", - status, - id ) + .bind(status) + .bind(id) .fetch_one(pool) .await?; Ok(req) } pub async fn increment_request_count(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> { - sqlx::query!("UPDATE requirements SET request_count = request_count + 1 WHERE id = $1", id) + sqlx::query("UPDATE requirements SET request_count = request_count + 1 WHERE id = $1") + .bind(id) .execute(pool) .await?; Ok(()) } pub async fn increment_accepted_count(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> { - sqlx::query!( + sqlx::query( "UPDATE requirements SET accepted_count = accepted_count + 1 WHERE id = $1", - id ) + .bind(id) .execute(pool) .await?; Ok(()) @@ -180,16 +178,15 @@ impl RequirementRepository { pool: &PgPool, id: Uuid, ) -> Result { - sqlx::query_as!( - Requirement, + sqlx::query_as::<_, Requirement>( r#" UPDATE requirements SET accepted_count = accepted_count + 1, updated_at = NOW() WHERE id = $1 RETURNING * "#, - id ) + .bind(id) .fetch_one(pool) .await } @@ -199,17 +196,16 @@ impl RequirementRepository { id: Uuid, admin_user_id: Uuid, ) -> Result { - sqlx::query_as!( - Requirement, + sqlx::query_as::<_, Requirement>( r#" UPDATE requirements SET status = 'OPEN', approved_at = NOW(), approved_by = $1, rejection_reason = NULL, updated_at = NOW() WHERE id = $2 RETURNING * "#, - admin_user_id, - id ) + .bind(admin_user_id) + .bind(id) .fetch_one(pool) .await } @@ -219,17 +215,16 @@ impl RequirementRepository { id: Uuid, reason: Option, ) -> Result { - sqlx::query_as!( - Requirement, + sqlx::query_as::<_, Requirement>( r#" UPDATE requirements SET status = 'REJECTED', rejection_reason = $1, approved_at = NULL, approved_by = NULL, updated_at = NOW() WHERE id = $2 RETURNING * "#, - reason, - id ) + .bind(reason) + .bind(id) .fetch_one(pool) .await } diff --git a/crates/db/src/models/role.rs b/crates/db/src/models/role.rs index 50157e4..2bae0ba 100644 --- a/crates/db/src/models/role.rs +++ b/crates/db/src/models/role.rs @@ -27,17 +27,16 @@ impl RoleRepository { pool: &sqlx::PgPool, payload: CreateRolePayload, ) -> Result { - let role = sqlx::query_as!( - Role, + let role = sqlx::query_as::<_, Role>( r#" INSERT INTO roles (key, name, audience) VALUES ($1, $2, $3) RETURNING id, key, name, audience, is_active, created_at "#, - payload.key, - payload.name, - payload.audience ) + .bind(payload.key) + .bind(payload.name) + .bind(payload.audience) .fetch_one(pool) .await?; @@ -45,13 +44,12 @@ impl RoleRepository { } pub async fn get_all(pool: &sqlx::PgPool) -> Result, sqlx::Error> { - let roles = sqlx::query_as!( - Role, + let roles = sqlx::query_as::<_, Role>( r#" SELECT id, key, name, audience, is_active, created_at FROM roles ORDER BY created_at DESC - "# + "#, ) .fetch_all(pool) .await?; @@ -60,15 +58,14 @@ impl RoleRepository { } pub async fn get_by_key(pool: &sqlx::PgPool, key: &str) -> Result { - let role = sqlx::query_as!( - Role, + let role = sqlx::query_as::<_, Role>( r#" SELECT id, key, name, audience, is_active, created_at FROM roles WHERE key = $1 "#, - key ) + .bind(key) .fetch_one(pool) .await?; diff --git a/crates/db/src/models/social_media_manager.rs b/crates/db/src/models/social_media_manager.rs index b5e2f9d..c5093e2 100644 --- a/crates/db/src/models/social_media_manager.rs +++ b/crates/db/src/models/social_media_manager.rs @@ -28,19 +28,19 @@ pub struct SocialMediaManagerRepository; impl SocialMediaManagerRepository { pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!( - SocialMediaManagerProfile, + sqlx::query_as::<_, SocialMediaManagerProfile>( r#"SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM social_media_manager_profiles WHERE user_id = $1"#, - user_id - ).fetch_optional(pool).await + ) + .bind(user_id) + .fetch_optional(pool) + .await } pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertSocialMediaManagerProfilePayload) -> Result { - sqlx::query_as!( - SocialMediaManagerProfile, + sqlx::query_as::<_, SocialMediaManagerProfile>( r#"INSERT INTO social_media_manager_profiles (user_id, display_name, bio, location, custom_data) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (user_id) DO UPDATE SET @@ -52,7 +52,13 @@ impl SocialMediaManagerRepository { RETURNING id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at"#, - user_id, p.display_name, p.bio, p.location, p.custom_data - ).fetch_one(pool).await + ) + .bind(user_id) + .bind(p.display_name) + .bind(p.bio) + .bind(p.location) + .bind(p.custom_data) + .fetch_one(pool) + .await } } diff --git a/crates/db/src/models/tutor.rs b/crates/db/src/models/tutor.rs index 95ca445..f4d0e25 100644 --- a/crates/db/src/models/tutor.rs +++ b/crates/db/src/models/tutor.rs @@ -28,19 +28,19 @@ pub struct TutorRepository; impl TutorRepository { pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!( - TutorProfile, + sqlx::query_as::<_, TutorProfile>( r#"SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM tutor_profiles WHERE user_id = $1"#, - user_id - ).fetch_optional(pool).await + ) + .bind(user_id) + .fetch_optional(pool) + .await } pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertTutorProfilePayload) -> Result { - sqlx::query_as!( - TutorProfile, + sqlx::query_as::<_, TutorProfile>( r#"INSERT INTO tutor_profiles (user_id, display_name, bio, location, custom_data) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (user_id) DO UPDATE SET @@ -52,7 +52,13 @@ impl TutorRepository { RETURNING id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at"#, - user_id, p.display_name, p.bio, p.location, p.custom_data - ).fetch_one(pool).await + ) + .bind(user_id) + .bind(p.display_name) + .bind(p.bio) + .bind(p.location) + .bind(p.custom_data) + .fetch_one(pool) + .await } } diff --git a/crates/db/src/models/ugc_content_creator.rs b/crates/db/src/models/ugc_content_creator.rs index 4e12a5e..a1ecebd 100644 --- a/crates/db/src/models/ugc_content_creator.rs +++ b/crates/db/src/models/ugc_content_creator.rs @@ -28,19 +28,19 @@ pub struct UgcContentCreatorRepository; impl UgcContentCreatorRepository { pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!( - UgcContentCreatorProfile, + sqlx::query_as::<_, UgcContentCreatorProfile>( r#"SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM ugc_content_creator_profiles WHERE user_id = $1"#, - user_id - ).fetch_optional(pool).await + ) + .bind(user_id) + .fetch_optional(pool) + .await } pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertUgcContentCreatorProfilePayload) -> Result { - sqlx::query_as!( - UgcContentCreatorProfile, + sqlx::query_as::<_, UgcContentCreatorProfile>( r#"INSERT INTO ugc_content_creator_profiles (user_id, display_name, bio, location, custom_data) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (user_id) DO UPDATE SET @@ -52,7 +52,13 @@ impl UgcContentCreatorRepository { RETURNING id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at"#, - user_id, p.display_name, p.bio, p.location, p.custom_data - ).fetch_one(pool).await + ) + .bind(user_id) + .bind(p.display_name) + .bind(p.bio) + .bind(p.location) + .bind(p.custom_data) + .fetch_one(pool) + .await } } diff --git a/crates/db/src/models/user.rs b/crates/db/src/models/user.rs index 1ac3c07..ce4edad 100644 --- a/crates/db/src/models/user.rs +++ b/crates/db/src/models/user.rs @@ -49,8 +49,7 @@ pub struct UserRepository; impl UserRepository { pub async fn create(pool: &PgPool, payload: CreateUserPayload) -> Result { - let user = sqlx::query_as!( - User, + let user = sqlx::query_as::<_, User>( r#" INSERT INTO users (full_name, email, phone, password_hash, email_verified, phone_verified) VALUES ($1, $2, $3, $4, false, false) @@ -61,11 +60,11 @@ impl UserRepository { reset_password_token, reset_password_expires_at, created_at, updated_at, deleted_at "#, - payload.full_name, - payload.email.to_lowercase(), - payload.phone as Option, - payload.password_hash, ) + .bind(payload.full_name) + .bind(payload.email.to_lowercase()) + .bind(payload.phone) + .bind(payload.password_hash) .fetch_one(pool) .await?; @@ -73,8 +72,7 @@ impl UserRepository { } pub async fn get_by_email(pool: &PgPool, email: &str) -> Result { - sqlx::query_as!( - User, + sqlx::query_as::<_, User>( r#" SELECT id, email, password_hash, full_name, phone, email_verified, phone_verified, status, @@ -84,15 +82,14 @@ impl UserRepository { FROM users WHERE email = $1 AND deleted_at IS NULL "#, - email.to_lowercase() ) + .bind(email.to_lowercase()) .fetch_one(pool) .await } pub async fn get_by_id(pool: &PgPool, id: Uuid) -> Result { - sqlx::query_as!( - User, + sqlx::query_as::<_, User>( r#" SELECT id, email, password_hash, full_name, phone, email_verified, phone_verified, status, @@ -102,15 +99,15 @@ impl UserRepository { FROM users WHERE id = $1 AND deleted_at IS NULL "#, - id ) + .bind(id) .fetch_one(pool) .await } /// Returns all approved role keys for a user (e.g. ["COMPANY", "JOB_SEEKER"]) pub async fn get_user_role_keys(pool: &PgPool, user_id: Uuid) -> Result, sqlx::Error> { - let rows = sqlx::query_scalar!( + let rows = sqlx::query_scalar::<_, String>( r#" SELECT r.key FROM user_roles ur @@ -118,8 +115,8 @@ impl UserRepository { WHERE ur.user_id = $1 AND ur.status = 'APPROVED' ORDER BY ur.approved_at ASC "#, - user_id ) + .bind(user_id) .fetch_all(pool) .await?; @@ -133,24 +130,23 @@ impl UserRepository { token: &str, expires_at: DateTime, ) -> Result<(), sqlx::Error> { - sqlx::query!( + sqlx::query( r#" UPDATE users SET email_verification_token = $1, email_verification_expires_at = $2, updated_at = NOW() WHERE id = $3 "#, - token, - expires_at, - user_id ) + .bind(token) + .bind(expires_at) + .bind(user_id) .execute(pool) .await?; Ok(()) } pub async fn get_by_verification_token(pool: &PgPool, token: &str) -> Result { - sqlx::query_as!( - User, + sqlx::query_as::<_, User>( r#" SELECT id, email, password_hash, full_name, phone, email_verified, phone_verified, status, @@ -160,17 +156,17 @@ impl UserRepository { FROM users WHERE email_verification_token = $1 AND deleted_at IS NULL "#, - token ) + .bind(token) .fetch_one(pool) .await } pub async fn set_email_verified(pool: &PgPool, user_id: Uuid) -> Result<(), sqlx::Error> { - sqlx::query!( + sqlx::query( "UPDATE users SET email_verified = true, email_verification_token = NULL, email_verification_expires_at = NULL, updated_at = NOW() WHERE id = $1", - user_id ) + .bind(user_id) .execute(pool) .await?; Ok(()) @@ -182,24 +178,23 @@ impl UserRepository { token: &str, expires_at: DateTime, ) -> Result<(), sqlx::Error> { - sqlx::query!( + sqlx::query( r#" UPDATE users SET reset_password_token = $1, reset_password_expires_at = $2, updated_at = NOW() WHERE id = $3 "#, - token, - expires_at, - user_id ) + .bind(token) + .bind(expires_at) + .bind(user_id) .execute(pool) .await?; Ok(()) } pub async fn get_by_reset_token(pool: &PgPool, token: &str) -> Result { - sqlx::query_as!( - User, + sqlx::query_as::<_, User>( r#" SELECT id, email, password_hash, full_name, phone, email_verified, phone_verified, status, @@ -209,39 +204,39 @@ impl UserRepository { FROM users WHERE reset_password_token = $1 AND deleted_at IS NULL "#, - token ) + .bind(token) .fetch_one(pool) .await } pub async fn clear_reset_token(pool: &PgPool, user_id: Uuid) -> Result<(), sqlx::Error> { - sqlx::query!( + sqlx::query( "UPDATE users SET reset_password_token = NULL, reset_password_expires_at = NULL, updated_at = NOW() WHERE id = $1", - user_id ) + .bind(user_id) .execute(pool) .await?; Ok(()) } pub async fn update_password(pool: &PgPool, user_id: Uuid, password_hash: &str) -> Result<(), sqlx::Error> { - sqlx::query!( + sqlx::query( "UPDATE users SET password_hash = $1, updated_at = NOW() WHERE id = $2", - password_hash, - user_id ) + .bind(password_hash) + .bind(user_id) .execute(pool) .await?; Ok(()) } pub async fn update_status(pool: &PgPool, user_id: Uuid, status: &str) -> Result<(), sqlx::Error> { - sqlx::query!( + sqlx::query( "UPDATE users SET status = $1, updated_at = NOW() WHERE id = $2", - status, - user_id ) + .bind(status) + .bind(user_id) .execute(pool) .await?; Ok(()) @@ -253,17 +248,16 @@ impl UserRepository { token_hash: &str, expires_at: DateTime, ) -> Result { - sqlx::query_as!( - RefreshToken, + sqlx::query_as::<_, RefreshToken>( r#" INSERT INTO refresh_tokens (user_id, token_hash, expires_at) VALUES ($1, $2, $3) RETURNING id, user_id, token_hash, expires_at, revoked, created_at "#, - user_id, - token_hash, - expires_at ) + .bind(user_id) + .bind(token_hash) + .bind(expires_at) .fetch_one(pool) .await } @@ -272,8 +266,7 @@ impl UserRepository { pool: &PgPool, token_hash: &str, ) -> Result { - sqlx::query_as!( - RefreshToken, + sqlx::query_as::<_, RefreshToken>( r#" SELECT id, user_id, token_hash, expires_at, revoked, created_at FROM refresh_tokens @@ -281,27 +274,27 @@ impl UserRepository { AND revoked = false AND expires_at > NOW() "#, - token_hash ) + .bind(token_hash) .fetch_one(pool) .await } pub async fn revoke_refresh_token(pool: &PgPool, token_hash: &str) -> Result<(), sqlx::Error> { - sqlx::query!( + sqlx::query( "UPDATE refresh_tokens SET revoked = true WHERE token_hash = $1", - token_hash ) + .bind(token_hash) .execute(pool) .await?; Ok(()) } pub async fn revoke_all_for_user(pool: &PgPool, user_id: Uuid) -> Result<(), sqlx::Error> { - sqlx::query!( + sqlx::query( "UPDATE refresh_tokens SET revoked = true WHERE user_id = $1", - user_id ) + .bind(user_id) .execute(pool) .await?; Ok(()) diff --git a/crates/db/src/models/video_editor.rs b/crates/db/src/models/video_editor.rs index aa73d5a..285b4fc 100644 --- a/crates/db/src/models/video_editor.rs +++ b/crates/db/src/models/video_editor.rs @@ -28,19 +28,19 @@ pub struct VideoEditorRepository; impl VideoEditorRepository { pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result, sqlx::Error> { - sqlx::query_as!( - VideoEditorProfile, + sqlx::query_as::<_, VideoEditorProfile>( r#"SELECT id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at FROM video_editor_profiles WHERE user_id = $1"#, - user_id - ).fetch_optional(pool).await + ) + .bind(user_id) + .fetch_optional(pool) + .await } pub async fn upsert(pool: &PgPool, user_id: Uuid, p: UpsertVideoEditorProfilePayload) -> Result { - sqlx::query_as!( - VideoEditorProfile, + sqlx::query_as::<_, VideoEditorProfile>( r#"INSERT INTO video_editor_profiles (user_id, display_name, bio, location, custom_data) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (user_id) DO UPDATE SET @@ -52,7 +52,13 @@ impl VideoEditorRepository { RETURNING id, user_id, display_name, bio, location, custom_data, status, created_at, updated_at"#, - user_id, p.display_name, p.bio, p.location, p.custom_data - ).fetch_one(pool).await + ) + .bind(user_id) + .bind(p.display_name) + .bind(p.bio) + .bind(p.location) + .bind(p.custom_data) + .fetch_one(pool) + .await } }