Skip to content

Commit 9e88a91

Browse files
committed
wip: affiliate payouts again
1 parent 03b0eba commit 9e88a91

File tree

4 files changed

+143
-7
lines changed

4 files changed

+143
-7
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CREATE TABLE users_subscriptions_affiliations (
2+
id BIGSERIAL NOT NULL PRIMARY KEY,
3+
subscription_id BIGINT NOT NULL REFERENCES users_subscriptions(id),
4+
affiliate_code BIGINT NOT NULL REFERENCES affiliate_codes(id),
5+
deactivated_at TIMESTAMPTZ
6+
);
7+
8+
CREATE TABLE users_subscriptions_affiliations_payouts(
9+
id BIGSERIAL PRIMARY KEY,
10+
charge_id BIGINT NOT NULL REFERENCES charges(id),
11+
subscription_id BIGINT NOT NULL REFERENCES users_subscriptions(id),
12+
affiliate_code BIGINT NOT NULL REFERENCES affiliate_codes(id),
13+
payout_value_id BIGSERIAL NOT NULL REFERENCES payouts_values(id),
14+
UNIQUE (charge_id)
15+
);

apps/labrinth/src/database/models/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub mod user_subscription_item;
3535
pub mod users_compliance;
3636
pub mod users_notifications_preferences_item;
3737
pub mod users_redeemals;
38+
pub mod users_subscriptions_affiliations;
3839
pub mod users_subscriptions_credits;
3940
pub mod version_item;
4041

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
use chrono::{DateTime, Utc};
2+
use serde::{Deserialize, Serialize};
3+
4+
use crate::database::models::{
5+
DBAffiliateCodeId, DBChargeId, DBUserSubscriptionId,
6+
};
7+
8+
#[derive(Debug, Clone, Serialize, Deserialize)]
9+
pub struct DBUsersSubscriptionsAffiliations {
10+
pub id: i64,
11+
pub subscription_id: DBUserSubscriptionId,
12+
pub affiliate_code: DBAffiliateCodeId,
13+
pub deactivated_at: Option<DateTime<Utc>>,
14+
}
15+
16+
impl DBUsersSubscriptionsAffiliations {
17+
pub async fn insert<'a, E>(&mut self, exec: E) -> sqlx::Result<()>
18+
where
19+
E: sqlx::PgExecutor<'a>,
20+
{
21+
let id = sqlx::query_scalar!(
22+
"
23+
INSERT INTO users_subscriptions_affiliations
24+
(subscription_id, affiliate_code, deactivated_at)
25+
VALUES ($1, $2, $3)
26+
RETURNING id
27+
",
28+
self.subscription_id.0,
29+
self.affiliate_code.0,
30+
self.deactivated_at,
31+
)
32+
.fetch_one(exec)
33+
.await?;
34+
35+
self.id = id;
36+
Ok(())
37+
}
38+
39+
pub async fn update<'a, E>(&mut self, exec: E) -> sqlx::Result<()>
40+
where
41+
E: sqlx::PgExecutor<'a>,
42+
{
43+
sqlx::query!(
44+
"UPDATE users_subscriptions_affiliations
45+
SET subscription_id = $1, affiliate_code = $2, deactivated_at = $3
46+
WHERE id = $4",
47+
self.subscription_id.0,
48+
self.affiliate_code.0,
49+
self.deactivated_at,
50+
self.id
51+
)
52+
.execute(exec)
53+
.await?;
54+
Ok(())
55+
}
56+
}
57+
58+
#[derive(Debug, Clone, Serialize, Deserialize)]
59+
pub struct DBUsersSubscriptionsAffiliationsPayouts {
60+
pub id: i64,
61+
pub charge_id: DBChargeId,
62+
pub subscription_id: DBUserSubscriptionId,
63+
pub affiliate_code: DBAffiliateCodeId,
64+
pub payout_value_id: i64,
65+
}
66+
67+
impl DBUsersSubscriptionsAffiliationsPayouts {
68+
pub async fn insert<'a, E>(&mut self, exec: E) -> sqlx::Result<()>
69+
where
70+
E: sqlx::PgExecutor<'a>,
71+
{
72+
let id = sqlx::query_scalar!(
73+
"
74+
INSERT INTO users_subscriptions_affiliations_payouts
75+
(charge_id, subscription_id, affiliate_code, payout_value_id)
76+
VALUES ($1, $2, $3, $4)
77+
RETURNING id
78+
",
79+
self.charge_id.0,
80+
self.subscription_id.0,
81+
self.affiliate_code.0,
82+
self.payout_value_id,
83+
)
84+
.fetch_one(exec)
85+
.await?;
86+
87+
self.id = id;
88+
Ok(())
89+
}
90+
}

