docs: mark MC base currency implementation as completed in redesign plan

This commit is contained in:
mik-tf
2025-09-08 15:44:39 -04:00
parent abbf59207a
commit d9a449304c
16 changed files with 139 additions and 41 deletions

View File

@@ -35,14 +35,14 @@ This document outlines the comprehensive redesign of the Project Mycelium market
- [x] Update backend currency handling - [x] Update backend currency handling
### 2. Currency System Overhaul ### 2. Currency System Overhaul
- [ ] **Implement Mycelium Credit (MC)** - [x] **Implement Mycelium Credit (MC)**
- [ ] Update currency service to use MC as base - [x] Update currency service to use MC as base
- [ ] Set initial exchange rate: 1 MC = 1 USD - [x] Set initial exchange rate: 1 MC = 1 USD
- [ ] Update currency conversion logic if needed - [x] Update currency conversion logic if needed
- [ ] Update pricing calculations if needed - [x] Update pricing calculations if needed
- [ ] **Currency Display Preferences** - [x] **Currency Display Preferences**
- [ ] Add AED to supported currencies (see /dashboard/settings Currency Preferences) - [x] Add AED to supported currencies (see /dashboard/settings Currency Preferences)
### 3. Statistics & Grid Integration ### 3. Statistics & Grid Integration
- [ ] **TF Grid Statistics** - [ ] **TF Grid Statistics**

View File

