Skip to content

Commit 6b644b8

Browse files
committed
Add bonus days
1 parent 8d94989 commit 6b644b8

File tree

6 files changed

+100
-17
lines changed

6 files changed

+100
-17
lines changed

dev/dev.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,16 @@ CREATE INDEX idx_subscriptions_expires_at ON subscriptions(expires_at);
170170
CREATE INDEX idx_subscriptions_referred_by ON subscriptions(referred_by);
171171

172172

173+
ALTER TABLE subscriptions
174+
ADD COLUMN refer_code CHAR(13);
175+
176+
CREATE INDEX idx_subscriptions_refcode ON subscriptions(refer_code);
177+
178+
ALTER TABLE subscriptions
179+
ADD COLUMN bonus_days INTEGER DEFAULT NULL;
180+
181+
182+
173183

174184

175185

src/bin/api/core/http/handlers/sub.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,11 @@ where
281281
let down_str = format_bytes(downlink);
282282
let up_str = format_bytes(uplink);
283283

284+
let bonus_days = if let Some(days) = sub.bonus_days() {
285+
format!("{}", days)
286+
} else {
287+
format!("0")
288+
};
284289
let base_link = format!("{}/sub?id={}&env={}", host, id, env);
285290
let main_link = format!("{}/sub?id={}&format=txt&env={}", host, id, env);
286291

