1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
use chrono::{DateTime, Utc};
use serde_json::Value as JsonValue;

#[derive(Debug, PartialEq, Clone, sqlx::FromRow)]
pub struct Coupon {
    pub coupon: String,
    pub discount: JsonValue,
    pub remaining: i32,
    pub email: Option<String>,
    pub valid_until: Option<DateTime<Utc>>,
    pub created_at: DateTime<Utc>,
}

pub async fn fetch_for_update<'e>(
    coupon: &str,
    conn: impl sqlx::Executor<'_, Database = sqlx::Postgres>,
) -> Result<Option<Coupon>, sqlx::Error> {
    sqlx::query_as("SELECT * FROM coupons WHERE coupon = $1 FOR UPDATE")
        .bind(coupon)
        .fetch_optional(conn)
        .await
}

pub async fn decrease_remaining<'e>(
    coupon: &str,
    conn: impl sqlx::Executor<'_, Database = sqlx::Postgres>,
) -> Result<(), sqlx::Error> {
    sqlx::query("UPDATE coupons SET remaining = remaining - 1 WHERE coupon = $1")
        .bind(coupon)
        .execute(conn)
        .await?;
    Ok(())
}