fix: convert all SQLx macros to runtime API, remove SQLX_OFFLINE requirement

This commit is contained in:
Ashwin Kumar 2026-04-09 07:40:15 +02:00
parent 58eff5ce63
commit 83c62a1c5e
52 changed files with 553 additions and 572 deletions

View file

@ -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

View file

@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
async fn list_catering_services(
State(state): State<ProfessionState>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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<ProfessionState>,
Path(id): Path<Uuid>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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}")))?;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -40,8 +40,7 @@ pub fn router() -> Router<AppState> {
async fn list_leads(
State(state): State<AppState>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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

View file

@ -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

View file

@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
async fn list_developers(
State(state): State<ProfessionState>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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<ProfessionState>,
Path(id): Path<Uuid>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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}")))?;

View file

@ -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

View file

@ -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

View file

@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
async fn list_fitness_trainers(
State(state): State<ProfessionState>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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<ProfessionState>,
Path(id): Path<Uuid>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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}")))?;

View file

@ -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

View file

@ -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

View file

@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
async fn list_graphic_designers(
State(state): State<ProfessionState>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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<ProfessionState>,
Path(id): Path<Uuid>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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}")))?;

View file

@ -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

View file

@ -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

View file

@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
async fn list_makeup_artists(
State(state): State<ProfessionState>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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<ProfessionState>,
Path(id): Path<Uuid>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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}")))?;

View file

@ -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

View file

@ -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<AppState>,
@ -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();

View file

@ -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

View file

@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
async fn list_photographers(
State(state): State<ProfessionState>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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<ProfessionState>,
Path(id): Path<Uuid>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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}")))?;

View file

@ -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

View file

@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
async fn list_social_media_managers(
State(state): State<ProfessionState>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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<ProfessionState>,
Path(id): Path<Uuid>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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}")))?;

View file

@ -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

View file

@ -43,14 +43,13 @@ pub fn router() -> Router<ProfessionState> {
async fn list_tutors(
State(state): State<ProfessionState>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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<ProfessionState>,
Path(id): Path<Uuid>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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}")))?;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -40,14 +40,13 @@ pub fn router() -> Router<ProfessionState> {
async fn list_video_editors(
State(state): State<ProfessionState>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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<ProfessionState>,
Path(id): Path<Uuid>,
) -> Result<impl IntoResponse, (StatusCode, String)> {
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}")))?;

View file

@ -31,18 +31,17 @@ impl ApplicationRepository {
pool: &PgPool,
payload: CreateApplicationPayload,
) -> Result<Application, sqlx::Error> {
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<Option<Application>, 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<Vec<Application>, 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<Vec<Application>, 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<Application, sqlx::Error> {
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(())

View file

@ -30,19 +30,19 @@ pub struct CateringServiceRepository;
impl CateringServiceRepository {
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<CateringServiceProfile>, 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<CateringServiceProfile, sqlx::Error> {
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
}
}

View file

@ -56,11 +56,10 @@ impl CompanyRepository {
pool: &PgPool,
user_id: Uuid,
) -> Result<Option<CompanyProfile>, 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<CompanyProfile, sqlx::Error> {
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<CompanyProfile, sqlx::Error> {
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?;

View file

@ -82,33 +82,32 @@ impl ConfigRepository {
payload: CreateOnboardingConfigPayload,
) -> Result<OnboardingConfig, sqlx::Error> {
// 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<OnboardingConfig, sqlx::Error> {
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<Vec<OnboardingConfigListItem>, 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<OnboardingConfig, sqlx::Error> {
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<DashboardConfig, sqlx::Error> {
// 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<DashboardConfig, sqlx::Error> {
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<Vec<DashboardConfigListItem>, 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<DashboardConfig, sqlx::Error> {
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<RuntimeConfig, sqlx::Error> {
// 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<RuntimeConfig, sqlx::Error> {
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<RuntimeConfig, sqlx::Error> {
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?;

View file

@ -39,18 +39,17 @@ impl CustomerRepository {
pool: &PgPool,
user_id: Uuid,
) -> Result<Option<CustomerProfile>, 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<CustomerProfile, sqlx::Error> {
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<CustomerProfile, sqlx::Error> {
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?;

View file

@ -28,19 +28,19 @@ pub struct DeveloperRepository;
impl DeveloperRepository {
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<DeveloperProfile>, 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<DeveloperProfile, sqlx::Error> {
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
}
}

View file

@ -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(())

View file

@ -28,19 +28,19 @@ pub struct FitnessTrainerRepository;
impl FitnessTrainerRepository {
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<FitnessTrainerProfile>, 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<FitnessTrainerProfile, sqlx::Error> {
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
}
}

View file

@ -28,19 +28,19 @@ pub struct GraphicDesignerRepository;
impl GraphicDesignerRepository {
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<GraphicDesignerProfile>, 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<GraphicDesignerProfile, sqlx::Error> {
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
}
}

View file

@ -56,27 +56,26 @@ pub struct JobRepository;
impl JobRepository {
pub async fn create(pool: &PgPool, payload: CreateJobPayload) -> Result<Job, sqlx::Error> {
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<Option<Job>, 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<Vec<Job>, 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<Job, sqlx::Error> {
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<Job, sqlx::Error> {
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<Job, sqlx::Error> {
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<String>,
) -> Result<Job, sqlx::Error> {
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<i64, sqlx::Error> {
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)
}
}

View file

@ -40,18 +40,17 @@ impl JobSeekerRepository {
pool: &PgPool,
user_id: Uuid,
) -> Result<Option<JobSeekerProfile>, 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<JobSeekerProfile, sqlx::Error> {
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<JobSeekerProfile, sqlx::Error> {
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)
}
}

View file

@ -31,17 +31,16 @@ impl LeadRequestRepository {
pool: &PgPool,
payload: CreateLeadRequestPayload,
) -> Result<LeadRequest, sqlx::Error> {
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<Option<LeadRequest>, 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<Vec<LeadRequest>, 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<LeadRequest, sqlx::Error> {
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)

View file

@ -28,19 +28,19 @@ pub struct MakeupArtistRepository;
impl MakeupArtistRepository {
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<MakeupArtistProfile>, 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<MakeupArtistProfile, sqlx::Error> {
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
}
}

View file

@ -41,17 +41,16 @@ impl OnboardingStateRepository {
user_id: Uuid,
role_id: Uuid,
) -> Result<Option<OnboardingState>, 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<OnboardingState, sqlx::Error> {
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<OnboardingState, sqlx::Error> {
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<bool, sqlx::Error> {
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))

View file

@ -28,19 +28,19 @@ pub struct PhotographerRepository;
impl PhotographerRepository {
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<PhotographerProfile>, 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<PhotographerProfile, sqlx::Error> {
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
}
}

View file

@ -116,11 +116,10 @@ pub struct ProfessionalRepository;
impl ProfessionalRepository {
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Professional, sqlx::Error> {
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<Vec<Requirement>, 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<Vec<PortfolioItem>, 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<Vec<Service>, 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<Wallet, sqlx::Error> {
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<Professional, sqlx::Error> {
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?;

View file

@ -54,25 +54,24 @@ impl RequirementRepository {
pool: &PgPool,
payload: CreateRequirementPayload,
) -> Result<Requirement, sqlx::Error> {
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<Option<Requirement>, 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<Vec<Requirement>, 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<Requirement, sqlx::Error> {
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<Requirement, sqlx::Error> {
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<Requirement, sqlx::Error> {
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<Requirement, sqlx::Error> {
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<String>,
) -> Result<Requirement, sqlx::Error> {
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
}

View file

@ -27,17 +27,16 @@ impl RoleRepository {
pool: &sqlx::PgPool,
payload: CreateRolePayload,
) -> Result<Role, sqlx::Error> {
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<Vec<Role>, 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<Role, sqlx::Error> {
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?;

View file

@ -28,19 +28,19 @@ pub struct SocialMediaManagerRepository;
impl SocialMediaManagerRepository {
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<SocialMediaManagerProfile>, 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<SocialMediaManagerProfile, sqlx::Error> {
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
}
}

View file

@ -28,19 +28,19 @@ pub struct TutorRepository;
impl TutorRepository {
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<TutorProfile>, 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<TutorProfile, sqlx::Error> {
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
}
}

View file

@ -28,19 +28,19 @@ pub struct UgcContentCreatorRepository;
impl UgcContentCreatorRepository {
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<UgcContentCreatorProfile>, 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<UgcContentCreatorProfile, sqlx::Error> {
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
}
}

View file

@ -49,8 +49,7 @@ pub struct UserRepository;
impl UserRepository {
pub async fn create(pool: &PgPool, payload: CreateUserPayload) -> Result<User, sqlx::Error> {
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<String>,
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<User, sqlx::Error> {
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<User, sqlx::Error> {
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<Vec<String>, 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<Utc>,
) -> 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<User, sqlx::Error> {
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<Utc>,
) -> 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<User, sqlx::Error> {
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<Utc>,
) -> Result<RefreshToken, sqlx::Error> {
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<RefreshToken, sqlx::Error> {
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(())

View file

@ -28,19 +28,19 @@ pub struct VideoEditorRepository;
impl VideoEditorRepository {
pub async fn get_by_user_id(pool: &PgPool, user_id: Uuid) -> Result<Option<VideoEditorProfile>, 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<VideoEditorProfile, sqlx::Error> {
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
}
}