@@ -427,6 +432,7 @@ ul {{
427432
</div>
428433
429434
<div class="small">Вы пригласили: {invited}</div>
435+
<div class="small">Вы получили {bonus_days} бесплатных дней</div>
430436
431437
<div class="small"><a href="{web_host}/ref.html"> Информация о реферальной программе</a></div>
432438
@@ -469,8 +475,8 @@ window.onload = () => {{
469475
base_link = base_link,
470476
ref = sub.referral_code(),
471477
invited = invited,
472-
subscription_id = id
473-
);
478+
subscription_id = id,
479+
bonus_days = bonus_days );
474480

475481
Ok(Box::new(warp::reply::with_status(
476482
warp::reply::with_header(html, "Content-Type", "text/html; charset=utf-8"),

src/bin/api/core/postgres/subscription.rs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use std::sync::Arc;
22
use tokio::sync::Mutex;
33

4-
use super::PgClientManager;
54
use pony::memory::subscription::Subscription;
5+
use pony::utils::get_uuid_last_octet_simple;
66
use pony::Result;
77

8+
use super::PgClientManager;
9+
810
pub struct PgSubscription {
911
pub manager: Arc<Mutex<PgClientManager>>,
1012
}
@@ -34,41 +36,51 @@ impl PgSubscription {
3436
let mut manager = self.manager.lock().await;
3537
let client = manager.get_client().await?;
3638

39+
let ref_code = get_uuid_last_octet_simple(&new_sub.id);
40+
3741
let row = client
3842
.query_one(
3943
r#"
4044
INSERT INTO subscriptions
41-
(id, expires_at, referred_by)
42-
VALUES ($1, $2, $3)
45+
(id, expires_at, referred_by, refer_code)
46+
VALUES ($1, $2, $3, $4)
4347
RETURNING *
4448
"#,
45-
&[&new_sub.id, &new_sub.expires_at, &new_sub.referred_by],
49+
&[
50+
&new_sub.id,
51+
&new_sub.expires_at,
52+
&new_sub.referred_by,
53+
&ref_code,
54+
],
4655
)
4756
.await?;
4857

4958
Ok(Subscription::from(row))
5059
}
5160

52-
pub async fn update_expires_at(
61+
pub async fn update_subscription(
5362
&self,
5463
id: uuid::Uuid,
55-
expires_at: Option<chrono::DateTime<chrono::Utc>>,
64+
expires_at: chrono::DateTime<chrono::Utc>,
65+
bonus_days: Option<i32>,
66+
referred_by: Option<&String>,
5667
) -> Result<Subscription> {
5768
let mut manager = self.manager.lock().await;
5869
let client = manager.get_client().await?;
59-
6070
let now = chrono::Utc::now();
6171

6272
let row = client
6373
.query_one(
6474
r#"
6575
UPDATE subscriptions
66-
SET expires_at = $1,
67-
updated_at = $2
68-
WHERE id = $3
76+
SET expires_at = $1,
77+
bonus_days = $2,
78+
referred_by = $3,
79+
updated_at = $4
80+
WHERE id = $5
6981
RETURNING *
7082
"#,
71-
&[&expires_at, &now, &id],
83+
&[&expires_at, &bonus_days, &referred_by, &now, &id],
7284
)
7385
.await?;
7486

src/bin/api/core/sync/tasks.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -462,19 +462,39 @@ where
462462
sub.extend(days);
463463
}
464464

465+
if let Some(bonus_days) = sub_req.bonus_days {
466+
sub.set_bonus_days(bonus_days); // 👈 см. ниже
467+
}
468+
469+
if let Some(ref_code) = sub_req.referred_by.clone() {
470+
sub.set_referred_by(ref_code);
471+
}
472+
473+
let expires_at = sub
474+
.expires_at()
475+
.ok_or_else(|| SyncError::InconsistentState {
476+
resource: "Subscription".to_string(),
477+
id: *sub_id,
478+
})?;
479+
465480
if let Err(e) = self
466481
.db
467482
.sub()
468-
.update_expires_at(*sub_id, sub.expires_at())
483+
.update_subscription(
484+
*sub_id,
485+
expires_at,
486+
sub.bonus_days(),
487+
sub.referred_by().as_ref(),
488+
)
469489
.await
470490
{
471491
log::error!(
472-
"Failed to update subscription {} stats in database: {}",
492+
"Failed to update subscription {} in database: {}",
473493
sub_id,
474494
e
475495
);
476496
return Err(SyncError::Database(e));
477-
};
497+
}
478498

479499
log::info!("Successfully updated subscription: {}", sub_id);
480500
Ok(OperationStatus::Updated(*sub_id))

src/http/requests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pub struct SubCreateReq {
4444
pub struct SubUpdateReq {
4545
pub referred_by: Option<String>,
4646
pub days: Option<i64>,
47+
pub bonus_days: Option<i32>,
4748
}
4849

4950
#[derive(Serialize, Deserialize)]

src/memory/subscription.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ pub struct Subscription {
1414
pub id: uuid::Uuid,
1515
pub expires_at: Option<DateTime<Utc>>,
1616
pub referred_by: Option<String>,
17+
pub refer_code: Option<String>,
18+
pub bonus_days: Option<i32>,
1719
pub created_at: DateTime<Utc>,
1820
pub updated_at: DateTime<Utc>,
1921
pub is_deleted: bool,
@@ -30,6 +32,8 @@ impl Subscription {
3032
id: id,
3133
expires_at: exp_at,
3234
referred_by: ref_by,
35+
refer_code: Some(get_uuid_last_octet_simple(&id)),
36+
bonus_days: None,
3337
created_at: now,
3438
updated_at: now,
3539
is_deleted: false,
@@ -40,11 +44,16 @@ impl Subscription {
4044
impl Default for Subscription {
4145
fn default() -> Self {
4246
let now = Utc::now();
47+
let id = uuid::Uuid::new_v4();
48+
49+
let refer_code = get_uuid_last_octet_simple(&id);
4350

4451
Self {
45-
id: uuid::Uuid::new_v4(),
52+
id: id,
4653
expires_at: None,
4754
referred_by: None,
55+
refer_code: Some(refer_code),
56+
bonus_days: None,
4857
created_at: now,
4958
updated_at: now,
5059
is_deleted: false,
@@ -62,6 +71,8 @@ impl From<tokio_postgres::Row> for Subscription {
6271
id: row.get("id"),
6372
expires_at,
6473
referred_by: row.get("referred_by"),
74+
refer_code: row.get("refer_code"),
75+
bonus_days: row.get("bonus_days"),
6576
created_at,
6677
updated_at,
6778
is_deleted: row.get::<_, bool>("is_deleted"),
@@ -113,6 +124,7 @@ pub struct UpdateSubscription {
113124
pub struct SubscriptionStats {
114125
pub id: uuid::Uuid,
115126
pub expires_at: Option<DateTime<Utc>>,
127+
pub bonus_days: i32,
116128
pub days_remaining: i64,
117129
pub is_active: bool,
118130
}
@@ -126,9 +138,16 @@ impl Subscription {
126138
99999
127139
};
128140

141+
let bonus_days = if let Some(days) = self.bonus_days {
142+
days
143+
} else {
144+
0
145+
};
146+
129147
SubscriptionStats {
130148
id: self.id,
131149
expires_at: self.expires_at,
150+
bonus_days,
132151
days_remaining,
133152
is_active: days_remaining > 0 && !self.is_deleted,
134153
}
@@ -141,10 +160,13 @@ pub trait Operations {
141160
fn expires_at(&self) -> Option<DateTime<Utc>>;
142161
fn referral_code(&self) -> String;
143162
fn referred_by(&self) -> Option<String>;
163+
fn set_referred_by(&mut self, code: String);
144164
fn is_active(&self) -> bool;
145165
fn days_remaining(&self) -> Option<i64>;
146166
fn set_expires_at(&mut self, expires_at: DateTime<Utc>) -> Result<(), String>;
147167
fn mark_deleted(&mut self);
168+
fn bonus_days(&self) -> Option<i32>;
169+
fn set_bonus_days(&mut self, days: i32);
148170
}
149171

150172
impl Operations for Subscription {
@@ -171,6 +193,10 @@ impl Operations for Subscription {
171193
self.referred_by.clone()
172194
}
173195

196+
fn set_referred_by(&mut self, code: String) {
197+
self.referred_by = Some(code);
198+
}
199+
174200
fn is_active(&self) -> bool {
175201
!self.is_deleted && self.expires_at > Some(Utc::now())
176202
}
@@ -184,6 +210,14 @@ impl Operations for Subscription {
184210
}
185211
}
186212

213+
fn bonus_days(&self) -> Option<i32> {
214+
self.bonus_days.clone()
215+
}
216+
217+
fn set_bonus_days(&mut self, days: i32) {
218+
self.bonus_days = Some(days);
219+
}
220+
187221
fn set_expires_at(&mut self, expires_at: DateTime<Utc>) -> Result<(), String> {
188222
if expires_at <= Utc::now() {
189223
return Err("Expiration date must be in the future".to_string());

0 commit comments

Comments
 (0)