apps/labrinth/src/routes/internal/billing.rs

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,19 @@ use crate::database::models::charge_item::DBCharge;
44
use crate::database::models::ids::DBUserSubscriptionId;
55
use crate::database::models::notification_item::NotificationBuilder;
66
use crate::database::models::products_tax_identifier_item::product_info_by_product_price_id;
7+
use crate::database::models::users_subscriptions_affiliations::DBUsersSubscriptionsAffiliations;
78
use crate::database::models::users_subscriptions_credits::DBUserSubscriptionCredit;
89
use crate::database::models::{
9-
charge_item, generate_charge_id, product_item, user_subscription_item,
10+
DBAffiliateCodeId, charge_item, generate_charge_id, product_item,
11+
user_subscription_item,
1012
};
1113
use crate::database::redis::RedisPool;
1214
use crate::models::billing::{
1315
Charge, ChargeStatus, ChargeType, PaymentPlatform, Price, PriceDuration,
1416
Product, ProductMetadata, ProductPrice, SubscriptionMetadata,
1517
SubscriptionStatus, UserSubscription,
1618
};
19+
use crate::models::ids::AffiliateCodeId;
1720
use crate::models::notifications::NotificationBody;
1821
use crate::models::pats::Scopes;
1922
use crate::models::users::Badges;
@@ -1328,7 +1331,15 @@ pub enum ChargeRequestType {
13281331

13291332
#[derive(Deserialize, Serialize)]
13301333
#[serde(tag = "type", rename_all = "snake_case")]
1331-
pub enum PaymentRequestMetadata {
1334+
pub struct PaymentRequestMetadata {
1335+
#[serde(flatten)]
1336+
pub kind: PaymentRequestMetadataKind,
1337+
pub affiliate_code: Option<AffiliateCodeId>,
1338+
}
1339+
1340+
#[derive(Deserialize, Serialize)]
1341+
#[serde(tag = "type", rename_all = "snake_case")]
1342+
pub enum PaymentRequestMetadataKind {
13321343
Pyro {
13331344
server_name: Option<String>,
13341345
server_region: Option<String>,
@@ -1866,12 +1877,12 @@ pub async fn stripe_webhook(
18661877
} else {
18671878
let (server_name, server_region, source) =
18681879
if let Some(
1869-
PaymentRequestMetadata::Pyro {
1870-
ref server_name,
1871-
ref server_region,
1872-
ref source,
1880+
PaymentRequestMetadataKind::Pyro {
1881+
server_name,
1882+
server_region,
1883+
source,
18731884
},
1874-
) = metadata.payment_metadata
1885+
) = metadata.payment_metadata.as_ref().map(|m| &m.kind)
18751886
{
18761887
(
18771888
server_name.clone(),
@@ -2055,6 +2066,25 @@ pub async fn stripe_webhook(
20552066
}
20562067
.upsert(&mut transaction)
20572068
.await?;
2069+
2070+
if let Some(affiliate_code) = metadata
2071+
.payment_metadata
2072+
.as_ref()
2073+
.and_then(|m| m.affiliate_code)
2074+
{
2075+
DBUsersSubscriptionsAffiliations {
2076+
id: 0,
2077+
subscription_id: subscription.id,
2078+
affiliate_code: DBAffiliateCodeId::from(
2079+
affiliate_code,
2080+
),
2081+
deactivated_at: None,
2082+
}
2083+
.insert(&mut *transaction)
2084+
.await?;
2085+
}
2086+
2087+
// TODO affiliate code
20582088
};
20592089

20602090
subscription.status = SubscriptionStatus::Provisioned;

0 commit comments

Comments
 (0)