Региональные цены: UAH/BYN/VND/UZS + обобщённый список по валюте
plan_prices уже поддерживал мультивалютность (USD/RUB/CNY/TRY/IRR) — просто добавляю ещё 4 по аналогии, по локалям уже сделанным в этой сессии (uk/be/vi/uz). Цифры — прикидка (~45% от рыночной конвертации, тот же порядок, что уже неявно в RUB/CNY/TRY), не сверено с реальными конкурентами по каждому рынку — легко поправить UPDATE'ом по этой же таблице. list_active_plans_by_currency — обобщённая версия list_active_plans_usd, нужна для мультивалютного /plans и бота.
This commit is contained in:
@@ -0,0 +1,74 @@
|
|||||||
|
-- Расширение регионального прайса: UAH/BYN/VND/UZS — по аналогии с уже
|
||||||
|
-- заведёнными USD/RUB/CNY/TRY/IRR (см. 0001_init.sql). Валюты выбраны по
|
||||||
|
-- уже сделанным в этой сессии локалям (uk/be/vi/uz).
|
||||||
|
--
|
||||||
|
-- Курс и скидка (~45% от чистой рыночной конвертации, тот же порядок, что
|
||||||
|
-- уже неявно заложен в RUB/CNY/TRY) — ПРИКИДКА для старта, не сверено с
|
||||||
|
-- реальными локальными конкурентами по каждому рынку. Легко поправить —
|
||||||
|
-- это просто UPDATE по этой же таблице, менять код не нужно.
|
||||||
|
--
|
||||||
|
-- VND/UZS — целыми единицами (без копеек/копий), та же логика, что уже у
|
||||||
|
-- IRR: у донга и сума нет ходовой разменной монеты, дробные суммы не имеют
|
||||||
|
-- смысла для конечного пользователя.
|
||||||
|
INSERT INTO plan_prices (plan_name, currency, amount) VALUES
|
||||||
|
-- =================================================================
|
||||||
|
-- УКРАИНА (UAH)
|
||||||
|
-- =================================================================
|
||||||
|
('GHOST_1M', 'UAH', 11900), -- 119.00 ₴
|
||||||
|
('GHOST_6M', 'UAH', 59900), -- 599.00 ₴
|
||||||
|
('GHOST_12M', 'UAH', 89900), -- 899.00 ₴
|
||||||
|
|
||||||
|
('NETRUNNER_1M', 'UAH', 21900), -- 219.00 ₴
|
||||||
|
('NETRUNNER_6M', 'UAH', 109900), -- 1 099.00 ₴
|
||||||
|
('NETRUNNER_12M', 'UAH', 149900), -- 1 499.00 ₴
|
||||||
|
|
||||||
|
('MAINFRAME_1M', 'UAH', 49900), -- 499.00 ₴
|
||||||
|
('MAINFRAME_6M', 'UAH', 229900), -- 2 299.00 ₴
|
||||||
|
('MAINFRAME_12M', 'UAH', 349900), -- 3 499.00 ₴
|
||||||
|
|
||||||
|
-- =================================================================
|
||||||
|
-- БЕЛАРУСЬ (BYN)
|
||||||
|
-- =================================================================
|
||||||
|
('GHOST_1M', 'BYN', 900), -- 9.00 Br
|
||||||
|
('GHOST_6M', 'BYN', 4400), -- 44.00 Br
|
||||||
|
('GHOST_12M', 'BYN', 6500), -- 65.00 Br
|
||||||
|
|
||||||
|
('NETRUNNER_1M', 'BYN', 1650), -- 16.50 Br
|
||||||
|
('NETRUNNER_6M', 'BYN', 8200), -- 82.00 Br
|
||||||
|
('NETRUNNER_12M', 'BYN', 10900), -- 109.00 Br
|
||||||
|
|
||||||
|
('MAINFRAME_1M', 'BYN', 3600), -- 36.00 Br
|
||||||
|
('MAINFRAME_6M', 'BYN', 17500), -- 175.00 Br
|
||||||
|
('MAINFRAME_12M', 'BYN', 26000), -- 260.00 Br
|
||||||
|
|
||||||
|
-- =================================================================
|
||||||
|
-- ВЬЕТНАМ (VND) — целыми донгами, без копеек (см. заголовок)
|
||||||
|
-- =================================================================
|
||||||
|
('GHOST_1M', 'VND', 69000), -- 69 000 ₫
|
||||||
|
('GHOST_6M', 'VND', 329000), -- 329 000 ₫
|
||||||
|
('GHOST_12M', 'VND', 499000), -- 499 000 ₫
|
||||||
|
|
||||||
|
('NETRUNNER_1M', 'VND', 125000), -- 125 000 ₫
|
||||||
|
('NETRUNNER_6M', 'VND', 619000), -- 619 000 ₫
|
||||||
|
('NETRUNNER_12M', 'VND', 829000), -- 829 000 ₫
|
||||||
|
|
||||||
|
('MAINFRAME_1M', 'VND', 279000), -- 279 000 ₫
|
||||||
|
('MAINFRAME_6M', 'VND', 1329000), -- 1 329 000 ₫
|
||||||
|
('MAINFRAME_12M', 'VND', 1999000), -- 1 999 000 ₫
|
||||||
|
|
||||||
|
-- =================================================================
|
||||||
|
-- УЗБЕКИСТАН (UZS) — целыми сумами, без копеек (см. заголовок)
|
||||||
|
-- =================================================================
|
||||||
|
('GHOST_1M', 'UZS', 35000), -- 35 000 сум
|
||||||
|
('GHOST_6M', 'UZS', 169000), -- 169 000 сум
|
||||||
|
('GHOST_12M', 'UZS', 249000), -- 249 000 сум
|
||||||
|
|
||||||
|
('NETRUNNER_1M', 'UZS', 63000), -- 63 000 сум
|
||||||
|
('NETRUNNER_6M', 'UZS', 319000), -- 319 000 сум
|
||||||
|
('NETRUNNER_12M', 'UZS', 419000), -- 419 000 сум
|
||||||
|
|
||||||
|
('MAINFRAME_1M', 'UZS', 139000), -- 139 000 сум
|
||||||
|
('MAINFRAME_6M', 'UZS', 669000), -- 669 000 сум
|
||||||
|
('MAINFRAME_12M', 'UZS', 999000) -- 999 000 сум
|
||||||
|
ON CONFLICT (plan_name, currency) DO UPDATE
|
||||||
|
SET amount = EXCLUDED.amount;
|
||||||
@@ -124,6 +124,15 @@ pub trait AppRepository: Send + Sync {
|
|||||||
/// `0001_init.sql`), а не потому что CryptoBot требует именно её.
|
/// `0001_init.sql`), а не потому что CryptoBot требует именно её.
|
||||||
async fn list_active_plans_usd(&self) -> Result<Vec<(String, i64)>, sqlx::Error>;
|
async fn list_active_plans_usd(&self) -> Result<Vec<(String, i64)>, sqlx::Error>;
|
||||||
|
|
||||||
|
/// Обобщённая версия `list_active_plans_usd` — тарифы в произвольной
|
||||||
|
/// валюте (см. `modules::geoip` — валюта определяется по IP/языку).
|
||||||
|
/// Пустой Vec, если для этой валюты нет ни одной активной строки в
|
||||||
|
/// `plan_prices` (вызывающая сторона должна фолбэкнуться на USD).
|
||||||
|
async fn list_active_plans_by_currency(
|
||||||
|
&self,
|
||||||
|
currency: &str,
|
||||||
|
) -> Result<Vec<(String, i64)>, sqlx::Error>;
|
||||||
|
|
||||||
async fn create_invoice(
|
async fn create_invoice(
|
||||||
&self,
|
&self,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
@@ -728,6 +737,22 @@ impl AppRepository for PgRepository {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self))]
|
||||||
|
async fn list_active_plans_by_currency(
|
||||||
|
&self,
|
||||||
|
currency: &str,
|
||||||
|
) -> Result<Vec<(String, i64)>, sqlx::Error> {
|
||||||
|
sqlx::query_as(
|
||||||
|
"SELECT pp.plan_name, pp.amount FROM plan_prices pp \
|
||||||
|
JOIN plans p ON p.name = pp.plan_name \
|
||||||
|
WHERE pp.currency = $1 AND pp.is_active = TRUE AND p.is_active = TRUE \
|
||||||
|
ORDER BY pp.amount ASC",
|
||||||
|
)
|
||||||
|
.bind(currency)
|
||||||
|
.fetch_all(&self.pool)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(skip(self))]
|
#[instrument(skip(self))]
|
||||||
async fn create_invoice(
|
async fn create_invoice(
|
||||||
&self,
|
&self,
|
||||||
|
|||||||
Reference in New Issue
Block a user