@@ -734,7 +734,7 @@ impl DashboardController {
if let Ok(Some(user_email)) = session.get::<String>("user_email") { if let Ok(Some(user_email)) = session.get::<String>("user_email") {
ctx.insert("user_email", &user_email); ctx.insert("user_email", &user_email);
if let Some(user_data) = crate::services::user_persistence::UserPersistence::load_user_data(&user_email) { if let Some(user_data) = crate::services::user_persistence::UserPersistence::load_user_data(&user_email) {
ctx.insert("user_display_currency", &user_data.display_currency.unwrap_or_else(|| "USD".to_string())); ctx.insert("user_display_currency", &user_data.display_currency.unwrap_or_else(|| "MC".to_string()));
ctx.insert("user_quick_topup_amounts", &user_data.quick_topup_amounts.unwrap_or_else(|| vec![ ctx.insert("user_quick_topup_amounts", &user_data.quick_topup_amounts.unwrap_or_else(|| vec![
rust_decimal_macros::dec!(10), rust_decimal_macros::dec!(10),
rust_decimal_macros::dec!(25), rust_decimal_macros::dec!(25),
@@ -743,7 +743,7 @@ impl DashboardController {
])); ]));
} else { } else {
// Default values if no persistent data found // Default values if no persistent data found
ctx.insert("user_display_currency", &"USD".to_string()); ctx.insert("user_display_currency", &"MC".to_string());
ctx.insert("user_quick_topup_amounts", &vec![ ctx.insert("user_quick_topup_amounts", &vec![
rust_decimal_macros::dec!(10), rust_decimal_macros::dec!(10),
rust_decimal_macros::dec!(25), rust_decimal_macros::dec!(25),

View File

@@ -180,9 +180,9 @@ impl WalletController {
let (currency, effective_currency) = match currency_service.get_currency(&display_currency) { let (currency, effective_currency) = match currency_service.get_currency(&display_currency) {
Some(c) => (c, display_currency.clone()), Some(c) => (c, display_currency.clone()),
None => { None => {
let usd = currency_service.get_currency("USD").expect("USD currency must be available"); let mc = currency_service.get_currency("MC").expect("MC currency must be available");
display_currency = "USD".to_string(); display_currency = "MC".to_string();
(usd, "USD".to_string()) (mc, "MC".to_string())
} }
}; };
@@ -258,9 +258,9 @@ impl WalletController {
let (currency, effective_currency) = match currency_service.get_currency(&display_currency) { let (currency, effective_currency) = match currency_service.get_currency(&display_currency) {
Some(c) => (c, display_currency.clone()), Some(c) => (c, display_currency.clone()),
None => { None => {
let usd = currency_service.get_currency("USD").expect("USD currency must be available"); let mc = currency_service.get_currency("MC").expect("MC currency must be available");
display_currency = "USD".to_string(); display_currency = "MC".to_string();
(usd, "USD".to_string()) (mc, "MC".to_string())
} }
}; };

View File

@@ -886,7 +886,7 @@ impl CurrencyServiceBuilder {
return Err("Base currency cannot be empty".to_string()); return Err("Base currency cannot be empty".to_string());
} }
let display_currency = self.display_currency.unwrap_or_else(|| "USD".to_string()); let display_currency = self.display_currency.unwrap_or_else(|| "MC".to_string());
Ok(crate::services::currency::CurrencyService::new_with_display_config( Ok(crate::services::currency::CurrencyService::new_with_display_config(
cache_duration, cache_duration,
@@ -1225,7 +1225,7 @@ impl SessionDataBuilder {
name: self.name, name: self.name,
country: self.country, country: self.country,
timezone: self.timezone, timezone: self.timezone,
display_currency: Some("USD".to_string()), display_currency: Some("MC".to_string()),
quick_topup_amounts: Some(vec![dec!(10), dec!(25), dec!(50), dec!(100)]), quick_topup_amounts: Some(vec![dec!(10), dec!(25), dec!(50), dec!(100)]),
..Default::default() ..Default::default()
} }

View File

@@ -325,7 +325,7 @@ impl InstantPurchaseService {
let mut persistent_data = UserPersistence::load_user_data(&user_email) let mut persistent_data = UserPersistence::load_user_data(&user_email)
.unwrap_or_else(|| crate::services::user_persistence::UserPersistentData { .unwrap_or_else(|| crate::services::user_persistence::UserPersistentData {
user_email: user_email.clone(), user_email: user_email.clone(),
display_currency: Some("USD".to_string()), display_currency: Some("MC".to_string()),
quick_topup_amounts: Some(vec![dec!(10), dec!(25), dec!(50), dec!(100)]), quick_topup_amounts: Some(vec![dec!(10), dec!(25), dec!(50), dec!(100)]),
..Default::default() ..Default::default()
}); });

View File

@@ -79,16 +79,16 @@ impl NavbarService {
// Get user's preferred display currency // Get user's preferred display currency
let mut display_currency = self.currency_service.get_user_preferred_currency(session); let mut display_currency = self.currency_service.get_user_preferred_currency(session);
// Get currency info for formatting; fall back to USD if invalid // Get currency info for formatting; fall back to MC if invalid
let (currency, effective_currency) = match self.currency_service.get_currency(&display_currency) { let (currency, effective_currency) = match self.currency_service.get_currency(&display_currency) {
Some(c) => (c, display_currency.clone()), Some(c) => (c, display_currency.clone()),
None => { None => {
let usd = self let mc = self
.currency_service .currency_service
.get_currency("USD") .get_currency("MC")
.expect("USD currency must be available"); .expect("MC currency must be available");
display_currency = "USD".to_string(); display_currency = "MC".to_string();
(usd, "USD".to_string()) (mc, "MC".to_string())
} }
}; };
@@ -150,8 +150,8 @@ impl NavbarService {
user_email: String::new(), user_email: String::new(),
wallet_balance: Decimal::ZERO, wallet_balance: Decimal::ZERO,
wallet_balance_formatted: "Not logged in".to_string(), wallet_balance_formatted: "Not logged in".to_string(),
display_currency: "USD".to_string(), display_currency: "MC".to_string(),
currency_symbol: "$".to_string(), currency_symbol: "".to_string(),
quick_actions: vec![ quick_actions: vec![
QuickAction { QuickAction {
id: "login".to_string(), id: "login".to_string(),

View File

@@ -1352,7 +1352,7 @@ impl UserPersistence {
UserPersistentData { UserPersistentData {
user_email: user_email.to_string(), user_email: user_email.to_string(),
wallet_balance_usd: dec!(0), wallet_balance_usd: dec!(0),
display_currency: Some("USD".to_string()), display_currency: Some("MC".to_string()),
quick_topup_amounts: Some(vec![dec!(10), dec!(25), dec!(50), dec!(100)]), quick_topup_amounts: Some(vec![dec!(10), dec!(25), dec!(50), dec!(100)]),
..Default::default() ..Default::default()
} }
@@ -1363,7 +1363,7 @@ impl UserPersistence {
UserPersistentData { UserPersistentData {
user_email: user_email.to_string(), user_email: user_email.to_string(),
wallet_balance_usd: balance, wallet_balance_usd: balance,
display_currency: Some("USD".to_string()), display_currency: Some("MC".to_string()),
quick_topup_amounts: Some(vec![dec!(10), dec!(25), dec!(50), dec!(100)]), quick_topup_amounts: Some(vec![dec!(10), dec!(25), dec!(50), dec!(100)]),
..Default::default() ..Default::default()
} }

View File

@@ -15,8 +15,8 @@
} }
const hyd = readHydration('hydration-dashboard-cart'); const hyd = readHydration('hydration-dashboard-cart');
const currencySymbol = (hyd && hyd.currency_symbol) || '$'; const currencySymbol = (hyd && hyd.currency_symbol) || '';
const displayCurrency = (hyd && hyd.display_currency) || 'USD'; const displayCurrency = (hyd && hyd.display_currency) || 'MC';
const showToast = (window.showToast) ? window.showToast : function (msg, type) { const showToast = (window.showToast) ? window.showToast : function (msg, type) {
// Fallback: log to console in case toast helper isn't available // Fallback: log to console in case toast helper isn't available

View File

@@ -2,7 +2,7 @@
(function () { (function () {
'use strict'; 'use strict';
let HYDRATION = { currency_symbol: '$', display_currency: 'USD' }; let HYDRATION = { currency_symbol: '', display_currency: 'MC' };
function parseHydration() { function parseHydration() {
try { try {

View File

@@ -15,8 +15,8 @@
} }
const hyd = readHydration('wallet-hydration'); const hyd = readHydration('wallet-hydration');
const currencySymbol = (hyd && hyd.currency_symbol) || '$'; const currencySymbol = (hyd && hyd.currency_symbol) || '';
const displayCurrency = (hyd && hyd.display_currency) || 'USD'; const displayCurrency = (hyd && hyd.display_currency) || 'MC';
function showSuccessToast(message) { function showSuccessToast(message) {
try { try {

View File

@@ -73,7 +73,7 @@
<!-- Wallet Balance Check --> <!-- Wallet Balance Check -->
<div class="wallet-status mb-3"> <div class="wallet-status mb-3">
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<span>Your {{ display_currency | default(value="USD") }} Credits:</span> <span>Your {{ display_currency | default(value="MC") }} Credits:</span>
<span class="fw-bold" id="userBalance">{{ currency_symbol | default(value="$") }}0.00</span> <span class="fw-bold" id="userBalance">{{ currency_symbol | default(value="$") }}0.00</span>
</div> </div>
<div class="balance-indicator mt-2" id="balanceIndicator"> <div class="balance-indicator mt-2" id="balanceIndicator">
@@ -197,7 +197,7 @@
<script id="hydration-dashboard-cart" type="application/json"> <script id="hydration-dashboard-cart" type="application/json">
{ {
"currency_symbol": {{ currency_symbol | default(value="$") | json_encode() }}, "currency_symbol": {{ currency_symbol | default(value="$") | json_encode() }},
"display_currency": {{ display_currency | default(value="USD") | json_encode() }} "display_currency": {{ display_currency | default(value="MC") | json_encode() }}
} }
</script> </script>
{% endblock %} {% endblock %}

View File

@@ -50,7 +50,7 @@
<h5 class="card-title">Wallet Balance</h5> <h5 class="card-title">Wallet Balance</h5>
<div class="d-flex justify-content-between align-items-end"> <div class="d-flex justify-content-between align-items-end">
<h2 class="mb-0" id="dashboardWalletBalance">{{ currency_symbol | default(value="$") }}{% if user_metrics is defined and user_metrics.wallet_balance is defined %}{{ user_metrics.wallet_balance | format_decimal(precision=2) }}{% else %}0{% endif %}</h2> <h2 class="mb-0" id="dashboardWalletBalance">{{ currency_symbol | default(value="$") }}{% if user_metrics is defined and user_metrics.wallet_balance is defined %}{{ user_metrics.wallet_balance | format_decimal(precision=2) }}{% else %}0{% endif %}</h2>
<small class="text-muted">Credits (<span id="dashboardCurrencyCode">{{ display_currency | default(value="USD") }}</span>)</small> <small class="text-muted">Credits (<span id="dashboardCurrencyCode">{{ display_currency | default(value="MC") }}</span>)</small>
</div> </div>
</div> </div>
</div> </div>
@@ -266,7 +266,7 @@
<!-- JSON hydration for dashboard charts --> <!-- JSON hydration for dashboard charts -->
<script type="application/json" id="dashboard-chart-data"> <script type="application/json" id="dashboard-chart-data">
{ {
"displayCurrency": "{% if display_currency is defined and display_currency %}{{ display_currency }}{% else %}USD{% endif %}", "displayCurrency": "{% if display_currency is defined and display_currency %}{{ display_currency }}{% else %}MC{% endif %}",
"resourceUtilization": { "resourceUtilization": {
{% if user_metrics is defined and user_metrics.resource_utilization is defined %} {% if user_metrics is defined and user_metrics.resource_utilization is defined %}
"cpu": {{ user_metrics.resource_utilization.cpu }}, "cpu": {{ user_metrics.resource_utilization.cpu }},

View File

@@ -194,7 +194,7 @@
<script type="application/json" id="orders-hydration"> <script type="application/json" id="orders-hydration">
{ {
"currency_symbol": {{ currency_symbol | default(value='$') | json_encode() }}, "currency_symbol": {{ currency_symbol | default(value='$') | json_encode() }},
"display_currency": {{ display_currency | default(value='USD') | json_encode() }} "display_currency": {{ display_currency | default(value='MC') | json_encode() }}
} }
</script> </script>
<script src="/static/js/dashboard_orders.js"></script> <script src="/static/js/dashboard_orders.js"></script>

View File

@@ -20,7 +20,7 @@
{{ currency_symbol | default(value="$") }}0.00 {{ currency_symbol | default(value="$") }}0.00
{% endif %} {% endif %}
</h2> </h2>
<small class="text-light">Credits ({{ display_currency | default(value="USD") }})</small> <small class="text-light">Credits ({{ display_currency | default(value="MC") }})</small>
</div> </div>
</div> </div>
</div> </div>
@@ -270,7 +270,7 @@
</div> </div>
<div class="mb-3"> <div class="mb-3">
<div class="alert alert-info"> <div class="alert alert-info">
<strong>Rate:</strong> 1 Credit = {{ currency_symbol | default(value="$") }}1 {{ display_currency | default(value="USD") }}<br> <strong>Rate:</strong> 1 Credit = {{ currency_symbol | default(value="") }}1 {{ display_currency | default(value="MC") }}<br>
<strong>Total Cost:</strong> {{ currency_symbol | default(value="$") }}<span id="totalCost">0.00</span> <strong>Total Cost:</strong> {{ currency_symbol | default(value="$") }}<span id="totalCost">0.00</span>
</div> </div>
</div> </div>
@@ -435,7 +435,7 @@
<script type="application/json" id="wallet-hydration"> <script type="application/json" id="wallet-hydration">
{ {
"currency_symbol": {{ currency_symbol | default(value='$') | json_encode() }}, "currency_symbol": {{ currency_symbol | default(value='$') | json_encode() }},
"display_currency": {{ display_currency | default(value='USD') | json_encode() }} "display_currency": {{ display_currency | default(value='MC') | json_encode() }}
} }
</script> </script>
<script src="/static/js/dashboard_wallet.js"></script> <script src="/static/js/dashboard_wallet.js"></script>

View File

@@ -0,0 +1,49 @@
{
"user_email": "user111@example.com",
"wallet_balance_usd": 0.0,
"transactions": [],
"staked_amount_usd": 0.0,
"pool_positions": {},
"name": "user111",
"country": null,
"timezone": null,
"password_hash": "$2b$12$0I0taABmXC9qgK/oe1ynjO/eVIG4sdguLm6DLQffvbjU33jkSe6Ti",
"services": [],
"service_requests": [],
"service_bookings": [],
"availability": null,
"slas": [],
"apps": [],
"application_deployments": [],
"deleted": null,
"deleted_at": null,
"deletion_reason": null,
"nodes": [],
"resource_provider_earnings": [],
"resource_provider_settings": null,
"slice_products": [],
"user_activities": [],
"user_preferences": null,
"usage_statistics": null,
"orders": [],
"active_product_rentals": [],
"resource_provider_rental_earnings": [],
"node_rentals": [],
"node_groups": [],
"slice_rentals": [],
"slice_assignments": [],
"display_currency": "MC",
"quick_topup_amounts": [
10.0,
25.0,
50.0,
100.0
],
"auto_topup_settings": null,
"products": [],
"owned_products": [],
"owned_product_ids": [],
"ssh_keys": [],
"message_threads": null,
"messages": null
}

View File

@@ -0,0 +1,49 @@
{
"user_email": "user321@example.com",
"wallet_balance_usd": 0.0,
"transactions": [],
"staked_amount_usd": 0.0,
"pool_positions": {},
"name": "user321",
"country": null,
"timezone": null,
"password_hash": "$2b$12$3I5q1NB/ukv2isB6p5RN1ecn6Wkb92gmD2O5gzQ8YF3veOLUa1JXu",
"services": [],
"service_requests": [],
"service_bookings": [],
"availability": null,
"slas": [],
"apps": [],
"application_deployments": [],
"deleted": null,
"deleted_at": null,
"deletion_reason": null,
"nodes": [],
"resource_provider_earnings": [],
"resource_provider_settings": null,
"slice_products": [],
"user_activities": [],
"user_preferences": null,
"usage_statistics": null,
"orders": [],
"active_product_rentals": [],
"resource_provider_rental_earnings": [],
"node_rentals": [],
"node_groups": [],
"slice_rentals": [],
"slice_assignments": [],
"display_currency": "MC",
"quick_topup_amounts": [
10.0,
25.0,
50.0,
100.0
],
"auto_topup_settings": null,
"products": [],
"owned_products": [],
"owned_product_ids": [],
"ssh_keys": [],
"message_threads": null,
"messages": null
}