feat: rename farmer to resource provider across codebase and update terminology

This commit is contained in:
mik-tf
2025-09-06 23:27:14 -04:00
parent bf273102cb
commit c8e28cf8ed
34 changed files with 511 additions and 511 deletions

View File

@@ -392,11 +392,11 @@ impl DashboardController {
render_template(&tmpl, "dashboard/user.html", &ctx) render_template(&tmpl, "dashboard/user.html", &ctx)
} }
/// Renders the farmer section of the dashboard /// Renders the resource provider section of the dashboard
pub async fn farmer_section(tmpl: web::Data<Tera>, session: Session) -> Result<impl Responder> { pub async fn resource_provider_section(tmpl: web::Data<Tera>, session: Session) -> Result<impl Responder> {
let mut ctx = crate::models::builders::ContextBuilder::new() let mut ctx = crate::models::builders::ContextBuilder::new()
.active_page("dashboard") .active_page("dashboard")
.active_section("farmer") .active_section("resource_provider")
.gitea_enabled(get_app_config().is_gitea_enabled()) .gitea_enabled(get_app_config().is_gitea_enabled())
.build(); .build();
@@ -406,17 +406,17 @@ impl DashboardController {
return render_template(&tmpl, "dashboard/welcome.html", &ctx); return render_template(&tmpl, "dashboard/welcome.html", &ctx);
} }
// FARMER FIX: Use persistent data only, no mock data for farmer dashboard // RESOURCE PROVIDER FIX: Use persistent data only, no mock data for resource provider dashboard
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);
// Initialize farmer service with slice calculator // Initialize resource provider service with slice calculator
if let Ok(farmer_service) = crate::services::farmer::FarmerService::builder().build() { if let Ok(resource_provider_service) = crate::services::resource_provider::ResourceProviderService::builder().build() {
// Repair node-group data consistency when farmer dashboard loads // Repair node-group data consistency when resource provider dashboard loads
if let Err(_e) = farmer_service.repair_node_group_consistency(&user_email) { if let Err(_e) = resource_provider_service.repair_node_group_consistency(&user_email) {
} }
// Repair missing marketplace SLA data for existing nodes // Repair missing marketplace SLA data for existing nodes
if let Err(_e) = farmer_service.repair_missing_marketplace_sla( if let Err(_e) = resource_provider_service.repair_missing_marketplace_sla(
&user_email, &user_email,
99.8, // default uptime 99.8, // default uptime
100, // default bandwidth 100, // default bandwidth
@@ -424,18 +424,18 @@ impl DashboardController {
) { ) {
} }
// Get farmer nodes with updated slice calculations // Get resource provider nodes with updated slice calculations
let farmer_nodes = farmer_service.get_farmer_nodes(&user_email); let resource_provider_nodes = resource_provider_service.get_resource_provider_nodes(&user_email);
// Calculate farmer statistics from nodes // Calculate resource_provider statistics from nodes
let total_nodes = farmer_nodes.len() as u32; let total_nodes = resource_provider_nodes.len() as u32;
let mut online_nodes = 0u32; let mut online_nodes = 0u32;
let mut total_base_slices = 0u32; let mut total_base_slices = 0u32;
let mut allocated_base_slices = 0u32; let mut allocated_base_slices = 0u32;
let mut total_monthly_earnings = rust_decimal::Decimal::ZERO; let mut total_monthly_earnings = rust_decimal::Decimal::ZERO;
let mut average_uptime = 0.0f32; let mut average_uptime = 0.0f32;
for node in &farmer_nodes { for node in &resource_provider_nodes {
if matches!(node.status, crate::models::user::NodeStatus::Online) { if matches!(node.status, crate::models::user::NodeStatus::Online) {
online_nodes += 1; online_nodes += 1;
} }
@@ -449,8 +449,8 @@ impl DashboardController {
average_uptime /= total_nodes as f32; average_uptime /= total_nodes as f32;
} }
// Create farmer statistics for the dashboard // Create resource_provider statistics for the dashboard
let farmer_stats = serde_json::json!({ let resource_provider_stats = serde_json::json!({
"total_nodes": total_nodes, "total_nodes": total_nodes,
"online_nodes": online_nodes, "online_nodes": online_nodes,
"total_base_slices": total_base_slices, "total_base_slices": total_base_slices,
@@ -465,8 +465,8 @@ impl DashboardController {
} }
}); });
ctx.insert("farmer_stats", &farmer_stats); ctx.insert("resource_provider_stats", &resource_provider_stats);
ctx.insert("farmer_nodes", &farmer_nodes); ctx.insert("resource_provider_nodes", &resource_provider_nodes);
} }
// Load user data from session (without mock data override) // Load user data from session (without mock data override)
@@ -490,7 +490,7 @@ impl DashboardController {
} }
ctx.insert("wallet_balance", &persistent_data.wallet_balance_usd); ctx.insert("wallet_balance", &persistent_data.wallet_balance_usd);
ctx.insert("farmer_earnings", &persistent_data.farmer_earnings); ctx.insert("resource_provider_earnings", &persistent_data.resource_provider_earnings);
} }
ctx.insert("user_json", &user_json); ctx.insert("user_json", &user_json);
@@ -498,10 +498,10 @@ impl DashboardController {
} }
} }
// Load slice rental service to get farmer slice rental statistics // Load slice rental service to get resource_provider slice rental statistics
if let Ok(slice_rental_service) = crate::services::slice_rental::SliceRentalService::builder().build() { if let Ok(slice_rental_service) = crate::services::slice_rental::SliceRentalService::builder().build() {
let farmer_slice_stats = slice_rental_service.get_farmer_slice_statistics(&user_email); let resource_provider_slice_stats = slice_rental_service.get_resource_provider_slice_statistics(&user_email);
ctx.insert("slice_rental_statistics", &farmer_slice_stats); ctx.insert("slice_rental_statistics", &resource_provider_slice_stats);
// Release any expired rentals // Release any expired rentals
if let Err(_e) = slice_rental_service.release_expired_rentals(&user_email) { if let Err(_e) = slice_rental_service.release_expired_rentals(&user_email) {
@@ -509,7 +509,7 @@ impl DashboardController {
} }
} }
render_template(&tmpl, "dashboard/farmer.html", &ctx) render_template(&tmpl, "dashboard/resource_provider.html", &ctx)
} }
/// Renders the app provider section of the dashboard /// Renders the app provider section of the dashboard
@@ -837,13 +837,13 @@ impl DashboardController {
render_template(&tmpl, "dashboard/pools.html", &ctx) render_template(&tmpl, "dashboard/pools.html", &ctx)
} }
/// API endpoint to return farmer dashboard data as JSON /// API endpoint to return resource_provider dashboard data as JSON
pub async fn farmer_data_api(session: Session) -> Result<impl Responder> { pub async fn resource_provider_data_api(session: Session) -> Result<impl Responder> {
let user_email = session.get::<String>("user_email").unwrap_or_default().unwrap_or_default(); let user_email = session.get::<String>("user_email").unwrap_or_default().unwrap_or_default();
// FARMER FIX: Use farmer service to ensure data consistency // RESOURCE_PROVIDER FIX: Use resource_provider service to ensure data consistency
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(_e) => { Err(_e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -853,16 +853,16 @@ impl DashboardController {
}; };
// Repair data consistency before loading // Repair data consistency before loading
if let Err(_e) = farmer_service.repair_node_group_consistency(&user_email) { if let Err(_e) = resource_provider_service.repair_node_group_consistency(&user_email) {
} }
// Load real farmer data from persistence using farmer service // Load real resource_provider data from persistence using resource_provider service
let nodes = farmer_service.get_farmer_nodes(&user_email); let nodes = resource_provider_service.get_resource_provider_nodes(&user_email);
let earnings = farmer_service.get_farmer_earnings(&user_email); let earnings = resource_provider_service.get_resource_provider_earnings(&user_email);
let stats = farmer_service.get_farmer_statistics(&user_email); let stats = resource_provider_service.get_resource_provider_statistics(&user_email);
// Always use persistent data - no fallback to mock data for farmer dashboard // Always use persistent data - no fallback to mock data for resource_provider dashboard
// If no data exists, return empty but valid farmer data structure // If no data exists, return empty but valid resource_provider data structure
if nodes.is_empty() { if nodes.is_empty() {
return Ok(ResponseBuilder::ok() return Ok(ResponseBuilder::ok()
.json(serde_json::json!({ .json(serde_json::json!({
@@ -885,12 +885,12 @@ impl DashboardController {
.build()); .build());
} }
// Load slice products for this farmer // Load slice products for this resource_provider
let slice_products = crate::services::user_persistence::UserPersistence::get_slice_products(&user_email); let slice_products = crate::services::user_persistence::UserPersistence::get_slice_products(&user_email);
let active_slices = slice_products.len() as i32; let active_slices = slice_products.len() as i32;
// Build comprehensive farmer data using statistics from farmer service // Build comprehensive resource_provider data using statistics from resource_provider service
let farmer_data = serde_json::json!({ let resource_provider_data = serde_json::json!({
"total_nodes": stats.total_nodes, "total_nodes": stats.total_nodes,
"online_nodes": stats.online_nodes, "online_nodes": stats.online_nodes,
"total_capacity": stats.total_capacity, "total_capacity": stats.total_capacity,
@@ -904,13 +904,13 @@ impl DashboardController {
"slice_products": slice_products "slice_products": slice_products
}); });
Ok(ResponseBuilder::ok() Ok(ResponseBuilder::ok()
.json(farmer_data) .json(resource_provider_data)
.build()) .build())
} }
/// Enhanced farmer dashboard with node management /// Enhanced resource_provider dashboard with node management
pub async fn farmer_dashboard_enhanced(tmpl: web::Data<Tera>, session: Session) -> Result<impl Responder> { pub async fn resource_provider_dashboard_enhanced(tmpl: web::Data<Tera>, session: Session) -> Result<impl Responder> {
let farmer_service = crate::services::farmer::FarmerService::builder() let resource_provider_service = crate::services::resource_provider::ResourceProviderService::builder()
.auto_sync_enabled(true) .auto_sync_enabled(true)
.metrics_collection(true) .metrics_collection(true)
.build() .build()
@@ -922,14 +922,14 @@ impl DashboardController {
.unwrap_or_default() .unwrap_or_default()
.unwrap_or_default(); .unwrap_or_default();
// Load farmer data using the service // Load resource_provider data using the service
let nodes = farmer_service.get_farmer_nodes(&user_email); let nodes = resource_provider_service.get_resource_provider_nodes(&user_email);
let earnings = farmer_service.get_farmer_earnings(&user_email); let earnings = resource_provider_service.get_resource_provider_earnings(&user_email);
let stats = farmer_service.get_farmer_statistics(&user_email); let stats = resource_provider_service.get_resource_provider_statistics(&user_email);
let mut ctx = crate::models::builders::ContextBuilder::new() let mut ctx = crate::models::builders::ContextBuilder::new()
.active_page("dashboard") .active_page("dashboard")
.active_section("farmer") .active_section("resource_provider")
.build(); .build();
ctx.insert("nodes", &nodes); ctx.insert("nodes", &nodes);
@@ -944,10 +944,10 @@ impl DashboardController {
ctx.insert("user", &user); ctx.insert("user", &user);
} }
render_template(&tmpl, "dashboard/farmer.html", &ctx) render_template(&tmpl, "dashboard/resource_provider.html", &ctx)
} }
/// API endpoint to add a new farm node using FarmerService /// API endpoint to add a new farm node using ResourceProviderService
pub async fn add_farm_node_enhanced(session: Session, form: web::Json<serde_json::Value>) -> Result<impl Responder> { pub async fn add_farm_node_enhanced(session: Session, form: web::Json<serde_json::Value>) -> Result<impl Responder> {
let user_email = session.get::<String>("user_email") let user_email = session.get::<String>("user_email")
@@ -960,8 +960,8 @@ impl DashboardController {
})).build()); })).build());
} }
// Initialize farmer service // Initialize resource_provider service
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(_e) => { Err(_e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -1064,7 +1064,7 @@ impl DashboardController {
.bandwidth_mbps(node_data_json.get("bandwidth_mbps") .bandwidth_mbps(node_data_json.get("bandwidth_mbps")
.and_then(|v| v.as_i64()) .and_then(|v| v.as_i64())
.unwrap_or(100) as i32) .unwrap_or(100) as i32)
.node_type("MyceliumNode"); // Always MyceliumNode - farmers register MyceliumNodes to Mycelium Grid .node_type("MyceliumNode"); // Always MyceliumNode - resource providers register MyceliumNodes to Mycelium Grid
// Add optional fields // Add optional fields
if let Some(region) = node_data_json.get("region").and_then(|v| v.as_str()) { if let Some(region) = node_data_json.get("region").and_then(|v| v.as_str()) {
@@ -1087,8 +1087,8 @@ impl DashboardController {
actix_web::error::ErrorBadRequest(format!("Invalid node data: {}", e)) actix_web::error::ErrorBadRequest(format!("Invalid node data: {}", e))
})?; })?;
// Add node using farmer service // Add node using resource_provider service
match farmer_service.add_node(&user_email, node_data) { match resource_provider_service.add_node(&user_email, node_data) {
Ok(node) => { Ok(node) => {
// Add activity record // Add activity record
@@ -1143,7 +1143,7 @@ impl DashboardController {
_ => crate::models::user::NodeStatus::Offline, _ => crate::models::user::NodeStatus::Offline,
}; };
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -1152,7 +1152,7 @@ impl DashboardController {
} }
}; };
match farmer_service.update_node_status(&user_email, &node_id, status) { match resource_provider_service.update_node_status(&user_email, &node_id, status) {
Ok(()) => { Ok(()) => {
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
"success": true, "success": true,
@@ -1182,7 +1182,7 @@ impl DashboardController {
let node_id = path.into_inner(); let node_id = path.into_inner();
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -1191,7 +1191,7 @@ impl DashboardController {
} }
}; };
match farmer_service.get_node_by_id(&user_email, &node_id) { match resource_provider_service.get_node_by_id(&user_email, &node_id) {
Some(mut node) => { Some(mut node) => {
// MARKETPLACE SLA FIX: Override grid data with marketplace SLA values when available // MARKETPLACE SLA FIX: Override grid data with marketplace SLA values when available
@@ -1235,7 +1235,7 @@ impl DashboardController {
})).build()); })).build());
} }
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -1244,7 +1244,7 @@ impl DashboardController {
} }
}; };
let stats = farmer_service.get_farmer_statistics(&user_email); let stats = resource_provider_service.get_resource_provider_statistics(&user_email);
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
"success": true, "success": true,
@@ -1262,7 +1262,7 @@ impl DashboardController {
} }
/// API endpoint to update node configuration /// API endpoint to update node configuration
pub async fn update_node_comprehensive(session: Session, path: web::Path<String>, form: web::Json<crate::services::farmer::NodeUpdateData>) -> Result<impl Responder> { pub async fn update_node_comprehensive(session: Session, path: web::Path<String>, form: web::Json<crate::services::resource_provider::NodeUpdateData>) -> Result<impl Responder> {
let user_email = session.get::<String>("user_email") let user_email = session.get::<String>("user_email")
.unwrap_or_default() .unwrap_or_default()
.unwrap_or_default(); .unwrap_or_default();
@@ -1275,7 +1275,7 @@ impl DashboardController {
let node_id = path.into_inner(); let node_id = path.into_inner();
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -1284,7 +1284,7 @@ impl DashboardController {
} }
}; };
match farmer_service.update_node(&user_email, &node_id, form.into_inner()) { match resource_provider_service.update_node(&user_email, &node_id, form.into_inner()) {
Ok(()) => { Ok(()) => {
// Add activity record // Add activity record
@@ -1324,7 +1324,7 @@ impl DashboardController {
})).build()); })).build());
} }
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -1338,7 +1338,7 @@ impl DashboardController {
let mut customized_formats = Vec::new(); let mut customized_formats = Vec::new();
for format_id in default_format_ids { for format_id in default_format_ids {
if let Some(format) = farmer_service.get_default_slice_format_with_customizations(&user_email, format_id) { if let Some(format) = resource_provider_service.get_default_slice_format_with_customizations(&user_email, format_id) {
customized_formats.push(format); customized_formats.push(format);
} }
} }
@@ -1358,7 +1358,7 @@ impl DashboardController {
})).build()); })).build());
} }
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -1367,7 +1367,7 @@ impl DashboardController {
} }
}; };
let groups = farmer_service.get_node_groups(&user_email); let groups = resource_provider_service.get_node_groups(&user_email);
Ok(ResponseBuilder::ok().json(groups).build()) Ok(ResponseBuilder::ok().json(groups).build())
} }
@@ -1383,7 +1383,7 @@ impl DashboardController {
})).build()); })).build());
} }
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -1402,7 +1402,7 @@ impl DashboardController {
.and_then(|v| v.as_str()) .and_then(|v| v.as_str())
.map(|s| s.to_string()); .map(|s| s.to_string());
match farmer_service.create_custom_node_group(&user_email, name, description, None) { match resource_provider_service.create_custom_node_group(&user_email, name, description, None) {
Ok(group) => { Ok(group) => {
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
"success": true, "success": true,
@@ -1431,7 +1431,7 @@ impl DashboardController {
})).build()); })).build());
} }
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -1449,10 +1449,10 @@ impl DashboardController {
.and_then(|v| v.as_str()) .and_then(|v| v.as_str())
.map(|s| s.to_string()); .map(|s| s.to_string());
match farmer_service.update_node_group_assignment(&user_email, node_id, group_id) { match resource_provider_service.update_node_group_assignment(&user_email, node_id, group_id) {
Ok(group_name) => { Ok(group_name) => {
// FARMER FIX: Repair consistency after group assignment change // RESOURCE_PROVIDER FIX: Repair consistency after group assignment change
if let Err(e) = farmer_service.repair_node_group_consistency(&user_email) { if let Err(e) = resource_provider_service.repair_node_group_consistency(&user_email) {
} }
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
"success": true, "success": true,
@@ -1482,7 +1482,7 @@ impl DashboardController {
})).build()); })).build());
} }
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -1493,7 +1493,7 @@ impl DashboardController {
let group_id = path.into_inner(); let group_id = path.into_inner();
match farmer_service.delete_custom_node_group(&user_email, &group_id) { match resource_provider_service.delete_custom_node_group(&user_email, &group_id) {
Ok(()) => { Ok(()) => {
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
"success": true, "success": true,
@@ -1523,7 +1523,7 @@ impl DashboardController {
let format_id = path.into_inner(); let format_id = path.into_inner();
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -1532,7 +1532,7 @@ impl DashboardController {
} }
}; };
match farmer_service.get_default_slice_format_with_customizations(&user_email, &format_id) { match resource_provider_service.get_default_slice_format_with_customizations(&user_email, &format_id) {
Some(format) => { Some(format) => {
Ok(ResponseBuilder::ok().json(format).build()) Ok(ResponseBuilder::ok().json(format).build())
} }
@@ -1558,7 +1558,7 @@ impl DashboardController {
let format_id = path.into_inner(); let format_id = path.into_inner();
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -1576,7 +1576,7 @@ impl DashboardController {
let bandwidth_mbps = form.get("bandwidth_mbps").and_then(|v| v.as_i64()).unwrap_or(100) as i32; let bandwidth_mbps = form.get("bandwidth_mbps").and_then(|v| v.as_i64()).unwrap_or(100) as i32;
let price_per_hour = form.get("price_per_hour").and_then(|v| v.as_f64()).map(rust_decimal::Decimal::from_f64_retain).flatten().unwrap_or(rust_decimal::Decimal::from(10)); let price_per_hour = form.get("price_per_hour").and_then(|v| v.as_f64()).map(rust_decimal::Decimal::from_f64_retain).flatten().unwrap_or(rust_decimal::Decimal::from(10));
let customization = crate::services::farmer::DefaultSliceFormat { let customization = crate::services::resource_provider::DefaultSliceFormat {
id: format_id.clone(), id: format_id.clone(),
name, name,
cpu_cores, cpu_cores,
@@ -1587,7 +1587,7 @@ impl DashboardController {
price_per_hour, price_per_hour,
}; };
match farmer_service.save_default_slice_customization(&user_email, &format_id, customization) { match resource_provider_service.save_default_slice_customization(&user_email, &format_id, customization) {
Ok(_) => { Ok(_) => {
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
"success": true, "success": true,
@@ -1630,9 +1630,9 @@ impl DashboardController {
.map(|p| rust_decimal::Decimal::from_f64_retain(p).unwrap_or(rust_decimal::Decimal::new(50, 2))) .map(|p| rust_decimal::Decimal::from_f64_retain(p).unwrap_or(rust_decimal::Decimal::new(50, 2)))
.unwrap_or(rust_decimal::Decimal::new(50, 2)); // Fallback to 0.50 TFC/hour only if no price provided .unwrap_or(rust_decimal::Decimal::new(50, 2)); // Fallback to 0.50 TFC/hour only if no price provided
// Load user data to get farmer name // Load user data to get resource_provider name
let user = Self::load_user_with_persistent_data(&session); let user = Self::load_user_with_persistent_data(&session);
let farmer_name = user.as_ref().map(|u| u.name.clone()).unwrap_or_else(|| "Unknown Farmer".to_string()); let resource_provider_name = user.as_ref().map(|u| u.name.clone()).unwrap_or_else(|| "Unknown ResourceProvider".to_string());
// Create slice configuration with pricing // Create slice configuration with pricing
let slice_pricing = crate::models::product::SlicePricing::from_hourly( let slice_pricing = crate::models::product::SlicePricing::from_hourly(
@@ -1657,7 +1657,7 @@ impl DashboardController {
// Create slice product // Create slice product
let slice_product = crate::models::product::Product::create_slice_product( let slice_product = crate::models::product::Product::create_slice_product(
user_email.clone(), user_email.clone(),
farmer_name, resource_provider_name,
name, name,
slice_config, slice_config,
price_per_hour, price_per_hour,
@@ -2225,18 +2225,18 @@ impl DashboardController {
} }
}; };
// Initialize farmer service to check for existing nodes // Initialize resource_provider service to check for existing nodes
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
"error": "Failed to initialize farmer service" "error": "Failed to initialize resource_provider service"
})).build()); })).build());
} }
}; };
// Get existing nodes to check for duplicates // Get existing nodes to check for duplicates
let existing_nodes = farmer_service.get_farmer_nodes(&user_email); let existing_nodes = resource_provider_service.get_resource_provider_nodes(&user_email);
// Validate each node and fetch data // Validate each node and fetch data
let mut validated_nodes = Vec::new(); let mut validated_nodes = Vec::new();
@@ -2502,12 +2502,12 @@ impl DashboardController {
let slice_format = form.get("slice_format").and_then(|v| v.as_str()).map(|s| s.to_string()); let slice_format = form.get("slice_format").and_then(|v| v.as_str()).map(|s| s.to_string());
let slice_price = form.get("slice_price").and_then(|v| v.as_f64()).map(|p| Decimal::from_f64_retain(p).unwrap_or_default()); let slice_price = form.get("slice_price").and_then(|v| v.as_f64()).map(|p| Decimal::from_f64_retain(p).unwrap_or_default());
// Initialize farmer service // Initialize resource_provider service
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
"error": "Failed to initialize farmer service" "error": "Failed to initialize resource_provider service"
})).build()); })).build());
} }
}; };
@@ -2515,7 +2515,7 @@ impl DashboardController {
// Add nodes with comprehensive configuration // Add nodes with comprehensive configuration
log::info!( log::info!(
target: "api.dashboard", target: "api.dashboard",
"add_grid_nodes:invoke_farmer_service req_id={} email={} node_count={} slice_enabled={} full_node_enabled={} pricing_mode={}", "add_grid_nodes:invoke_resource_provider_service req_id={} email={} node_count={} slice_enabled={} full_node_enabled={} pricing_mode={}",
req_id, req_id,
user_email, user_email,
node_ids.len(), node_ids.len(),
@@ -2556,19 +2556,19 @@ impl DashboardController {
// For multi-node scenarios, apply pricing configuration based on user choice // For multi-node scenarios, apply pricing configuration based on user choice
if node_ids.len() > 1 && pricing_mode == "same_for_all" && rental_options.is_some() { if node_ids.len() > 1 && pricing_mode == "same_for_all" && rental_options.is_some() {
} else if node_ids.len() > 1 && pricing_mode == "individual" && individual_node_pricing.is_some() { } else if node_ids.len() > 1 && pricing_mode == "individual" && individual_node_pricing.is_some() {
// Individual pricing will be handled in the farmer service // Individual pricing will be handled in the resource_provider service
} }
// Choose the appropriate method based on pricing mode // Choose the appropriate method based on pricing mode
if pricing_mode == "individual" && individual_node_pricing.is_some() { if pricing_mode == "individual" && individual_node_pricing.is_some() {
farmer_service.add_multiple_grid_nodes_with_individual_pricing( resource_provider_service.add_multiple_grid_nodes_with_individual_pricing(
&user_email, &user_email,
node_ids.clone(), node_ids.clone(),
slice_formats, slice_formats,
individual_node_pricing.unwrap() individual_node_pricing.unwrap()
).await ).await
} else { } else {
farmer_service.add_multiple_grid_nodes_with_comprehensive_config( resource_provider_service.add_multiple_grid_nodes_with_comprehensive_config(
&user_email, &user_email,
node_ids.clone(), node_ids.clone(),
slice_formats, slice_formats,
@@ -2576,7 +2576,7 @@ impl DashboardController {
).await ).await
} }
} else { } else {
farmer_service.add_multiple_grid_nodes(&user_email, node_ids.clone()).await resource_provider_service.add_multiple_grid_nodes(&user_email, node_ids.clone()).await
}; };
match add_result { match add_result {
@@ -2594,7 +2594,7 @@ impl DashboardController {
// If node_group_id is provided, assign nodes to existing group // If node_group_id is provided, assign nodes to existing group
if let Some(group_id) = node_group_id { if let Some(group_id) = node_group_id {
for node in &added_nodes { for node in &added_nodes {
if let Err(e) = farmer_service.assign_node_to_group(&user_email, &node.id, Some(group_id.clone())) { if let Err(e) = resource_provider_service.assign_node_to_group(&user_email, &node.id, Some(group_id.clone())) {
} else { } else {
} }
} }
@@ -2606,7 +2606,7 @@ impl DashboardController {
group_data.get("description").and_then(|v| v.as_str()) group_data.get("description").and_then(|v| v.as_str())
) { ) {
// Create node group // Create node group
match farmer_service.create_custom_node_group( match resource_provider_service.create_custom_node_group(
&user_email, &user_email,
group_name.to_string(), group_name.to_string(),
Some(group_description.to_string()), Some(group_description.to_string()),
@@ -2626,7 +2626,7 @@ impl DashboardController {
// Add nodes to group // Add nodes to group
for node in &added_nodes { for node in &added_nodes {
if let Err(e) = farmer_service.assign_node_to_group(&user_email, &node.id, Some(group.id.clone())) { if let Err(e) = resource_provider_service.assign_node_to_group(&user_email, &node.id, Some(group.id.clone())) {
} }
} }
} }
@@ -2663,7 +2663,7 @@ impl DashboardController {
} }
}; };
if let Err(e) = farmer_service.stake_on_node(&user_email, &node.id, staking_options) { if let Err(e) = resource_provider_service.stake_on_node(&user_email, &node.id, staking_options) {
} else { } else {
} }
} }
@@ -2691,7 +2691,7 @@ impl DashboardController {
}; };
for node in &added_nodes { for node in &added_nodes {
if let Err(e) = farmer_service.stake_on_node(&user_email, &node.id, staking_options.clone()) { if let Err(e) = resource_provider_service.stake_on_node(&user_email, &node.id, staking_options.clone()) {
} else { } else {
} }
} }
@@ -2752,11 +2752,11 @@ impl DashboardController {
let slice_format = form.get("slice_format").and_then(|v| v.as_str()).map(|s| s.to_string()); let slice_format = form.get("slice_format").and_then(|v| v.as_str()).map(|s| s.to_string());
let slice_price = form.get("slice_price").and_then(|v| v.as_f64()).map(|p| Decimal::from_f64_retain(p).unwrap_or_default()); let slice_price = form.get("slice_price").and_then(|v| v.as_f64()).map(|p| Decimal::from_f64_retain(p).unwrap_or_default());
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(_e) => { Err(_e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
"error": "Failed to initialize farmer service" "error": "Failed to initialize resource_provider service"
})).build()); })).build());
} }
}; };
@@ -2774,7 +2774,7 @@ impl DashboardController {
resource_optimization: crate::models::user::ResourceOptimization::default(), resource_optimization: crate::models::user::ResourceOptimization::default(),
}; };
match farmer_service.create_custom_node_group( match resource_provider_service.create_custom_node_group(
&user_email, &user_email,
name.to_string(), name.to_string(),
description, description,
@@ -2810,7 +2810,7 @@ impl DashboardController {
})).build()), })).build()),
}; };
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ Err(e) => return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
"success": false, "success": false,
@@ -2818,15 +2818,15 @@ impl DashboardController {
})).build()), })).build()),
}; };
// FARMER FIX: Repair node-group data consistency before getting statistics // RESOURCE_PROVIDER FIX: Repair node-group data consistency before getting statistics
if let Err(e) = farmer_service.repair_node_group_consistency(&user_email) { if let Err(e) = resource_provider_service.repair_node_group_consistency(&user_email) {
} }
let groups = farmer_service.get_node_groups(&user_email); let groups = resource_provider_service.get_node_groups(&user_email);
let mut groups_with_stats = Vec::new(); let mut groups_with_stats = Vec::new();
for group in groups { for group in groups {
match farmer_service.get_group_statistics(&user_email, &group.id) { match resource_provider_service.get_group_statistics(&user_email, &group.id) {
Ok(stats) => { Ok(stats) => {
groups_with_stats.push(serde_json::json!({ groups_with_stats.push(serde_json::json!({
"group": group, "group": group,
@@ -5387,7 +5387,7 @@ impl DashboardController {
}; };
// Check if node exists and get its details first // Check if node exists and get its details first
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -5398,7 +5398,7 @@ impl DashboardController {
}; };
// Verify node exists and belongs to user // Verify node exists and belongs to user
let _node = match farmer_service.get_node_by_id(&user_email, &node_id) { let _node = match resource_provider_service.get_node_by_id(&user_email, &node_id) {
Some(node) => node, Some(node) => node,
None => { None => {
return Ok(ResponseBuilder::not_found().json(serde_json::json!({ return Ok(ResponseBuilder::not_found().json(serde_json::json!({
@@ -5457,7 +5457,7 @@ impl DashboardController {
} }
}; };
let _farmer_service = match crate::services::farmer::FarmerService::builder().build() { let _resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -5927,7 +5927,7 @@ impl DashboardController {
} }
}; };
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -5970,7 +5970,7 @@ impl DashboardController {
}; };
// Stake on node // Stake on node
match farmer_service.stake_on_node(&user_email, &node_id, staking_options) { match resource_provider_service.stake_on_node(&user_email, &node_id, staking_options) {
Ok(()) => { Ok(()) => {
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
"success": true, "success": true,
@@ -6010,7 +6010,7 @@ impl DashboardController {
} }
}; };
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -6030,7 +6030,7 @@ impl DashboardController {
match action { match action {
"unstake" => { "unstake" => {
// Unstake from node // Unstake from node
match farmer_service.unstake_from_node(&user_email, &node_id) { match resource_provider_service.unstake_from_node(&user_email, &node_id) {
Ok(returned_amount) => { Ok(returned_amount) => {
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
"success": true, "success": true,
@@ -6078,7 +6078,7 @@ impl DashboardController {
}; };
// Update node staking // Update node staking
match farmer_service.update_node_staking(&user_email, &node_id, staking_options) { match resource_provider_service.update_node_staking(&user_email, &node_id, staking_options) {
Ok(()) => { Ok(()) => {
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
"success": true, "success": true,
@@ -6120,7 +6120,7 @@ impl DashboardController {
} }
}; };
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -6130,7 +6130,7 @@ impl DashboardController {
} }
}; };
let statistics = farmer_service.get_staking_statistics(&user_email); let statistics = resource_provider_service.get_staking_statistics(&user_email);
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
"success": false, "success": false,
@@ -6293,7 +6293,7 @@ impl DashboardController {
.build()) .build())
} }
/// Refresh slice calculations for farmer /// Refresh slice calculations for resource_provider
pub async fn refresh_slice_calculations(session: Session) -> Result<impl Responder> { pub async fn refresh_slice_calculations(session: Session) -> Result<impl Responder> {
let user_email = match session.get::<String>("user_email") { let user_email = match session.get::<String>("user_email") {
Ok(Some(email)) => email, Ok(Some(email)) => email,
@@ -6303,7 +6303,7 @@ impl DashboardController {
})).build()) })).build())
}; };
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -6313,7 +6313,7 @@ impl DashboardController {
} }
}; };
match farmer_service.refresh_all_slice_calculations(&user_email) { match resource_provider_service.refresh_all_slice_calculations(&user_email) {
Ok(_) => { Ok(_) => {
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
"success": false, "success": false,
@@ -6329,7 +6329,7 @@ impl DashboardController {
} }
} }
/// Sync farmer nodes with ThreeFold Grid /// Sync resource_provider nodes with ThreeFold Grid
pub async fn sync_with_grid(session: Session) -> Result<impl Responder> { pub async fn sync_with_grid(session: Session) -> Result<impl Responder> {
// Check authentication // Check authentication
if let Err(response) = Self::check_authentication(&session) { if let Err(response) = Self::check_authentication(&session) {
@@ -6463,7 +6463,7 @@ impl DashboardController {
let node_id = path.into_inner(); let node_id = path.into_inner();
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -6473,7 +6473,7 @@ impl DashboardController {
} }
}; };
match farmer_service.get_node_slices(&user_email, node_id) { match resource_provider_service.get_node_slices(&user_email, node_id) {
Ok(slices) => { Ok(slices) => {
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
"success": false, "success": false,
@@ -6525,7 +6525,7 @@ impl DashboardController {
} }
// Initialize services // Initialize services
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -6550,7 +6550,7 @@ impl DashboardController {
let mut errors = Vec::new(); let mut errors = Vec::new();
for node_id in &node_ids { for node_id in &node_ids {
match farmer_service.fetch_and_validate_grid_node(*node_id).await { match resource_provider_service.fetch_and_validate_grid_node(*node_id).await {
Ok(node_data) => { Ok(node_data) => {
// Calculate automatic slices // Calculate automatic slices
let total_base_slices = slice_calculator.calculate_max_base_slices(&node_data.capacity); let total_base_slices = slice_calculator.calculate_max_base_slices(&node_data.capacity);
@@ -6709,8 +6709,8 @@ impl DashboardController {
})).build()); })).build());
} }
// Initialize farmer service // Initialize resource_provider service
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -6722,7 +6722,7 @@ impl DashboardController {
// Add nodes with automatic slice management // Add nodes with automatic slice management
match farmer_service.add_multiple_grid_nodes_with_automatic_slices( match resource_provider_service.add_multiple_grid_nodes_with_automatic_slices(
&user_email, &user_email,
node_ids.clone(), node_ids.clone(),
base_slice_price, base_slice_price,
@@ -6759,7 +6759,7 @@ impl DashboardController {
} }
} }
/// API endpoint to refresh slice calculations for all farmer nodes /// API endpoint to refresh slice calculations for all resource_provider nodes
pub async fn refresh_slice_calculations_api(session: Session) -> Result<impl Responder> { pub async fn refresh_slice_calculations_api(session: Session) -> Result<impl Responder> {
let user_email = session.get::<String>("user_email") let user_email = session.get::<String>("user_email")
@@ -6773,8 +6773,8 @@ impl DashboardController {
})).build()); })).build());
} }
// Initialize farmer service // Initialize resource_provider service
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -6785,7 +6785,7 @@ impl DashboardController {
}; };
// Refresh slice calculations for all nodes // Refresh slice calculations for all nodes
match farmer_service.refresh_all_slice_calculations_async(&user_email).await { match resource_provider_service.refresh_all_slice_calculations_async(&user_email).await {
Ok(updated_nodes) => { Ok(updated_nodes) => {
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
@@ -6817,8 +6817,8 @@ impl DashboardController {
})).build()); })).build());
} }
// Initialize farmer service // Initialize resource_provider service
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -6829,7 +6829,7 @@ impl DashboardController {
}; };
// Sync all nodes with grid // Sync all nodes with grid
match farmer_service.sync_all_nodes_with_grid_async(&user_email).await { match resource_provider_service.sync_all_nodes_with_grid_async(&user_email).await {
Ok(synced_nodes) => { Ok(synced_nodes) => {
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
@@ -6863,8 +6863,8 @@ impl DashboardController {
let node_id = path.into_inner(); let node_id = path.into_inner();
// Initialize farmer service // Initialize resource_provider service
let farmer_service = match crate::services::farmer::FarmerService::builder().build() { let resource_provider_service = match crate::services::resource_provider::ResourceProviderService::builder().build() {
Ok(service) => service, Ok(service) => service,
Err(e) => { Err(e) => {
return Ok(ResponseBuilder::internal_error().json(serde_json::json!({ return Ok(ResponseBuilder::internal_error().json(serde_json::json!({
@@ -6875,7 +6875,7 @@ impl DashboardController {
}; };
// Get node slice details // Get node slice details
match farmer_service.get_node_slice_details(&user_email, &node_id) { match resource_provider_service.get_node_slice_details(&user_email, &node_id) {
Ok(slice_details) => { Ok(slice_details) => {
Ok(ResponseBuilder::ok().json(serde_json::json!({ Ok(ResponseBuilder::ok().json(serde_json::json!({
"success": false, "success": false,

View File

@@ -13,7 +13,7 @@ use chrono::Utc;
/// Form data for slice rental requests /// Form data for slice rental requests
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct SliceRentalForm { pub struct SliceRentalForm {
pub farmer_email: String, pub resource_provider_email: String,
pub node_id: String, pub node_id: String,
pub combination_id: String, pub combination_id: String,
pub quantity: u32, pub quantity: u32,
@@ -377,7 +377,7 @@ impl MarketplaceController {
render_template(&tmpl, "marketplace/compute_resources.html", &ctx) render_template(&tmpl, "marketplace/compute_resources.html", &ctx)
} }
/// Renders the Mycelium Nodes marketplace page with REAL farmer nodes from database /// Renders the Mycelium Nodes marketplace page with REAL resource_provider nodes from database
pub async fn mycelium_nodes(tmpl: web::Data<Tera>, session: Session, query: web::Query<std::collections::HashMap<String, String>>) -> Result<impl Responder> { pub async fn mycelium_nodes(tmpl: web::Data<Tera>, session: Session, query: web::Query<std::collections::HashMap<String, String>>) -> Result<impl Responder> {
// Build services using established builder pattern // Build services using established builder pattern
let currency_service = CurrencyService::builder() let currency_service = CurrencyService::builder()
@@ -411,7 +411,7 @@ impl MarketplaceController {
.unwrap_or(0); .unwrap_or(0);
let page_size = 12; let page_size = 12;
// Get all real farmer nodes as marketplace products // Get all real resource_provider nodes as marketplace products
let all_node_products = node_marketplace_service.get_all_marketplace_nodes(); let all_node_products = node_marketplace_service.get_all_marketplace_nodes();
// Clone query for reuse // Clone query for reuse
@@ -933,7 +933,7 @@ impl MarketplaceController {
pub async fn show_slice_rental_form( pub async fn show_slice_rental_form(
tmpl: web::Data<Tera>, tmpl: web::Data<Tera>,
session: Session, session: Session,
path: web::Path<(String, String, String)> // farmer_email, node_id, combination_id path: web::Path<(String, String, String)> // resource_provider_email, node_id, combination_id
) -> Result<impl Responder> { ) -> Result<impl Responder> {
let mut ctx = crate::models::builders::ContextBuilder::new() let mut ctx = crate::models::builders::ContextBuilder::new()
.active_page("marketplace") .active_page("marketplace")
@@ -951,7 +951,7 @@ impl MarketplaceController {
} }
} }
let (farmer_email, node_id, combination_id) = path.into_inner(); let (resource_provider_email, node_id, combination_id) = path.into_inner();
// Get slice details for the form // Get slice details for the form
let node_marketplace_service = NodeMarketplaceService::builder() let node_marketplace_service = NodeMarketplaceService::builder()
@@ -963,12 +963,12 @@ impl MarketplaceController {
// Find the specific slice combination by checking product attributes // Find the specific slice combination by checking product attributes
if let Some(slice_product) = slice_combinations.iter().find(|p| { if let Some(slice_product) = slice_combinations.iter().find(|p| {
// Check if this product matches the requested slice // Check if this product matches the requested slice
if let (Some(farmer_attr), Some(node_attr), Some(combo_attr)) = ( if let (Some(resource_provider_attr), Some(node_attr), Some(combo_attr)) = (
p.attributes.get("farmer_email"), p.attributes.get("resource_provider_email"),
p.attributes.get("node_id"), p.attributes.get("node_id"),
p.attributes.get("combination_id") p.attributes.get("combination_id")
) { ) {
farmer_attr.value.as_str() == Some(&farmer_email) && resource_provider_attr.value.as_str() == Some(&resource_provider_email) &&
node_attr.value.as_str() == Some(&node_id) && node_attr.value.as_str() == Some(&node_id) &&
combo_attr.value.as_str() == Some(&combination_id) combo_attr.value.as_str() == Some(&combination_id)
} else { } else {
@@ -998,11 +998,11 @@ impl MarketplaceController {
slice_info.insert("price_per_hour", serde_json::Value::String(slice_product.base_price.to_string())); slice_info.insert("price_per_hour", serde_json::Value::String(slice_product.base_price.to_string()));
slice_info.insert("node_id", serde_json::Value::String(node_id.clone())); slice_info.insert("node_id", serde_json::Value::String(node_id.clone()));
slice_info.insert("farmer_email", serde_json::Value::String(farmer_email.clone())); slice_info.insert("resource_provider_email", serde_json::Value::String(resource_provider_email.clone()));
slice_info.insert("combination_id", serde_json::Value::String(combination_id.clone())); slice_info.insert("combination_id", serde_json::Value::String(combination_id.clone()));
ctx.insert("slice", &slice_info); ctx.insert("slice", &slice_info);
ctx.insert("farmer_email", &farmer_email); ctx.insert("resource_provider_email", &resource_provider_email);
ctx.insert("node_id", &node_id); ctx.insert("node_id", &node_id);
ctx.insert("combination_id", &combination_id); ctx.insert("combination_id", &combination_id);
} }
@@ -1109,7 +1109,7 @@ impl MarketplaceController {
// Attempt to rent the slice with deployment options // Attempt to rent the slice with deployment options
match slice_rental_service.rent_slice_combination_with_deployment( match slice_rental_service.rent_slice_combination_with_deployment(
&user_email, &user_email,
&form.farmer_email, &form.resource_provider_email,
&form.node_id, &form.node_id,
&form.combination_id, &form.combination_id,
form.quantity, form.quantity,
@@ -1134,7 +1134,7 @@ impl MarketplaceController {
meta.insert("deployment_type".to_string(), serde_json::Value::String(form.deployment_type.clone())); meta.insert("deployment_type".to_string(), serde_json::Value::String(form.deployment_type.clone()));
meta.insert("deployment_name".to_string(), serde_json::Value::String(deployment_name.clone())); meta.insert("deployment_name".to_string(), serde_json::Value::String(deployment_name.clone()));
meta.insert("quantity".to_string(), serde_json::Value::Number(serde_json::Number::from(form.quantity))); meta.insert("quantity".to_string(), serde_json::Value::Number(serde_json::Number::from(form.quantity)));
meta.insert("farmer_email".to_string(), serde_json::Value::String(form.farmer_email.clone())); meta.insert("resource_provider_email".to_string(), serde_json::Value::String(form.resource_provider_email.clone()));
if form.deployment_type == "kubernetes" { if form.deployment_type == "kubernetes" {
meta.insert("k8s_masters".to_string(), serde_json::Value::Number(serde_json::Number::from(form.k8s_masters.unwrap_or(1)))); meta.insert("k8s_masters".to_string(), serde_json::Value::Number(serde_json::Number::from(form.k8s_masters.unwrap_or(1))));
meta.insert("k8s_workers".to_string(), serde_json::Value::Number(serde_json::Number::from(form.k8s_workers.unwrap_or(1)))); meta.insert("k8s_workers".to_string(), serde_json::Value::Number(serde_json::Number::from(form.k8s_workers.unwrap_or(1))));
@@ -1206,7 +1206,7 @@ impl MarketplaceController {
// Attempt to rent the slice with deployment options // Attempt to rent the slice with deployment options
match slice_rental_service.rent_slice_combination_with_deployment( match slice_rental_service.rent_slice_combination_with_deployment(
&user_email, &user_email,
&form.farmer_email, &form.resource_provider_email,
&form.node_id, &form.node_id,
&form.combination_id, &form.combination_id,
form.quantity, form.quantity,
@@ -1231,7 +1231,7 @@ impl MarketplaceController {
meta.insert("deployment_type".to_string(), serde_json::Value::String(form.deployment_type.clone())); meta.insert("deployment_type".to_string(), serde_json::Value::String(form.deployment_type.clone()));
meta.insert("deployment_name".to_string(), serde_json::Value::String(form.deployment_name.clone())); meta.insert("deployment_name".to_string(), serde_json::Value::String(form.deployment_name.clone()));
meta.insert("quantity".to_string(), serde_json::Value::Number(serde_json::Number::from(form.quantity))); meta.insert("quantity".to_string(), serde_json::Value::Number(serde_json::Number::from(form.quantity)));
meta.insert("farmer_email".to_string(), serde_json::Value::String(form.farmer_email.clone())); meta.insert("resource_provider_email".to_string(), serde_json::Value::String(form.resource_provider_email.clone()));
serde_json::Value::Object(meta.into_iter().collect()) serde_json::Value::Object(meta.into_iter().collect())
}), }),
category: "slice_rental".to_string(), category: "slice_rental".to_string(),
@@ -1270,7 +1270,7 @@ impl MarketplaceController {
/// Request structure for slice rental with deployment options /// Request structure for slice rental with deployment options
#[derive(serde::Deserialize)] #[derive(serde::Deserialize)]
pub struct SliceRentalRequest { pub struct SliceRentalRequest {
pub farmer_email: String, pub resource_provider_email: String,
pub node_id: String, pub node_id: String,
pub combination_id: String, pub combination_id: String,
pub quantity: u32, pub quantity: u32,
@@ -1503,7 +1503,7 @@ fn reconstruct_service_from_json(service_value: &serde_json::Value) -> Result<cr
// Attempt to rent the slice combination // Attempt to rent the slice combination
match slice_rental_service.rent_slice_combination( match slice_rental_service.rent_slice_combination(
&user_email, &user_email,
&form.farmer_email, &form.resource_provider_email,
&form.node_id, &form.node_id,
&form.combination_id, &form.combination_id,
form.quantity, form.quantity,
@@ -1602,7 +1602,7 @@ fn reconstruct_service_from_json(service_value: &serde_json::Value) -> Result<cr
// Create SliceAssignmentRequest from the data // Create SliceAssignmentRequest from the data
let assignment_request_obj = SliceAssignmentRequest { let assignment_request_obj = SliceAssignmentRequest {
user_email: user_email.clone(), user_email: user_email.clone(),
farmer_email: assignment_request.get("farmer_email") resource_provider_email: assignment_request.get("resource_provider_email")
.and_then(|v| v.as_str()) .and_then(|v| v.as_str())
.unwrap_or("unknown@example.com") .unwrap_or("unknown@example.com")
.to_string(), .to_string(),

View File

@@ -88,8 +88,8 @@ impl PublicController {
render_template(&tmpl, "legal/terms.html", &ctx) render_template(&tmpl, "legal/terms.html", &ctx)
} }
/// Renders the farmers terms page /// Renders the resource providers terms page
pub async fn terms_farmers(tmpl: web::Data<Tera>, session: Session) -> Result<impl Responder> { pub async fn terms_resource_providers(tmpl: web::Data<Tera>, session: Session) -> Result<impl Responder> {
let mut ctx = crate::models::builders::ContextBuilder::new() let mut ctx = crate::models::builders::ContextBuilder::new()
.build(); .build();
ctx.insert("active_page", "terms"); ctx.insert("active_page", "terms");
@@ -105,7 +105,7 @@ impl PublicController {
} }
} }
render_template(&tmpl, "legal/terms-farmers.html", &ctx) render_template(&tmpl, "legal/terms-resource_providers.html", &ctx)
} }
/// Renders the service providers terms page /// Renders the service providers terms page

View File

@@ -173,7 +173,7 @@ impl RentalController {
rental_id: rental_id.clone(), rental_id: rental_id.clone(),
slice_combination_id: format!("combo-{}", rental_id), slice_combination_id: format!("combo-{}", rental_id),
node_id: "node-placeholder".to_string(), // TODO: Get from product node_id: "node-placeholder".to_string(), // TODO: Get from product
farmer_email: "farmer@example.com".to_string(), // TODO: Get from product resource_provider_email: "resource_provider@example.com".to_string(), // TODO: Get from product
slice_allocation: crate::services::slice_calculator::SliceAllocation { slice_allocation: crate::services::slice_calculator::SliceAllocation {
allocation_id: format!("alloc-{}", rental_id), allocation_id: format!("alloc-{}", rental_id),
slice_combination_id: format!("combo-{}", rental_id), slice_combination_id: format!("combo-{}", rental_id),

View File

@@ -33,5 +33,5 @@ pub mod utils;
// Re-export commonly used types // Re-export commonly used types
pub use models::user::{User, NodeStakingOptions, FarmNode}; pub use models::user::{User, NodeStakingOptions, FarmNode};
pub use services::farmer::FarmerService; pub use services::resource_provider::ResourceProviderService;
pub use services::user_persistence::UserPersistence; pub use services::user_persistence::UserPersistence;

View File

@@ -1234,11 +1234,11 @@ impl SessionDataBuilder {
// MockDataBuilder removed - using persistent data only // MockDataBuilder removed - using persistent data only
// ============================================================================= // =============================================================================
// FARMER DATA BUILDER // RESOURCE_PROVIDER DATA BUILDER
// ============================================================================= // =============================================================================
#[derive(Default)] #[derive(Default)]
pub struct FarmerDataBuilder { pub struct ResourceProviderDataBuilder {
total_nodes: Option<i32>, total_nodes: Option<i32>,
online_nodes: Option<i32>, online_nodes: Option<i32>,
total_capacity: Option<crate::models::user::NodeCapacity>, total_capacity: Option<crate::models::user::NodeCapacity>,
@@ -1251,7 +1251,7 @@ pub struct FarmerDataBuilder {
active_slices: Option<i32>, active_slices: Option<i32>,
} }
impl FarmerDataBuilder { impl ResourceProviderDataBuilder {
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
@@ -1373,8 +1373,8 @@ impl FarmerDataBuilder {
self self
} }
pub fn build(self) -> Result<crate::models::user::FarmerData, String> { pub fn build(self) -> Result<crate::models::user::ResourceProviderData, String> {
Ok(crate::models::user::FarmerData { Ok(crate::models::user::ResourceProviderData {
total_nodes: self.total_nodes.unwrap_or(0), total_nodes: self.total_nodes.unwrap_or(0),
online_nodes: self.online_nodes.unwrap_or(0), online_nodes: self.online_nodes.unwrap_or(0),
total_capacity: self.total_capacity.unwrap_or(crate::models::user::NodeCapacity { total_capacity: self.total_capacity.unwrap_or(crate::models::user::NodeCapacity {
@@ -1445,8 +1445,8 @@ impl FarmerDataBuilder {
#[derive(Default)] #[derive(Default)]
pub struct SliceProductBuilder { pub struct SliceProductBuilder {
farmer_id: Option<String>, resource_provider_id: Option<String>,
farmer_name: Option<String>, resource_provider_name: Option<String>,
slice_name: Option<String>, slice_name: Option<String>,
cpu_cores: Option<i32>, cpu_cores: Option<i32>,
memory_gb: Option<i32>, memory_gb: Option<i32>,
@@ -1464,13 +1464,13 @@ impl SliceProductBuilder {
Self::default() Self::default()
} }
pub fn farmer_id(mut self, farmer_id: impl Into<String>) -> Self { pub fn resource_provider_id(mut self, resource_provider_id: impl Into<String>) -> Self {
self.farmer_id = Some(farmer_id.into()); self.resource_provider_id = Some(resource_provider_id.into());
self self
} }
pub fn farmer_name(mut self, farmer_name: impl Into<String>) -> Self { pub fn resource_provider_name(mut self, resource_provider_name: impl Into<String>) -> Self {
self.farmer_name = Some(farmer_name.into()); self.resource_provider_name = Some(resource_provider_name.into());
self self
} }
@@ -1525,8 +1525,8 @@ impl SliceProductBuilder {
} }
pub fn build(self) -> Result<crate::models::product::Product, String> { pub fn build(self) -> Result<crate::models::product::Product, String> {
let farmer_id = self.farmer_id.ok_or("farmer_id is required")?; let resource_provider_id = self.resource_provider_id.ok_or("resource_provider_id is required")?;
let farmer_name = self.farmer_name.ok_or("farmer_name is required")?; let resource_provider_name = self.resource_provider_name.ok_or("resource_provider_name is required")?;
let slice_name = self.slice_name.ok_or("slice_name is required")?; let slice_name = self.slice_name.ok_or("slice_name is required")?;
let cpu_cores = self.cpu_cores.ok_or("cpu_cores is required")?; let cpu_cores = self.cpu_cores.ok_or("cpu_cores is required")?;
let memory_gb = self.memory_gb.ok_or("memory_gb is required")?; let memory_gb = self.memory_gb.ok_or("memory_gb is required")?;
@@ -1552,8 +1552,8 @@ impl SliceProductBuilder {
}; };
Ok(crate::models::product::Product::create_slice_product( Ok(crate::models::product::Product::create_slice_product(
farmer_id, resource_provider_id,
farmer_name, resource_provider_name,
slice_name, slice_name,
slice_config, slice_config,
price_per_hour, price_per_hour,
@@ -2081,7 +2081,7 @@ impl NodeRentalBuilder {
} }
#[derive(Default)] #[derive(Default)]
pub struct FarmerRentalEarningBuilder { pub struct ResourceProviderRentalEarningBuilder {
id: Option<String>, id: Option<String>,
node_id: Option<String>, node_id: Option<String>,
rental_id: Option<String>, rental_id: Option<String>,
@@ -2093,7 +2093,7 @@ pub struct FarmerRentalEarningBuilder {
payment_status: Option<crate::models::user::PaymentStatus>, payment_status: Option<crate::models::user::PaymentStatus>,
} }
impl FarmerRentalEarningBuilder { impl ResourceProviderRentalEarningBuilder {
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
@@ -2143,10 +2143,10 @@ impl FarmerRentalEarningBuilder {
self self
} }
pub fn build(self) -> Result<crate::models::user::FarmerRentalEarning, String> { pub fn build(self) -> Result<crate::models::user::ResourceProviderRentalEarning, String> {
let id = self.id.unwrap_or_else(|| format!("earning_{}", uuid::Uuid::new_v4())); let id = self.id.unwrap_or_else(|| format!("earning_{}", uuid::Uuid::new_v4()));
Ok(crate::models::user::FarmerRentalEarning { Ok(crate::models::user::ResourceProviderRentalEarning {
id, id,
node_id: self.node_id.ok_or("node_id is required")?, node_id: self.node_id.ok_or("node_id is required")?,
rental_id: self.rental_id.ok_or("rental_id is required")?, rental_id: self.rental_id.ok_or("rental_id is required")?,
@@ -2469,8 +2469,8 @@ impl NodeCreationDataBuilder {
self self
} }
pub fn build(self) -> Result<crate::services::farmer::NodeCreationData, String> { pub fn build(self) -> Result<crate::services::resource_provider::NodeCreationData, String> {
Ok(crate::services::farmer::NodeCreationData { Ok(crate::services::resource_provider::NodeCreationData {
name: self.name.ok_or("name is required")?, name: self.name.ok_or("name is required")?,
location: self.location.ok_or("location is required")?, location: self.location.ok_or("location is required")?,
cpu_cores: self.cpu_cores.unwrap_or(4), cpu_cores: self.cpu_cores.unwrap_or(4),

View File

@@ -305,10 +305,10 @@ pub enum SliceType {
} }
impl Product { impl Product {
/// Create a slice product from farmer configuration /// Create a slice product from resource_provider configuration
pub fn create_slice_product( pub fn create_slice_product(
farmer_id: String, resource_provider_id: String,
farmer_name: String, resource_provider_name: String,
slice_name: String, slice_name: String,
slice_config: SliceConfiguration, slice_config: SliceConfiguration,
price_per_hour: Decimal, price_per_hour: Decimal,
@@ -322,8 +322,8 @@ impl Product {
slice_config.cpu_cores, slice_config.memory_gb, slice_config.storage_gb), slice_config.cpu_cores, slice_config.memory_gb, slice_config.storage_gb),
price_per_hour, price_per_hour,
"USD".to_string(), "USD".to_string(),
farmer_id, resource_provider_id,
farmer_name, resource_provider_name,
); );
// Add slice-specific attributes // Add slice-specific attributes
@@ -448,8 +448,8 @@ impl Product {
/// Create a full node product from a FarmNode /// Create a full node product from a FarmNode
pub fn create_full_node_product( pub fn create_full_node_product(
node: &crate::models::user::FarmNode, node: &crate::models::user::FarmNode,
farmer_email: &str, resource_provider_email: &str,
farmer_name: &str, resource_provider_name: &str,
) -> Self { ) -> Self {
let mut product = Product { let mut product = Product {
id: format!("fullnode_{}", node.id), id: format!("fullnode_{}", node.id),
@@ -469,8 +469,8 @@ impl Product {
.unwrap_or_else(|| Decimal::from(200)), // Default price .unwrap_or_else(|| Decimal::from(200)), // Default price
base_currency: "USD".to_string(), base_currency: "USD".to_string(),
attributes: HashMap::new(), attributes: HashMap::new(),
provider_id: farmer_email.to_string(), provider_id: resource_provider_email.to_string(),
provider_name: farmer_name.to_string(), provider_name: resource_provider_name.to_string(),
availability: match node.availability_status { availability: match node.availability_status {
crate::models::user::NodeAvailabilityStatus::Available => ProductAvailability::Available, crate::models::user::NodeAvailabilityStatus::Available => ProductAvailability::Available,
crate::models::user::NodeAvailabilityStatus::PartiallyRented => ProductAvailability::Limited, crate::models::user::NodeAvailabilityStatus::PartiallyRented => ProductAvailability::Limited,

View File

@@ -146,7 +146,7 @@ pub struct RegionDeployments {
pub gateways: i32, pub gateways: i32,
} }
/// Node information for farmer dashboard /// Node information for resource_provider dashboard
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NodeInfo { pub struct NodeInfo {
pub id: String, pub id: String,
@@ -200,14 +200,14 @@ impl std::fmt::Display for NodeStatus {
} }
} }
/// Default maintenance window for farmer settings /// Default maintenance window for resource_provider settings
pub fn default_maintenance_window() -> String { pub fn default_maintenance_window() -> String {
"02:00-04:00 UTC".to_string() "02:00-04:00 UTC".to_string()
} }
/// Farmer configuration settings /// ResourceProvider configuration settings
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FarmerSettings { pub struct ResourceProviderSettings {
pub auto_accept_reserved_slices: bool, pub auto_accept_reserved_slices: bool,
pub maintenance_window: String, // e.g., "02:00-04:00 UTC" pub maintenance_window: String, // e.g., "02:00-04:00 UTC"
pub notification_email: Option<String>, pub notification_email: Option<String>,
@@ -229,7 +229,7 @@ pub struct FarmerSettings {
pub preferred_regions: Vec<String>, pub preferred_regions: Vec<String>,
} }
impl Default for FarmerSettings { impl Default for ResourceProviderSettings {
fn default() -> Self { fn default() -> Self {
Self { Self {
auto_accept_reserved_slices: true, auto_accept_reserved_slices: true,
@@ -324,7 +324,7 @@ impl Default for LiquidityPoolConfig {
} }
} }
impl Default for FarmerData { impl Default for ResourceProviderData {
fn default() -> Self { fn default() -> Self {
Self { Self {
total_nodes: 0, total_nodes: 0,
@@ -761,9 +761,9 @@ pub struct QuickAction {
pub enabled: bool, pub enabled: bool,
} }
/// Farmer-specific data /// ResourceProvider-specific data
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FarmerData { pub struct ResourceProviderData {
pub total_nodes: i32, pub total_nodes: i32,
pub active_nodes: i32, pub active_nodes: i32,
pub total_monthly_earnings_usd: i32, pub total_monthly_earnings_usd: i32,
@@ -1224,7 +1224,7 @@ where
.map_err(serde::de::Error::custom) .map_err(serde::de::Error::custom)
} }
/// Node group for farmer organization /// Node group for resource_provider organization
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NodeGroup { pub struct NodeGroup {
pub id: String, pub id: String,
@@ -1358,7 +1358,7 @@ pub struct NodeCapacity {
pub ram_gb: i32, pub ram_gb: i32,
} }
/// Farmer node information /// ResourceProvider node information
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FarmNode { pub struct FarmNode {
pub id: String, pub id: String,
@@ -1418,7 +1418,7 @@ pub struct FarmNode {
pub health_score: f32, pub health_score: f32,
} }
/// Earnings record for farmer data /// Earnings record for resource_provider data
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EarningsRecord { pub struct EarningsRecord {
pub date: String, pub date: String,
@@ -1428,7 +1428,7 @@ pub struct EarningsRecord {
pub source: String, pub source: String,
} }
/// Group statistics for farmer dashboard /// Group statistics for resource_provider dashboard
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GroupStatistics { pub struct GroupStatistics {
pub group_name: String, pub group_name: String,
@@ -1517,7 +1517,7 @@ pub struct GridNodeData {
/// Additional missing user model types /// Additional missing user model types
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FarmerRentalEarning { pub struct ResourceProviderRentalEarning {
pub date: String, pub date: String,
pub amount: Decimal, pub amount: Decimal,
pub rental_id: String, pub rental_id: String,

View File

@@ -52,7 +52,7 @@ pub fn configure_routes(cfg: &mut web::ServiceConfig) {
.route("/marketplace/services", web::get().to(MarketplaceController::services)) .route("/marketplace/services", web::get().to(MarketplaceController::services))
.route("/marketplace/statistics", web::get().to(MarketplaceController::statistics)) .route("/marketplace/statistics", web::get().to(MarketplaceController::statistics))
// Slice rental routes // Slice rental routes
.route("/marketplace/slice/rent/{farmer_email}/{node_id}/{combination_id}", web::get().to(MarketplaceController::show_slice_rental_form)) .route("/marketplace/slice/rent/{resource_provider_email}/{node_id}/{combination_id}", web::get().to(MarketplaceController::show_slice_rental_form))
.route("/marketplace/slice/rent", web::post().to(MarketplaceController::process_slice_rental)) .route("/marketplace/slice/rent", web::post().to(MarketplaceController::process_slice_rental))
// .route("/marketplace/rent-slice", web::post().to(MarketplaceController::rent_slice)) // Legacy route [DISABLED] // .route("/marketplace/rent-slice", web::post().to(MarketplaceController::rent_slice)) // Legacy route [DISABLED]
// Product routes // Product routes
@@ -107,7 +107,7 @@ pub fn configure_routes(cfg: &mut web::ServiceConfig) {
.route("/dashboard/slice-rentals/{id}/manage", web::post().to(DashboardController::manage_slice_rental_deployment)) .route("/dashboard/slice-rentals/{id}/manage", web::post().to(DashboardController::manage_slice_rental_deployment))
.route("/dashboard/slice-rentals/{id}", web::delete().to(DashboardController::cancel_slice_rental)) .route("/dashboard/slice-rentals/{id}", web::delete().to(DashboardController::cancel_slice_rental))
.route("/dashboard/user/slice-rentals/{id}", web::post().to(DashboardController::manage_slice_rental)) .route("/dashboard/user/slice-rentals/{id}", web::post().to(DashboardController::manage_slice_rental))
.route("/dashboard/farmer-data", web::get().to(DashboardController::farmer_data_api)) .route("/dashboard/resource_provider-data", web::get().to(DashboardController::resource_provider_data_api))
.route("/dashboard/app-provider-data", web::get().to(DashboardController::app_provider_data_api)) .route("/dashboard/app-provider-data", web::get().to(DashboardController::app_provider_data_api))
.route("/dashboard/slice-products", web::get().to(DashboardController::get_slice_products)) .route("/dashboard/slice-products", web::get().to(DashboardController::get_slice_products))
.route("/dashboard/slice-products", web::post().to(DashboardController::create_slice_product)) .route("/dashboard/slice-products", web::post().to(DashboardController::create_slice_product))
@@ -116,19 +116,19 @@ pub fn configure_routes(cfg: &mut web::ServiceConfig) {
.route("/dashboard/slice-details/{id}", web::get().to(DashboardController::get_slice_details)) .route("/dashboard/slice-details/{id}", web::get().to(DashboardController::get_slice_details))
.route("/dashboard/slice-configuration/{id}", web::put().to(DashboardController::update_slice_configuration)) .route("/dashboard/slice-configuration/{id}", web::put().to(DashboardController::update_slice_configuration))
.route("/dashboard/service-provider-data", web::get().to(DashboardController::service_provider_data_api)) .route("/dashboard/service-provider-data", web::get().to(DashboardController::service_provider_data_api))
// Farmer management API routes // Resource provider management API routes
.route("/dashboard/farm-nodes", web::post().to(DashboardController::add_farm_node)) .route("/dashboard/resource_provider-nodes", web::post().to(DashboardController::add_resource_provider_node))
.route("/dashboard/farm-nodes-enhanced", web::post().to(DashboardController::add_farm_node_enhanced)) .route("/dashboard/resource_provider-nodes-enhanced", web::post().to(DashboardController::add_resource_provider_node_enhanced))
.route("/dashboard/farm-nodes/{id}", web::get().to(DashboardController::get_node_details)) .route("/dashboard/resource_provider-nodes/{id}", web::get().to(DashboardController::get_node_details))
.route("/dashboard/farm-nodes/{id}", web::put().to(DashboardController::update_node_comprehensive)) .route("/dashboard/resource_provider-nodes/{id}", web::put().to(DashboardController::update_node_comprehensive))
.route("/dashboard/farm-nodes/{id}/status", web::put().to(DashboardController::update_node_status)) .route("/dashboard/resource_provider-nodes/{id}/status", web::put().to(DashboardController::update_node_status))
// Farmer slice management API routes // Resource provider slice management API routes
.route("/dashboard/farmer/slice-calculations/refresh", web::post().to(DashboardController::refresh_slice_calculations)) .route("/dashboard/resource_provider/slice-calculations/refresh", web::post().to(DashboardController::refresh_slice_calculations))
.route("/dashboard/farmer/grid-sync", web::post().to(DashboardController::sync_with_grid)) .route("/dashboard/resource_provider/grid-sync", web::post().to(DashboardController::sync_with_grid))
.route("/dashboard/farmer/nodes/{id}/slices", web::get().to(DashboardController::get_node_slices)) .route("/dashboard/resource_provider/nodes/{id}/slices", web::get().to(DashboardController::get_node_slices))
.route("/dashboard/farmer/slice-statistics", web::get().to(DashboardController::get_slice_statistics)) .route("/dashboard/resource_provider/slice-statistics", web::get().to(DashboardController::get_slice_statistics))
.route("/dashboard/farm-nodes/{id}", web::delete().to(DashboardController::delete_node)) .route("/dashboard/resource_provider-nodes/{id}", web::delete().to(DashboardController::delete_node))
.route("/dashboard/farm-nodes/{id}/configuration", web::put().to(DashboardController::update_node_configuration)) .route("/dashboard/resource_provider-nodes/{id}/configuration", web::put().to(DashboardController::update_node_configuration))
.route("/dashboard/default-slice-formats", web::get().to(DashboardController::get_default_slice_formats)) .route("/dashboard/default-slice-formats", web::get().to(DashboardController::get_default_slice_formats))
.route("/dashboard/default-slice-details/{id}", web::get().to(DashboardController::get_default_slice_details)) .route("/dashboard/default-slice-details/{id}", web::get().to(DashboardController::get_default_slice_details))
.route("/dashboard/default-slice-customization/{id}", web::put().to(DashboardController::save_default_slice_customization)) .route("/dashboard/default-slice-customization/{id}", web::put().to(DashboardController::save_default_slice_customization))
@@ -148,8 +148,8 @@ pub fn configure_routes(cfg: &mut web::ServiceConfig) {
.route("/dashboard/node-groups/{id}", web::delete().to(DashboardController::delete_custom_node_group)) .route("/dashboard/node-groups/{id}", web::delete().to(DashboardController::delete_custom_node_group))
.route("/dashboard/nodes/assign-group", web::post().to(DashboardController::assign_node_to_group)) .route("/dashboard/nodes/assign-group", web::post().to(DashboardController::assign_node_to_group))
// Node staking API routes // Node staking API routes
.route("/dashboard/farm-nodes/{id}/stake", web::post().to(DashboardController::stake_on_node)) .route("/dashboard/resource_provider-nodes/{id}/stake", web::post().to(DashboardController::stake_on_node))
.route("/dashboard/farm-nodes/{id}/staking", web::put().to(DashboardController::update_node_staking)) .route("/dashboard/resource_provider-nodes/{id}/staking", web::put().to(DashboardController::update_node_staking))
.route("/dashboard/staking/statistics", web::get().to(DashboardController::get_staking_statistics)) .route("/dashboard/staking/statistics", web::get().to(DashboardController::get_staking_statistics))
// Service management API routes // Service management API routes
.route("/dashboard/services", web::get().to(DashboardController::get_user_services)) .route("/dashboard/services", web::get().to(DashboardController::get_user_services))
@@ -260,7 +260,7 @@ pub fn configure_routes(cfg: &mut web::ServiceConfig) {
.wrap(JwtAuth) // Apply authentication middleware to all dashboard routes .wrap(JwtAuth) // Apply authentication middleware to all dashboard routes
.route("", web::get().to(DashboardController::index)) .route("", web::get().to(DashboardController::index))
.route("/user", web::get().to(DashboardController::user_section)) .route("/user", web::get().to(DashboardController::user_section))
.route("/farmer", web::get().to(DashboardController::farmer_section)) .route("/resource_provider", web::get().to(DashboardController::resource_provider_section))
.route("/app-provider", web::get().to(DashboardController::app_provider_section)) .route("/app-provider", web::get().to(DashboardController::app_provider_section))
.route("/service-provider", web::get().to(DashboardController::service_provider_section)) .route("/service-provider", web::get().to(DashboardController::service_provider_section))
@@ -282,7 +282,7 @@ pub fn configure_routes(cfg: &mut web::ServiceConfig) {
// Public information routes (legal, changelog, roadmap) // Public information routes (legal, changelog, roadmap)
.route("/privacy", web::get().to(PublicController::privacy)) .route("/privacy", web::get().to(PublicController::privacy))
.route("/terms", web::get().to(PublicController::terms)) .route("/terms", web::get().to(PublicController::terms))
.route("/terms/farmers", web::get().to(PublicController::terms_farmers)) .route("/terms/resource_providers", web::get().to(PublicController::terms_resource_providers))
.route("/terms/service-providers", web::get().to(PublicController::terms_service_providers)) .route("/terms/service-providers", web::get().to(PublicController::terms_service_providers))
.route("/terms/solution-providers", web::get().to(PublicController::terms_solution_providers)) .route("/terms/solution-providers", web::get().to(PublicController::terms_solution_providers))
.route("/terms/users", web::get().to(PublicController::terms_users)) .route("/terms/users", web::get().to(PublicController::terms_users))

View File

@@ -2,7 +2,7 @@
pub mod auto_topup; pub mod auto_topup;
pub mod currency; pub mod currency;
pub mod factory; pub mod factory;
pub mod farmer; pub mod resource_provider;
pub mod grid; pub mod grid;
pub mod instant_purchase; pub mod instant_purchase;
pub mod navbar; pub mod navbar;

View File

@@ -1,4 +1,4 @@
//! Node marketplace service for aggregating farmer nodes into marketplace products //! Node marketplace service for aggregating resource_provider nodes into marketplace products
//! Follows the established builder pattern for consistent API design //! Follows the established builder pattern for consistent API design
use crate::models::user::FarmNode; use crate::models::user::FarmNode;
@@ -11,7 +11,7 @@ use rust_decimal::prelude::ToPrimitive;
use std::collections::HashMap; use std::collections::HashMap;
use std::str::FromStr; use std::str::FromStr;
/// Service for converting farmer nodes to marketplace products /// Service for converting resource_provider nodes to marketplace products
#[derive(Clone)] #[derive(Clone)]
pub struct NodeMarketplaceService { pub struct NodeMarketplaceService {
currency_service: CurrencyService, currency_service: CurrencyService,
@@ -89,7 +89,7 @@ impl NodeMarketplaceService {
} }
} }
/// Get all farmer nodes as marketplace products /// Get all resource_provider nodes as marketplace products
pub fn get_all_marketplace_nodes(&self) -> Vec<Product> { pub fn get_all_marketplace_nodes(&self) -> Vec<Product> {
let mut all_products = Vec::new(); let mut all_products = Vec::new();
@@ -125,16 +125,16 @@ impl NodeMarketplaceService {
} }
/// Convert FarmNode to Product using builder pattern /// Convert FarmNode to Product using builder pattern
pub fn convert_node_to_product(&self, node: &FarmNode, farmer_email: &str) -> Result<Product, String> { pub fn convert_node_to_product(&self, node: &FarmNode, resource_provider_email: &str) -> Result<Product, String> {
// Calculate price based on node capacity // Calculate price based on node capacity
let hourly_price = self.calculate_node_price(node)?; let hourly_price = self.calculate_node_price(node)?;
// Create product attributes with node specifications // Create product attributes with node specifications
let mut attributes = HashMap::new(); let mut attributes = HashMap::new();
attributes.insert("farmer_email".to_string(), crate::models::product::ProductAttribute { attributes.insert("resource_provider_email".to_string(), crate::models::product::ProductAttribute {
key: "farmer_email".to_string(), key: "resource_provider_email".to_string(),
value: serde_json::Value::String(farmer_email.to_string()), value: serde_json::Value::String(resource_provider_email.to_string()),
attribute_type: crate::models::product::AttributeType::Text, attribute_type: crate::models::product::AttributeType::Text,
is_searchable: true, is_searchable: true,
is_filterable: true, is_filterable: true,
@@ -200,8 +200,8 @@ impl NodeMarketplaceService {
display_order: Some(6), display_order: Some(6),
}); });
// Get farmer display name // Get resource_provider display name
let farmer_display_name = self.get_farmer_display_name(farmer_email); let resource_provider_display_name = self.get_resource_provider_display_name(resource_provider_email);
// Create metadata with location // Create metadata with location
let metadata = crate::models::product::ProductMetadata { let metadata = crate::models::product::ProductMetadata {
@@ -215,7 +215,7 @@ impl NodeMarketplaceService {
// Use Product builder pattern with add_attribute for each attribute // Use Product builder pattern with add_attribute for each attribute
let mut builder = crate::models::product::Product::builder() let mut builder = crate::models::product::Product::builder()
.id(format!("node_{}", node.id)) .id(format!("node_{}", node.id))
.name(format!("{} - {}", node.name, farmer_display_name)) .name(format!("{} - {}", node.name, resource_provider_display_name))
.description(format!("Mycelium Node with {} CPU cores, {} GB RAM, {} GB storage in {}. Uptime: {:.1}%, Health Score: {:.1}", .description(format!("Mycelium Node with {} CPU cores, {} GB RAM, {} GB storage in {}. Uptime: {:.1}%, Health Score: {:.1}",
node.capacity.cpu_cores, node.capacity.cpu_cores,
node.capacity.memory_gb, node.capacity.memory_gb,
@@ -226,8 +226,8 @@ impl NodeMarketplaceService {
.base_price(hourly_price) .base_price(hourly_price)
.base_currency("USD".to_string()) .base_currency("USD".to_string())
.category_id("hardware".to_string()) .category_id("hardware".to_string())
.provider_id(farmer_email.to_string()) .provider_id(resource_provider_email.to_string())
.provider_name(farmer_display_name) .provider_name(resource_provider_display_name)
.metadata(metadata) .metadata(metadata)
.availability(if self.is_node_online(node) { .availability(if self.is_node_online(node) {
crate::models::product::ProductAvailability::Available crate::models::product::ProductAvailability::Available
@@ -276,17 +276,17 @@ impl NodeMarketplaceService {
format!("{}", node.status) == "Online" format!("{}", node.status) == "Online"
} }
/// Get farmer display name from email /// Get resource_provider display name from email
fn get_farmer_display_name(&self, farmer_email: &str) -> String { fn get_resource_provider_display_name(&self, resource_provider_email: &str) -> String {
// Try to get actual name from persistent data // Try to get actual name from persistent data
if let Some(user_data) = UserPersistence::load_user_data(farmer_email) { if let Some(user_data) = UserPersistence::load_user_data(resource_provider_email) {
if let Some(name) = user_data.name { if let Some(name) = user_data.name {
return name; return name;
} }
} }
// Fallback to email username // Fallback to email username
farmer_email.split('@').next().unwrap_or("Farmer").to_string() resource_provider_email.split('@').next().unwrap_or("ResourceProvider").to_string()
} }
/// Apply marketplace filters to node products /// Apply marketplace filters to node products
@@ -438,7 +438,7 @@ impl NodeMarketplaceService {
let mut total_cpu_cores = 0u32; let mut total_cpu_cores = 0u32;
let mut total_memory_gb = 0u32; let mut total_memory_gb = 0u32;
let mut total_storage_gb = 0u32; let mut total_storage_gb = 0u32;
let mut unique_farmers = std::collections::HashSet::new(); let mut unique_resource_providers = std::collections::HashSet::new();
let mut unique_locations = std::collections::HashSet::new(); let mut unique_locations = std::collections::HashSet::new();
for product in &all_slices { for product in &all_slices {
@@ -456,8 +456,8 @@ impl NodeMarketplaceService {
total_storage_gb += (storage * quantity) as u32; total_storage_gb += (storage * quantity) as u32;
} }
if let Some(farmer) = product.attributes.get("farmer_email").and_then(|f| f.value.as_str()) { if let Some(resource_provider) = product.attributes.get("resource_provider_email").and_then(|f| f.value.as_str()) {
unique_farmers.insert(farmer.to_string()); unique_resource_providers.insert(resource_provider.to_string());
} }
if let Some(location) = &product.metadata.location { if let Some(location) = &product.metadata.location {
@@ -471,9 +471,9 @@ impl NodeMarketplaceService {
"total_cpu_cores": total_cpu_cores, "total_cpu_cores": total_cpu_cores,
"total_memory_gb": total_memory_gb, "total_memory_gb": total_memory_gb,
"total_storage_gb": total_storage_gb, "total_storage_gb": total_storage_gb,
"unique_farmers": unique_farmers.len(), "unique_resource_providers": unique_resource_providers.len(),
"unique_locations": unique_locations.len(), "unique_locations": unique_locations.len(),
"farmers": unique_farmers.into_iter().collect::<Vec<_>>(), "resource_providers": unique_resource_providers.into_iter().collect::<Vec<_>>(),
"locations": unique_locations.into_iter().collect::<Vec<_>>() "locations": unique_locations.into_iter().collect::<Vec<_>>()
}) })
} }
@@ -531,7 +531,7 @@ impl NodeMarketplaceService {
pub fn get_all_slice_combinations(&self) -> Vec<Product> { pub fn get_all_slice_combinations(&self) -> Vec<Product> {
let mut all_slice_products = Vec::new(); let mut all_slice_products = Vec::new();
// Read all user data files to find farmers with nodes // Read all user data files to find resource_providers with nodes
if let Ok(entries) = std::fs::read_dir("./user_data") { if let Ok(entries) = std::fs::read_dir("./user_data") {
for entry in entries.flatten() { for entry in entries.flatten() {
if let Some(filename) = entry.file_name().to_str() { if let Some(filename) = entry.file_name().to_str() {
@@ -585,14 +585,14 @@ impl NodeMarketplaceService {
&self, &self,
combination: &SliceCombination, combination: &SliceCombination,
_node: &FarmNode, _node: &FarmNode,
farmer_email: &str resource_provider_email: &str
) -> Result<Product, String> { ) -> Result<Product, String> {
let mut attributes = HashMap::new(); let mut attributes = HashMap::new();
// Farmer information // ResourceProvider information
attributes.insert("farmer_email".to_string(), crate::models::product::ProductAttribute { attributes.insert("resource_provider_email".to_string(), crate::models::product::ProductAttribute {
key: "farmer_email".to_string(), key: "resource_provider_email".to_string(),
value: serde_json::Value::String(farmer_email.to_string()), value: serde_json::Value::String(resource_provider_email.to_string()),
attribute_type: crate::models::product::AttributeType::Text, attribute_type: crate::models::product::AttributeType::Text,
is_searchable: true, is_searchable: true,
is_filterable: true, is_filterable: true,
@@ -701,15 +701,15 @@ impl NodeMarketplaceService {
display_order: Some(10), display_order: Some(10),
}); });
// Get farmer display name // Get resource_provider display name
let farmer_display_name = self.get_farmer_display_name(farmer_email); let resource_provider_display_name = self.get_resource_provider_display_name(resource_provider_email);
// Create metadata // Create metadata
let metadata = crate::models::product::ProductMetadata { let metadata = crate::models::product::ProductMetadata {
location: Some(combination.node_location.clone()), location: Some(combination.node_location.clone()),
custom_fields: { custom_fields: {
let mut fields = std::collections::HashMap::new(); let mut fields = std::collections::HashMap::new();
fields.insert("provider".to_string(), serde_json::Value::String(farmer_display_name.clone())); fields.insert("provider".to_string(), serde_json::Value::String(resource_provider_display_name.clone()));
fields.insert("certification".to_string(), serde_json::Value::String(combination.node_certification_type.clone())); fields.insert("certification".to_string(), serde_json::Value::String(combination.node_certification_type.clone()));
fields.insert("created_at".to_string(), serde_json::Value::String(chrono::Utc::now().to_rfc3339())); fields.insert("created_at".to_string(), serde_json::Value::String(chrono::Utc::now().to_rfc3339()));
fields.insert("updated_at".to_string(), serde_json::Value::String(chrono::Utc::now().to_rfc3339())); fields.insert("updated_at".to_string(), serde_json::Value::String(chrono::Utc::now().to_rfc3339()));
@@ -727,7 +727,7 @@ impl NodeMarketplaceService {
// Build product using the builder pattern // Build product using the builder pattern
let mut product = crate::models::product::Product::builder() let mut product = crate::models::product::Product::builder()
.id(format!("slice_{}_{}", combination.node_id, combination.id)) .id(format!("slice_{}_{}", combination.node_id, combination.id))
.name(format!("{} Slice ({}x Base Unit)", farmer_display_name, combination.multiplier)) .name(format!("{} Slice ({}x Base Unit)", resource_provider_display_name, combination.multiplier))
.description(format!( .description(format!(
"Compute slice with {} vCPU, {}GB RAM, {}GB storage from {} ({}% uptime)", "Compute slice with {} vCPU, {}GB RAM, {}GB storage from {} ({}% uptime)",
combination.cpu_cores, combination.cpu_cores,
@@ -739,8 +739,8 @@ impl NodeMarketplaceService {
.category_id("compute_slices".to_string()) .category_id("compute_slices".to_string())
.base_price(combination.price_per_hour) .base_price(combination.price_per_hour)
.base_currency("USD".to_string()) .base_currency("USD".to_string())
.provider_id(farmer_email.to_string()) .provider_id(resource_provider_email.to_string())
.provider_name(farmer_display_name) .provider_name(resource_provider_display_name)
.metadata(metadata) .metadata(metadata)
.build() .build()
.map_err(|e| format!("Failed to build slice product: {}", e))?; .map_err(|e| format!("Failed to build slice product: {}", e))?;

View File

@@ -1,7 +1,7 @@
//! Node rental service for managing node rentals and farmer earnings //! Node rental service for managing node rentals and resource_provider earnings
//! Follows the established builder pattern for consistent API design //! Follows the established builder pattern for consistent API design
use crate::models::user::{NodeRental, NodeRentalType, NodeRentalStatus, FarmerRentalEarning, PaymentStatus, NodeAvailabilityStatus}; use crate::models::user::{NodeRental, NodeRentalType, NodeRentalStatus, ResourceProviderRentalEarning, PaymentStatus, NodeAvailabilityStatus};
use crate::services::user_persistence::{UserPersistence, ProductRental}; use crate::services::user_persistence::{UserPersistence, ProductRental};
use rust_decimal::Decimal; use rust_decimal::Decimal;
use chrono::{Utc, Duration}; use chrono::{Utc, Duration};
@@ -65,7 +65,7 @@ impl NodeRentalService {
duration_months: u32, duration_months: u32,
rental_type: NodeRentalType, rental_type: NodeRentalType,
monthly_cost: Decimal, monthly_cost: Decimal,
) -> Result<(NodeRental, FarmerRentalEarning), String> { ) -> Result<(NodeRental, ResourceProviderRentalEarning), String> {
// Extract node ID from product ID // Extract node ID from product ID
let node_id = if product_id.starts_with("fullnode_") { let node_id = if product_id.starts_with("fullnode_") {
product_id.strip_prefix("fullnode_").unwrap_or(product_id) product_id.strip_prefix("fullnode_").unwrap_or(product_id)
@@ -99,8 +99,8 @@ impl NodeRentalService {
.payment_method("USD".to_string()) .payment_method("USD".to_string())
.build()?; .build()?;
// Create farmer earning record // Create resource_provider earning record
let farmer_earning = crate::models::builders::FarmerRentalEarningBuilder::new() let resource_provider_earning = crate::models::builders::ResourceProviderRentalEarningBuilder::new()
.node_id(node_id.to_string()) .node_id(node_id.to_string())
.rental_id(rental.id.clone()) .rental_id(rental.id.clone())
.renter_email(renter_email.to_string()) .renter_email(renter_email.to_string())
@@ -111,29 +111,29 @@ impl NodeRentalService {
.payment_status(PaymentStatus::Completed) .payment_status(PaymentStatus::Completed)
.build()?; .build()?;
// Find the farmer who owns this node // Find the resource_provider who owns this node
let farmer_email = self.find_node_owner(node_id)?; let resource_provider_email = self.find_node_owner(node_id)?;
// Save rental to renter's data // Save rental to renter's data
self.save_rental_to_user(&rental, renter_email, product_id)?; self.save_rental_to_user(&rental, renter_email, product_id)?;
// Save earning to farmer's data // Save earning to resource_provider's data
self.save_earning_to_farmer(&farmer_earning, &farmer_email)?; self.save_earning_to_resource_provider(&resource_provider_earning, &resource_provider_email)?;
// Update node availability status // Update node availability status
self.update_node_availability(node_id, &farmer_email)?; self.update_node_availability(node_id, &resource_provider_email)?;
Ok((rental, farmer_earning)) Ok((rental, resource_provider_earning))
} }
/// Check for rental conflicts /// Check for rental conflicts
fn check_rental_conflicts(&self, node_id: &str, rental_type: &NodeRentalType) -> Result<(), String> { fn check_rental_conflicts(&self, node_id: &str, rental_type: &NodeRentalType) -> Result<(), String> {
// Find the farmer who owns this node // Find the resource_provider who owns this node
let farmer_email = self.find_node_owner(node_id)?; let resource_provider_email = self.find_node_owner(node_id)?;
if let Some(farmer_data) = UserPersistence::load_user_data(&farmer_email) { if let Some(resource_provider_data) = UserPersistence::load_user_data(&resource_provider_email) {
// Check existing rentals for this node // Check existing rentals for this node
let existing_rentals: Vec<_> = farmer_data.node_rentals.iter() let existing_rentals: Vec<_> = resource_provider_data.node_rentals.iter()
.filter(|r| r.node_id == node_id && r.is_active()) .filter(|r| r.node_id == node_id && r.is_active())
.collect(); .collect();
@@ -166,7 +166,7 @@ impl NodeRentalService {
Ok(()) Ok(())
} }
/// Find the farmer who owns a specific node /// Find the resource_provider who owns a specific node
fn find_node_owner(&self, node_id: &str) -> Result<String, String> { fn find_node_owner(&self, node_id: &str) -> Result<String, String> {
// Scan all user files to find the node owner // Scan all user files to find the node owner
if let Ok(entries) = std::fs::read_dir("./user_data/") { if let Ok(entries) = std::fs::read_dir("./user_data/") {
@@ -226,31 +226,31 @@ impl NodeRentalService {
Ok(()) Ok(())
} }
/// Save earning record to farmer's persistent data /// Save earning record to resource_provider's persistent data
fn save_earning_to_farmer(&self, earning: &FarmerRentalEarning, farmer_email: &str) -> Result<(), String> { fn save_earning_to_resource_provider(&self, earning: &ResourceProviderRentalEarning, resource_provider_email: &str) -> Result<(), String> {
let mut farmer_data = UserPersistence::load_user_data(farmer_email) let mut resource_provider_data = UserPersistence::load_user_data(resource_provider_email)
.unwrap_or_else(|| self.create_default_user_data(farmer_email)); .unwrap_or_else(|| self.create_default_user_data(resource_provider_email));
// Add to farmer rental earnings // Add to resource_provider rental earnings
farmer_data.farmer_rental_earnings.push(earning.clone()); resource_provider_data.resource_provider_rental_earnings.push(earning.clone());
// Update wallet balance // Update wallet balance
farmer_data.wallet_balance_usd += earning.amount; resource_provider_data.wallet_balance_usd += earning.amount;
UserPersistence::save_user_data(&farmer_data) UserPersistence::save_user_data(&resource_provider_data)
.map_err(|e| format!("Failed to save farmer data: {}", e))?; .map_err(|e| format!("Failed to save resource_provider data: {}", e))?;
Ok(()) Ok(())
} }
/// Update node availability status based on current rentals /// Update node availability status based on current rentals
fn update_node_availability(&self, node_id: &str, farmer_email: &str) -> Result<(), String> { fn update_node_availability(&self, node_id: &str, resource_provider_email: &str) -> Result<(), String> {
let mut farmer_data = UserPersistence::load_user_data(farmer_email) let mut resource_provider_data = UserPersistence::load_user_data(resource_provider_email)
.ok_or("Farmer data not found")?; .ok_or("ResourceProvider data not found")?;
if let Some(node) = farmer_data.nodes.iter_mut().find(|n| n.id == node_id) { if let Some(node) = resource_provider_data.nodes.iter_mut().find(|n| n.id == node_id) {
// Count active rentals for this node // Count active rentals for this node
let active_rentals: Vec<_> = farmer_data.node_rentals.iter() let active_rentals: Vec<_> = resource_provider_data.node_rentals.iter()
.filter(|r| r.node_id == node_id && r.is_active()) .filter(|r| r.node_id == node_id && r.is_active())
.collect(); .collect();
@@ -262,7 +262,7 @@ impl NodeRentalService {
NodeAvailabilityStatus::PartiallyRented NodeAvailabilityStatus::PartiallyRented
}; };
UserPersistence::save_user_data(&farmer_data) UserPersistence::save_user_data(&resource_provider_data)
.map_err(|e| format!("Failed to update node availability: {}", e))?; .map_err(|e| format!("Failed to update node availability: {}", e))?;
} }
@@ -285,10 +285,10 @@ impl NodeRentalService {
} }
} }
/// Get farmer earnings from rentals /// Get resource_provider earnings from rentals
pub fn get_farmer_rental_earnings(&self, farmer_email: &str) -> Vec<FarmerRentalEarning> { pub fn get_resource_provider_rental_earnings(&self, resource_provider_email: &str) -> Vec<ResourceProviderRentalEarning> {
if let Some(farmer_data) = UserPersistence::load_user_data(farmer_email) { if let Some(resource_provider_data) = UserPersistence::load_user_data(resource_provider_email) {
farmer_data.farmer_rental_earnings resource_provider_data.resource_provider_rental_earnings
} else { } else {
Vec::new() Vec::new()
} }
@@ -309,8 +309,8 @@ impl NodeRentalService {
} }
// Update node availability // Update node availability
let farmer_email = self.find_node_owner(&rental.node_id)?; let resource_provider_email = self.find_node_owner(&rental.node_id)?;
self.update_node_availability(&rental.node_id, &farmer_email)?; self.update_node_availability(&rental.node_id, &resource_provider_email)?;
UserPersistence::save_user_data(&user_data) UserPersistence::save_user_data(&user_data)
.map_err(|e| format!("Failed to save user data: {}", e))?; .map_err(|e| format!("Failed to save user data: {}", e))?;

View File

@@ -241,8 +241,8 @@ impl ProductService {
if let Some(combination_id) = product.attributes.get("combination_id") { if let Some(combination_id) = product.attributes.get("combination_id") {
details["combination_id"] = combination_id.value.clone(); details["combination_id"] = combination_id.value.clone();
} }
if let Some(farmer_email) = product.attributes.get("farmer_email") { if let Some(resource_provider_email) = product.attributes.get("resource_provider_email") {
details["farmer_email"] = farmer_email.value.clone(); details["resource_provider_email"] = resource_provider_email.value.clone();
} }
if let Some(cpu_cores) = product.attributes.get("cpu_cores") { if let Some(cpu_cores) = product.attributes.get("cpu_cores") {
details["cpu_cores"] = cpu_cores.value.clone(); details["cpu_cores"] = cpu_cores.value.clone();

View File

@@ -1,4 +1,4 @@
//! Farmer service for managing nodes, slice allocation, and earnings //! ResourceProvider service for managing nodes, slice allocation, and earnings
//! Follows the established builder pattern for consistent API design //! Follows the established builder pattern for consistent API design
use crate::models::user::{FarmNode, NodeCapacity, NodeStatus, EarningsRecord, NodeGroup, GroupStatistics, MarketplaceSLA}; use crate::models::user::{FarmNode, NodeCapacity, NodeStatus, EarningsRecord, NodeGroup, GroupStatistics, MarketplaceSLA};
@@ -12,7 +12,7 @@ use std::str::FromStr;
use chrono::{Utc, DateTime}; use chrono::{Utc, DateTime};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
/// Staking statistics for a farmer /// Staking statistics for a resource_provider
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StakingStatistics { pub struct StakingStatistics {
pub total_staked_amount: Decimal, pub total_staked_amount: Decimal,
@@ -30,25 +30,25 @@ impl Default for StakingStatistics {
} }
} }
/// Service for farmer-specific operations /// Service for resource_provider-specific operations
#[derive(Clone)] #[derive(Clone)]
pub struct FarmerService { pub struct ResourceProviderService {
auto_sync_enabled: bool, auto_sync_enabled: bool,
metrics_collection: bool, metrics_collection: bool,
grid_service: GridService, grid_service: GridService,
slice_calculator: SliceCalculatorService, slice_calculator: SliceCalculatorService,
} }
/// Builder for FarmerService /// Builder for ResourceProviderService
#[derive(Default)] #[derive(Default)]
pub struct FarmerServiceBuilder { pub struct ResourceProviderServiceBuilder {
auto_sync_enabled: Option<bool>, auto_sync_enabled: Option<bool>,
metrics_collection: Option<bool>, metrics_collection: Option<bool>,
grid_service: Option<GridService>, grid_service: Option<GridService>,
slice_calculator: Option<SliceCalculatorService>, slice_calculator: Option<SliceCalculatorService>,
} }
impl FarmerServiceBuilder { impl ResourceProviderServiceBuilder {
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }
@@ -73,7 +73,7 @@ impl FarmerServiceBuilder {
self self
} }
pub fn build(self) -> Result<FarmerService, String> { pub fn build(self) -> Result<ResourceProviderService, String> {
let grid_service = self.grid_service.unwrap_or_else(|| { let grid_service = self.grid_service.unwrap_or_else(|| {
GridService::builder().build().expect("Failed to create default GridService") GridService::builder().build().expect("Failed to create default GridService")
}); });
@@ -82,7 +82,7 @@ impl FarmerServiceBuilder {
SliceCalculatorService::builder().build().expect("Failed to create default SliceCalculatorService") SliceCalculatorService::builder().build().expect("Failed to create default SliceCalculatorService")
}); });
Ok(FarmerService { Ok(ResourceProviderService {
auto_sync_enabled: self.auto_sync_enabled.unwrap_or(true), auto_sync_enabled: self.auto_sync_enabled.unwrap_or(true),
metrics_collection: self.metrics_collection.unwrap_or(true), metrics_collection: self.metrics_collection.unwrap_or(true),
grid_service, grid_service,
@@ -91,13 +91,13 @@ impl FarmerServiceBuilder {
} }
} }
impl FarmerService { impl ResourceProviderService {
pub fn builder() -> FarmerServiceBuilder { pub fn builder() -> ResourceProviderServiceBuilder {
FarmerServiceBuilder::new() ResourceProviderServiceBuilder::new()
} }
/// Get all nodes for a farmer /// Get all nodes for a resource_provider
pub fn get_farmer_nodes(&self, user_email: &str) -> Vec<FarmNode> { pub fn get_resource_provider_nodes(&self, user_email: &str) -> Vec<FarmNode> {
if let Some(data) = UserPersistence::load_user_data(user_email) { if let Some(data) = UserPersistence::load_user_data(user_email) {
// Debug: Log marketplace SLA data for all nodes // Debug: Log marketplace SLA data for all nodes
for node in &data.nodes { for node in &data.nodes {
@@ -111,10 +111,10 @@ impl FarmerService {
} }
} }
/// Add a new node for a farmer (manual creation) /// Add a new node for a resource_provider (manual creation)
pub fn add_node(&self, user_email: &str, node_data: NodeCreationData) -> Result<FarmNode, String> { pub fn add_node(&self, user_email: &str, node_data: NodeCreationData) -> Result<FarmNode, String> {
// Check for duplicate node names first // Check for duplicate node names first
let existing_nodes = self.get_farmer_nodes(user_email); let existing_nodes = self.get_resource_provider_nodes(user_email);
if existing_nodes.iter().any(|n| n.name == node_data.name) { if existing_nodes.iter().any(|n| n.name == node_data.name) {
return Err(format!("Node '{}' is already registered", node_data.name)); return Err(format!("Node '{}' is already registered", node_data.name));
} }
@@ -234,7 +234,7 @@ impl FarmerService {
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
// Auto-generate marketplace products if rental options are configured // Auto-generate marketplace products if rental options are configured
self.auto_generate_marketplace_products(&node, user_email, &persistent_data.name.unwrap_or_else(|| "Unknown Farmer".to_string()), node_data.slice_prices.as_ref())?; self.auto_generate_marketplace_products(&node, user_email, &persistent_data.name.unwrap_or_else(|| "Unknown ResourceProvider".to_string()), node_data.slice_prices.as_ref())?;
Ok(node) Ok(node)
} }
@@ -434,10 +434,10 @@ impl FarmerService {
/// Sync node capacity and slices with grid data /// Sync node capacity and slices with grid data
pub async fn sync_node_with_grid(&self, user_email: &str, node_id: &str) -> Result<(), String> { pub async fn sync_node_with_grid(&self, user_email: &str, node_id: &str) -> Result<(), String> {
let mut farmer_data = UserPersistence::load_user_data(user_email) let mut resource_provider_data = UserPersistence::load_user_data(user_email)
.ok_or("Farmer data not found")?; .ok_or("ResourceProvider data not found")?;
if let Some(node) = farmer_data.nodes.iter_mut().find(|n| n.id == node_id) { if let Some(node) = resource_provider_data.nodes.iter_mut().find(|n| n.id == node_id) {
if let Some(grid_node_id) = &node.grid_node_id { if let Some(grid_node_id) = &node.grid_node_id {
// Fetch latest capacity from grid // Fetch latest capacity from grid
let grid_id: u32 = grid_node_id.parse().unwrap_or(0); let grid_id: u32 = grid_node_id.parse().unwrap_or(0);
@@ -472,7 +472,7 @@ impl FarmerService {
} }
// Save updated data // Save updated data
UserPersistence::save_user_data(&farmer_data) UserPersistence::save_user_data(&resource_provider_data)
.map_err(|e| format!("Failed to save user data: {}", e))?; .map_err(|e| format!("Failed to save user data: {}", e))?;
} else { } else {
return Err("Node is not linked to grid".to_string()); return Err("Node is not linked to grid".to_string());
@@ -486,7 +486,7 @@ impl FarmerService {
/// Auto-generate marketplace products for a node based on rental options /// Auto-generate marketplace products for a node based on rental options
/// Products are now managed through persistent user data and aggregated by ProductService /// Products are now managed through persistent user data and aggregated by ProductService
fn auto_generate_marketplace_products(&self, _node: &FarmNode, _farmer_email: &str, _farmer_name: &str, _slice_prices: Option<&std::collections::HashMap<String, rust_decimal::Decimal>>) -> Result<(), String> { fn auto_generate_marketplace_products(&self, _node: &FarmNode, _resource_provider_email: &str, _resource_provider_name: &str, _slice_prices: Option<&std::collections::HashMap<String, rust_decimal::Decimal>>) -> Result<(), String> {
// Product generation is now handled through persistent user data // Product generation is now handled through persistent user data
// ProductService automatically aggregates products from user-owned data // ProductService automatically aggregates products from user-owned data
Ok(()) Ok(())
@@ -754,7 +754,7 @@ impl FarmerService {
} }
/// Create a slice product from a node and slice format /// Create a slice product from a node and slice format
fn create_slice_product_from_node(&self, node: &FarmNode, slice_format_id: &str, farmer_email: &str, farmer_name: &str, custom_prices: Option<&std::collections::HashMap<String, rust_decimal::Decimal>>) -> Result<crate::models::product::Product, String> { fn create_slice_product_from_node(&self, node: &FarmNode, slice_format_id: &str, resource_provider_email: &str, resource_provider_name: &str, custom_prices: Option<&std::collections::HashMap<String, rust_decimal::Decimal>>) -> Result<crate::models::product::Product, String> {
// Get slice format details and default pricing // Get slice format details and default pricing
let (cpu_cores, memory_gb, storage_gb, bandwidth_mbps, default_price) = match slice_format_id { let (cpu_cores, memory_gb, storage_gb, bandwidth_mbps, default_price) = match slice_format_id {
"basic" => (2, 4, 100, 100, 25), "basic" => (2, 4, 100, 100, 25),
@@ -789,8 +789,8 @@ impl FarmerService {
base_price: price, base_price: price,
base_currency: "USD".to_string(), base_currency: "USD".to_string(),
attributes: std::collections::HashMap::new(), attributes: std::collections::HashMap::new(),
provider_id: farmer_email.to_string(), provider_id: resource_provider_email.to_string(),
provider_name: farmer_name.to_string(), provider_name: resource_provider_name.to_string(),
availability: match node.availability_status { availability: match node.availability_status {
crate::models::user::NodeAvailabilityStatus::Available => crate::models::product::ProductAvailability::Available, crate::models::user::NodeAvailabilityStatus::Available => crate::models::product::ProductAvailability::Available,
crate::models::user::NodeAvailabilityStatus::PartiallyRented => crate::models::product::ProductAvailability::Limited, crate::models::user::NodeAvailabilityStatus::PartiallyRented => crate::models::product::ProductAvailability::Limited,
@@ -880,19 +880,19 @@ impl FarmerService {
Ok(()) Ok(())
} }
/// Get farmer earnings /// Get resource_provider earnings
pub fn get_farmer_earnings(&self, user_email: &str) -> Vec<EarningsRecord> { pub fn get_resource_provider_earnings(&self, user_email: &str) -> Vec<EarningsRecord> {
if let Some(data) = UserPersistence::load_user_data(user_email) { if let Some(data) = UserPersistence::load_user_data(user_email) {
data.farmer_earnings data.resource_provider_earnings
} else { } else {
Vec::new() Vec::new()
} }
} }
/// Get farmer statistics /// Get resource_provider statistics
pub fn get_farmer_statistics(&self, user_email: &str) -> FarmerStatistics { pub fn get_resource_provider_statistics(&self, user_email: &str) -> FarmerStatistics {
let nodes = self.get_farmer_nodes(user_email); let nodes = self.get_resource_provider_nodes(user_email);
let earnings = self.get_farmer_earnings(user_email); let earnings = self.get_resource_provider_earnings(user_email);
let total_nodes = nodes.len() as i32; let total_nodes = nodes.len() as i32;
let online_nodes = nodes.iter() let online_nodes = nodes.iter()
@@ -990,7 +990,7 @@ impl FarmerService {
slice_config.bandwidth_mbps <= available_bandwidth) slice_config.bandwidth_mbps <= available_bandwidth)
} }
/// Get default slice formats available to all farmers /// Get default slice formats available to all resource providers
pub fn get_default_slice_formats(&self) -> Vec<DefaultSliceFormat> { pub fn get_default_slice_formats(&self) -> Vec<DefaultSliceFormat> {
vec![ vec![
DefaultSliceFormat { DefaultSliceFormat {
@@ -1039,8 +1039,8 @@ impl FarmerService {
// Load user customizations from persistent data // Load user customizations from persistent data
if let Some(persistent_data) = UserPersistence::load_user_data(user_email) { if let Some(persistent_data) = UserPersistence::load_user_data(user_email) {
if let Some(farmer_settings) = persistent_data.farmer_settings { if let Some(resource_provider_settings) = persistent_data.resource_provider_settings {
if let Some(customizations) = farmer_settings.default_slice_customizations { if let Some(customizations) = resource_provider_settings.default_slice_customizations {
if let Some(custom_format) = customizations.get(format_id) { if let Some(custom_format) = customizations.get(format_id) {
// Apply user customizations // Apply user customizations
if let Some(cpu_cores) = custom_format.get("cpu_cores").and_then(|v| v.as_u64()).map(|v| v as u32) { if let Some(cpu_cores) = custom_format.get("cpu_cores").and_then(|v| v.as_u64()).map(|v| v as u32) {
@@ -1075,9 +1075,9 @@ impl FarmerService {
pub fn save_default_slice_customization(&self, user_email: &str, format_id: &str, customization: DefaultSliceFormat) -> Result<(), String> { pub fn save_default_slice_customization(&self, user_email: &str, format_id: &str, customization: DefaultSliceFormat) -> Result<(), String> {
let mut persistent_data = crate::models::builders::SessionDataBuilder::load_or_create(user_email); let mut persistent_data = crate::models::builders::SessionDataBuilder::load_or_create(user_email);
// Initialize farmer settings if needed // Initialize resource_provider settings if needed
if persistent_data.farmer_settings.is_none() { if persistent_data.resource_provider_settings.is_none() {
persistent_data.farmer_settings = Some(crate::models::user::FarmerSettings { persistent_data.resource_provider_settings = Some(crate::models::user::FarmerSettings {
auto_accept_reserved_slices: true, auto_accept_reserved_slices: true,
maintenance_window: "02:00-04:00 UTC".to_string(), maintenance_window: "02:00-04:00 UTC".to_string(),
notification_email: None, notification_email: None,
@@ -1096,12 +1096,12 @@ impl FarmerService {
} }
// Initialize default slice customizations if needed // Initialize default slice customizations if needed
if let Some(ref mut farmer_settings) = persistent_data.farmer_settings { if let Some(ref mut resource_provider_settings) = persistent_data.resource_provider_settings {
if farmer_settings.default_slice_customizations.is_none() { if resource_provider_settings.default_slice_customizations.is_none() {
farmer_settings.default_slice_customizations = Some(serde_json::to_value(std::collections::HashMap::<String, serde_json::Value>::new()).unwrap_or_default()); resource_provider_settings.default_slice_customizations = Some(serde_json::to_value(std::collections::HashMap::<String, serde_json::Value>::new()).unwrap_or_default());
} }
if let Some(ref mut customizations) = farmer_settings.default_slice_customizations { if let Some(ref mut customizations) = resource_provider_settings.default_slice_customizations {
if let Some(obj) = customizations.as_object_mut() { if let Some(obj) = customizations.as_object_mut() {
obj.insert(format_id.to_string(), serde_json::to_value(customization).unwrap_or_default()); obj.insert(format_id.to_string(), serde_json::to_value(customization).unwrap_or_default());
} }
@@ -1288,7 +1288,7 @@ impl FarmerService {
/// Add a node from ThreeFold Grid by node ID /// Add a node from ThreeFold Grid by node ID
pub async fn add_grid_node(&self, user_email: &str, grid_node_id: u32, _slice_format: Option<String>, _slice_price: Option<Decimal>) -> Result<FarmNode, String> { pub async fn add_grid_node(&self, user_email: &str, grid_node_id: u32, _slice_format: Option<String>, _slice_price: Option<Decimal>) -> Result<FarmNode, String> {
// Check for duplicate grid node IDs first // Check for duplicate grid node IDs first
let existing_nodes = self.get_farmer_nodes(user_email); let existing_nodes = self.get_resource_provider_nodes(user_email);
if existing_nodes.iter().any(|n| n.grid_node_id == Some(grid_node_id.to_string())) { if existing_nodes.iter().any(|n| n.grid_node_id == Some(grid_node_id.to_string())) {
return Err(format!("Node {} is already registered", grid_node_id)); return Err(format!("Node {} is already registered", grid_node_id));
} }
@@ -1845,8 +1845,8 @@ impl FarmerService {
.unwrap_or(false); .unwrap_or(false);
if slice_rental_enabled || full_node_rental_enabled { if slice_rental_enabled || full_node_rental_enabled {
let farmer_name = persistent_data.name.unwrap_or_else(|| "Unknown Farmer".to_string()); let resource_provider_name = persistent_data.name.unwrap_or_else(|| "Unknown ResourceProvider".to_string());
self.auto_generate_marketplace_products(&node, user_email, &farmer_name, None)?; self.auto_generate_marketplace_products(&node, user_email, &resource_provider_name, None)?;
} }
} }
Ok(node) Ok(node)
@@ -1856,7 +1856,7 @@ impl FarmerService {
// NODE GROUP MANAGEMENT // NODE GROUP MANAGEMENT
// ============================================================================= // =============================================================================
/// Ensure default node groups exist for a farmer /// Ensure default node groups exist for a resource_provider
pub fn ensure_default_node_groups(&self, user_email: &str) -> Result<(), String> { pub fn ensure_default_node_groups(&self, user_email: &str) -> Result<(), String> {
let mut persistent_data = crate::models::builders::SessionDataBuilder::load_or_create(user_email); let mut persistent_data = crate::models::builders::SessionDataBuilder::load_or_create(user_email);
@@ -1898,7 +1898,7 @@ impl FarmerService {
Ok(group) Ok(group)
} }
/// Get all node groups for a farmer (ensures defaults exist) /// Get all node groups for a resource_provider (ensures defaults exist)
pub fn get_node_groups(&self, user_email: &str) -> Vec<NodeGroup> { pub fn get_node_groups(&self, user_email: &str) -> Vec<NodeGroup> {
// Ensure default groups exist first // Ensure default groups exist first
if let Err(e) = self.ensure_default_node_groups(user_email) { if let Err(e) = self.ensure_default_node_groups(user_email) {
@@ -2165,7 +2165,7 @@ impl FarmerService {
/// Get node by name (for duplicate checking) /// Get node by name (for duplicate checking)
pub fn get_node_by_name(&self, user_email: &str, node_name: &str) -> Option<FarmNode> { pub fn get_node_by_name(&self, user_email: &str, node_name: &str) -> Option<FarmNode> {
let nodes = self.get_farmer_nodes(user_email); let nodes = self.get_resource_provider_nodes(user_email);
nodes.into_iter().find(|n| n.name == node_name) nodes.into_iter().find(|n| n.name == node_name)
} }
@@ -2278,12 +2278,12 @@ impl FarmerService {
Ok(()) Ok(())
} }
/// Create default user data for new farmers /// Create default user data for new resource providers
fn create_default_user_data(user_email: &str) -> UserPersistentData { fn create_default_user_data(user_email: &str) -> UserPersistentData {
crate::models::builders::SessionDataBuilder::new_user(user_email) crate::models::builders::SessionDataBuilder::new_user(user_email)
} }
/// Refresh all slice calculations for a farmer /// Refresh all slice calculations for a resource_provider
pub fn refresh_all_slice_calculations(&self, user_email: &str) -> Result<(), String> { pub fn refresh_all_slice_calculations(&self, user_email: &str) -> Result<(), String> {
let mut persistent_data = UserPersistence::load_user_data(user_email) let mut persistent_data = UserPersistence::load_user_data(user_email)
.ok_or("User data not found")?; .ok_or("User data not found")?;
@@ -2395,7 +2395,7 @@ impl FarmerService {
Ok(slices) Ok(slices)
} }
/// Get comprehensive slice statistics for a farmer /// Get comprehensive slice statistics for a resource_provider
pub fn get_slice_statistics(&self, user_email: &str) -> Result<serde_json::Value, String> { pub fn get_slice_statistics(&self, user_email: &str) -> Result<serde_json::Value, String> {
let persistent_data = UserPersistence::load_user_data(user_email) let persistent_data = UserPersistence::load_user_data(user_email)
.ok_or("User data not found")?; .ok_or("User data not found")?;
@@ -2821,7 +2821,7 @@ impl FarmerService {
Ok(repaired_count) Ok(repaired_count)
} }
/// Refresh all slice calculations for a farmer (async version) /// Refresh all slice calculations for a resource_provider (async version)
pub async fn refresh_all_slice_calculations_async(&self, user_email: &str) -> Result<u32, String> { pub async fn refresh_all_slice_calculations_async(&self, user_email: &str) -> Result<u32, String> {
let mut persistent_data = UserPersistence::load_user_data(user_email) let mut persistent_data = UserPersistence::load_user_data(user_email)
.ok_or("User data not found")?; .ok_or("User data not found")?;
@@ -2971,7 +2971,7 @@ pub struct NodeUpdateData {
pub marketplace_sla: Option<MarketplaceSLA>, pub marketplace_sla: Option<MarketplaceSLA>,
} }
/// Default slice formats available to all farmers /// Default slice formats available to all resource providers
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DefaultSliceFormat { pub struct DefaultSliceFormat {
pub id: String, pub id: String,
@@ -2984,7 +2984,7 @@ pub struct DefaultSliceFormat {
pub price_per_hour: rust_decimal::Decimal, pub price_per_hour: rust_decimal::Decimal,
} }
/// Farmer statistics summary /// ResourceProvider statistics summary
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FarmerStatistics { pub struct FarmerStatistics {
pub total_nodes: i32, pub total_nodes: i32,

View File

@@ -18,7 +18,7 @@ pub struct SliceAssignmentService {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SliceAssignmentRequest { pub struct SliceAssignmentRequest {
pub user_email: String, pub user_email: String,
pub farmer_email: String, pub resource_provider_email: String,
pub node_id: String, pub node_id: String,
pub combination_id: String, pub combination_id: String,
pub quantity: u32, pub quantity: u32,
@@ -127,7 +127,7 @@ pub struct SecurityConfiguration {
pub struct SliceAssignment { pub struct SliceAssignment {
pub assignment_id: String, pub assignment_id: String,
pub user_email: String, pub user_email: String,
pub farmer_email: String, pub resource_provider_email: String,
pub node_id: String, pub node_id: String,
pub combination_id: String, pub combination_id: String,
pub slice_allocations: Vec<SliceAllocation>, pub slice_allocations: Vec<SliceAllocation>,
@@ -241,7 +241,7 @@ impl SliceAssignmentService {
let assignment = SliceAssignment { let assignment = SliceAssignment {
assignment_id, assignment_id,
user_email: request.user_email, user_email: request.user_email,
farmer_email: request.farmer_email, resource_provider_email: request.resource_provider_email,
node_id: request.node_id, node_id: request.node_id,
combination_id: request.combination_id, combination_id: request.combination_id,
slice_allocations, slice_allocations,
@@ -377,7 +377,7 @@ impl SliceAssignmentService {
"status": "deploying", "status": "deploying",
"deployment_type": "vm", "deployment_type": "vm",
"node_id": assignment.node_id, "node_id": assignment.node_id,
"farmer_email": assignment.farmer_email, "resource_provider_email": assignment.resource_provider_email,
"started_at": Utc::now(), "started_at": Utc::now(),
"estimated_completion": Utc::now() + chrono::Duration::minutes(5) "estimated_completion": Utc::now() + chrono::Duration::minutes(5)
}); });

View File

@@ -42,7 +42,7 @@ pub struct SliceCombination {
pub node_location: String, pub node_location: String,
pub node_certification_type: String, pub node_certification_type: String,
pub node_id: String, pub node_id: String,
pub farmer_email: String, pub resource_provider_email: String,
} }
/// Track individual slice rentals /// Track individual slice rentals
@@ -70,7 +70,7 @@ pub enum AllocationStatus {
pub struct SlicePricing { pub struct SlicePricing {
pub base_price_per_hour: Decimal, // Price for 1 base slice per hour pub base_price_per_hour: Decimal, // Price for 1 base slice per hour
pub currency: String, pub currency: String,
pub pricing_multiplier: Decimal, // Farmer can adjust pricing (0.5x - 2.0x) pub pricing_multiplier: Decimal, // ResourceProvider can adjust pricing (0.5x - 2.0x)
} }
impl Default for SlicePricing { impl Default for SlicePricing {
@@ -157,7 +157,7 @@ impl SliceCalculatorService {
max_base_slices: u32, max_base_slices: u32,
allocated_slices: u32, allocated_slices: u32,
node: &FarmNode, node: &FarmNode,
farmer_email: &str resource_provider_email: &str
) -> Vec<SliceCombination> { ) -> Vec<SliceCombination> {
let available_base_slices = max_base_slices.saturating_sub(allocated_slices); let available_base_slices = max_base_slices.saturating_sub(allocated_slices);
let mut combinations = Vec::new(); let mut combinations = Vec::new();
@@ -208,7 +208,7 @@ impl SliceCalculatorService {
.to_string()) .to_string())
.unwrap_or_else(|| "DIY".to_string()), .unwrap_or_else(|| "DIY".to_string()),
node_id: node.id.clone(), node_id: node.id.clone(),
farmer_email: farmer_email.to_string(), resource_provider_email: resource_provider_email.to_string(),
}; };
combinations.push(combination); combinations.push(combination);
@@ -225,7 +225,7 @@ impl SliceCalculatorService {
max_base_slices: u32, max_base_slices: u32,
allocated_slices: u32, allocated_slices: u32,
node: &FarmNode, node: &FarmNode,
farmer_email: &str, resource_provider_email: &str,
uptime_percentage: f64, uptime_percentage: f64,
bandwidth_mbps: u32, bandwidth_mbps: u32,
base_price_per_hour: Decimal base_price_per_hour: Decimal
@@ -283,7 +283,7 @@ impl SliceCalculatorService {
.to_string()) .to_string())
.unwrap_or_else(|| "DIY".to_string()), .unwrap_or_else(|| "DIY".to_string()),
node_id: node.id.clone(), node_id: node.id.clone(),
farmer_email: farmer_email.to_string(), resource_provider_email: resource_provider_email.to_string(),
}; };
combinations.push(combination); combinations.push(combination);
@@ -304,7 +304,7 @@ impl SliceCalculatorService {
&self, &self,
node: &mut FarmNode, node: &mut FarmNode,
rented_base_slices: u32, rented_base_slices: u32,
farmer_email: &str resource_provider_email: &str
) -> Result<(), String> { ) -> Result<(), String> {
// Update allocated count // Update allocated count
node.allocated_base_slices += rented_base_slices as i32; node.allocated_base_slices += rented_base_slices as i32;
@@ -314,7 +314,7 @@ impl SliceCalculatorService {
node.total_base_slices as u32, node.total_base_slices as u32,
node.allocated_base_slices as u32, node.allocated_base_slices as u32,
node, node,
farmer_email resource_provider_email
); );
node.available_combinations = combinations.iter() node.available_combinations = combinations.iter()
.map(|c| serde_json::to_value(c).unwrap_or_default()) .map(|c| serde_json::to_value(c).unwrap_or_default())
@@ -328,7 +328,7 @@ impl SliceCalculatorService {
&self, &self,
node: &mut FarmNode, node: &mut FarmNode,
released_base_slices: u32, released_base_slices: u32,
farmer_email: &str resource_provider_email: &str
) -> Result<(), String> { ) -> Result<(), String> {
// Update allocated count // Update allocated count
node.allocated_base_slices = node.allocated_base_slices.saturating_sub(released_base_slices as i32); node.allocated_base_slices = node.allocated_base_slices.saturating_sub(released_base_slices as i32);
@@ -338,7 +338,7 @@ impl SliceCalculatorService {
node.total_base_slices as u32, node.total_base_slices as u32,
node.allocated_base_slices as u32, node.allocated_base_slices as u32,
node, node,
farmer_email resource_provider_email
).iter() ).iter()
.map(|c| serde_json::to_value(c).unwrap_or_default()) .map(|c| serde_json::to_value(c).unwrap_or_default())
.collect(); .collect();
@@ -364,7 +364,7 @@ pub struct SliceRental {
pub rental_id: String, pub rental_id: String,
pub slice_combination_id: String, pub slice_combination_id: String,
pub node_id: String, pub node_id: String,
pub farmer_email: String, pub resource_provider_email: String,
pub slice_allocation: SliceAllocation, pub slice_allocation: SliceAllocation,
pub total_cost: Decimal, pub total_cost: Decimal,
pub payment_status: PaymentStatus, pub payment_status: PaymentStatus,

View File

@@ -56,11 +56,11 @@ impl SliceRentalService {
SliceRentalServiceBuilder::new() SliceRentalServiceBuilder::new()
} }
/// Rent a slice combination from a farmer's node /// Rent a slice combination from a resource_provider's node
pub fn rent_slice_combination( pub fn rent_slice_combination(
&self, &self,
renter_email: &str, renter_email: &str,
farmer_email: &str, resource_provider_email: &str,
node_id: &str, node_id: &str,
combination_id: &str, combination_id: &str,
quantity: u32, quantity: u32,
@@ -68,9 +68,9 @@ impl SliceRentalService {
) -> Result<SliceRental, String> { ) -> Result<SliceRental, String> {
// Atomic operation with file locking to prevent conflicts // Atomic operation with file locking to prevent conflicts
if self.enable_file_locking { if self.enable_file_locking {
self.rent_with_file_lock(renter_email, farmer_email, node_id, combination_id, quantity, rental_duration_hours) self.rent_with_file_lock(renter_email, resource_provider_email, node_id, combination_id, quantity, rental_duration_hours)
} else { } else {
self.rent_without_lock(renter_email, farmer_email, node_id, combination_id, quantity, rental_duration_hours) self.rent_without_lock(renter_email, resource_provider_email, node_id, combination_id, quantity, rental_duration_hours)
} }
} }
@@ -78,7 +78,7 @@ impl SliceRentalService {
pub fn rent_slice_combination_with_deployment( pub fn rent_slice_combination_with_deployment(
&self, &self,
renter_email: &str, renter_email: &str,
farmer_email: &str, resource_provider_email: &str,
node_id: &str, node_id: &str,
combination_id: &str, combination_id: &str,
quantity: u32, quantity: u32,
@@ -89,7 +89,7 @@ impl SliceRentalService {
) -> Result<SliceRental, String> { ) -> Result<SliceRental, String> {
// First rent the slice combination // First rent the slice combination
let mut rental = self.rent_slice_combination( let mut rental = self.rent_slice_combination(
renter_email, farmer_email, node_id, combination_id, quantity, rental_duration_hours renter_email, resource_provider_email, node_id, combination_id, quantity, rental_duration_hours
)?; )?;
// Add deployment metadata to the rental // Add deployment metadata to the rental
@@ -133,21 +133,21 @@ impl SliceRentalService {
fn rent_with_file_lock( fn rent_with_file_lock(
&self, &self,
renter_email: &str, renter_email: &str,
farmer_email: &str, resource_provider_email: &str,
node_id: &str, node_id: &str,
combination_id: &str, combination_id: &str,
quantity: u32, quantity: u32,
rental_duration_hours: u32, rental_duration_hours: u32,
) -> Result<SliceRental, String> { ) -> Result<SliceRental, String> {
// Create lock file // Create lock file
let lock_file_path = format!("./user_data/.lock_{}_{}", farmer_email.replace("@", "_"), node_id); let lock_file_path = format!("./user_data/.lock_{}_{}", resource_provider_email.replace("@", "_"), node_id);
let _lock_file = OpenOptions::new() let _lock_file = OpenOptions::new()
.create(true) .create(true)
.write(true) .write(true)
.open(&lock_file_path) .open(&lock_file_path)
.map_err(|e| format!("Failed to create lock file: {}", e))?; .map_err(|e| format!("Failed to create lock file: {}", e))?;
let result = self.rent_without_lock(renter_email, farmer_email, node_id, combination_id, quantity, rental_duration_hours); let result = self.rent_without_lock(renter_email, resource_provider_email, node_id, combination_id, quantity, rental_duration_hours);
// Clean up lock file // Clean up lock file
let _ = std::fs::remove_file(&lock_file_path); let _ = std::fs::remove_file(&lock_file_path);
@@ -159,21 +159,21 @@ impl SliceRentalService {
fn rent_without_lock( fn rent_without_lock(
&self, &self,
renter_email: &str, renter_email: &str,
farmer_email: &str, resource_provider_email: &str,
node_id: &str, node_id: &str,
combination_id: &str, combination_id: &str,
quantity: u32, quantity: u32,
rental_duration_hours: u32, rental_duration_hours: u32,
) -> Result<SliceRental, String> { ) -> Result<SliceRental, String> {
// Load farmer data // Load resource_provider data
let mut farmer_data = UserPersistence::load_user_data(farmer_email) let mut resource_provider_data = UserPersistence::load_user_data(resource_provider_email)
.ok_or_else(|| "Farmer not found".to_string())?; .ok_or_else(|| "ResourceProvider not found".to_string())?;
// Find the node // Find the node
let node_index = farmer_data.nodes.iter().position(|n| n.id == node_id) let node_index = resource_provider_data.nodes.iter().position(|n| n.id == node_id)
.ok_or_else(|| "Node not found".to_string())?; .ok_or_else(|| "Node not found".to_string())?;
let node = &mut farmer_data.nodes[node_index]; let node = &mut resource_provider_data.nodes[node_index];
// Find the slice combination // Find the slice combination
let combination = node.available_combinations.iter() let combination = node.available_combinations.iter()
@@ -226,7 +226,7 @@ impl SliceRentalService {
self.slice_calculator.update_availability_after_rental( self.slice_calculator.update_availability_after_rental(
node, node,
total_base_slices_needed, total_base_slices_needed,
farmer_email resource_provider_email
)?; )?;
// Add allocation to node // Add allocation to node
@@ -237,7 +237,7 @@ impl SliceRentalService {
rental_id: rental_id.clone(), rental_id: rental_id.clone(),
slice_combination_id: combination_id.to_string(), slice_combination_id: combination_id.to_string(),
node_id: node_id.to_string(), node_id: node_id.to_string(),
farmer_email: farmer_email.to_string(), resource_provider_email: resource_provider_email.to_string(),
slice_allocation: allocation, slice_allocation: allocation,
total_cost, total_cost,
payment_status: PaymentStatus::Paid, payment_status: PaymentStatus::Paid,
@@ -260,12 +260,12 @@ impl SliceRentalService {
renter_data.wallet_balance_usd -= total_cost; renter_data.wallet_balance_usd -= total_cost;
renter_data.slice_rentals.push(slice_rental.clone()); renter_data.slice_rentals.push(slice_rental.clone());
// Add earnings to farmer // Add earnings to resource_provider
farmer_data.wallet_balance_usd += total_cost; resource_provider_data.wallet_balance_usd += total_cost;
// Save both user data // Save both user data
UserPersistence::save_user_data(&farmer_data) UserPersistence::save_user_data(&resource_provider_data)
.map_err(|e| format!("Failed to save farmer data: {}", e))?; .map_err(|e| format!("Failed to save resource_provider data: {}", e))?;
UserPersistence::save_user_data(&renter_data) UserPersistence::save_user_data(&renter_data)
.map_err(|e| format!("Failed to save renter data: {}", e))?; .map_err(|e| format!("Failed to save renter data: {}", e))?;
@@ -273,14 +273,14 @@ impl SliceRentalService {
} }
/// Release expired slice rentals /// Release expired slice rentals
pub fn release_expired_rentals(&self, farmer_email: &str) -> Result<u32, String> { pub fn release_expired_rentals(&self, resource_provider_email: &str) -> Result<u32, String> {
let mut farmer_data = UserPersistence::load_user_data(farmer_email) let mut resource_provider_data = UserPersistence::load_user_data(resource_provider_email)
.ok_or_else(|| "Farmer not found".to_string())?; .ok_or_else(|| "ResourceProvider not found".to_string())?;
let mut released_count = 0; let mut released_count = 0;
let now = Utc::now(); let now = Utc::now();
for node in &mut farmer_data.nodes { for node in &mut resource_provider_data.nodes {
let mut expired_allocations = Vec::new(); let mut expired_allocations = Vec::new();
// Find expired allocations // Find expired allocations
@@ -314,7 +314,7 @@ impl SliceRentalService {
self.slice_calculator.update_availability_after_release( self.slice_calculator.update_availability_after_release(
node, node,
base_slices_used, base_slices_used,
farmer_email resource_provider_email
)?; )?;
released_count += 1; released_count += 1;
@@ -322,20 +322,20 @@ impl SliceRentalService {
} }
if released_count > 0 { if released_count > 0 {
UserPersistence::save_user_data(&farmer_data) UserPersistence::save_user_data(&resource_provider_data)
.map_err(|e| format!("Failed to save farmer data: {}", e))?; .map_err(|e| format!("Failed to save resource_provider data: {}", e))?;
} }
Ok(released_count) Ok(released_count)
} }
/// Get slice rental statistics for a farmer /// Get slice rental statistics for a resource_provider
pub fn get_farmer_slice_statistics(&self, farmer_email: &str) -> SliceRentalStatistics { pub fn get_resource_provider_slice_statistics(&self, resource_provider_email: &str) -> SliceRentalStatistics {
if let Some(farmer_data) = UserPersistence::load_user_data(farmer_email) { if let Some(resource_provider_data) = UserPersistence::load_user_data(resource_provider_email) {
let mut stats = SliceRentalStatistics::default(); let mut stats = SliceRentalStatistics::default();
for node in &farmer_data.nodes { for node in &resource_provider_data.nodes {
stats.total_nodes += 1; stats.total_nodes += 1;
stats.total_base_slices += node.total_base_slices as u32; stats.total_base_slices += node.total_base_slices as u32;
stats.allocated_base_slices += node.allocated_base_slices as u32; stats.allocated_base_slices += node.allocated_base_slices as u32;
@@ -379,7 +379,7 @@ impl SliceRentalService {
} }
} }
/// Statistics for farmer slice rentals /// Statistics for resource_provider slice rentals
#[derive(Debug, Clone, Serialize, Deserialize, Default)] #[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct SliceRentalStatistics { pub struct SliceRentalStatistics {
pub total_nodes: u32, pub total_nodes: u32,

View File

@@ -46,10 +46,10 @@ pub struct UserPersistentData {
pub deleted: Option<bool>, pub deleted: Option<bool>,
pub deleted_at: Option<String>, pub deleted_at: Option<String>,
pub deletion_reason: Option<String>, pub deletion_reason: Option<String>,
// Farmer-specific data // ResourceProvider-specific data
pub nodes: Vec<crate::models::user::FarmNode>, pub nodes: Vec<crate::models::user::FarmNode>,
pub farmer_earnings: Vec<crate::models::user::EarningsRecord>, pub resource_provider_earnings: Vec<crate::models::user::EarningsRecord>,
pub farmer_settings: Option<crate::models::user::FarmerSettings>, pub resource_provider_settings: Option<crate::models::user::FarmerSettings>,
#[serde(default)] #[serde(default)]
pub slice_products: Vec<crate::models::product::Product>, pub slice_products: Vec<crate::models::product::Product>,
// User activity tracking // User activity tracking
@@ -63,10 +63,10 @@ pub struct UserPersistentData {
#[serde(default)] #[serde(default)]
pub active_product_rentals: Vec<ProductRental>, pub active_product_rentals: Vec<ProductRental>,
#[serde(default)] #[serde(default)]
pub farmer_rental_earnings: Vec<crate::models::user::FarmerRentalEarning>, pub resource_provider_rental_earnings: Vec<crate::models::user::FarmerRentalEarning>,
#[serde(default)] #[serde(default)]
pub node_rentals: Vec<crate::models::user::NodeRental>, pub node_rentals: Vec<crate::models::user::NodeRental>,
// Node groups for farmer organization // Node groups for resource_provider organization
#[serde(default)] #[serde(default)]
pub node_groups: Vec<crate::models::user::NodeGroup>, pub node_groups: Vec<crate::models::user::NodeGroup>,
// NEW: Slice rental tracking for users // NEW: Slice rental tracking for users
@@ -142,15 +142,15 @@ impl Default for UserPersistentData {
deleted_at: None, deleted_at: None,
deletion_reason: None, deletion_reason: None,
nodes: Vec::new(), nodes: Vec::new(),
farmer_earnings: Vec::new(), resource_provider_earnings: Vec::new(),
farmer_settings: None, resource_provider_settings: None,
slice_products: Vec::new(), slice_products: Vec::new(),
user_activities: Vec::new(), user_activities: Vec::new(),
user_preferences: None, user_preferences: None,
usage_statistics: None, usage_statistics: None,
orders: Vec::new(), orders: Vec::new(),
active_product_rentals: Vec::new(), active_product_rentals: Vec::new(),
farmer_rental_earnings: Vec::new(), resource_provider_rental_earnings: Vec::new(),
node_rentals: Vec::new(), node_rentals: Vec::new(),
node_groups: Vec::new(), node_groups: Vec::new(),
slice_rentals: Vec::new(), slice_rentals: Vec::new(),
@@ -1306,19 +1306,19 @@ impl UserPersistence {
} }
} }
/// Get farmer earnings for a user /// Get resource_provider earnings for a user
pub fn get_farmer_earnings(user_email: &str) -> Vec<crate::models::user::EarningsRecord> { pub fn get_resource_provider_earnings(user_email: &str) -> Vec<crate::models::user::EarningsRecord> {
if let Some(data) = Self::load_user_data(user_email) { if let Some(data) = Self::load_user_data(user_email) {
data.farmer_earnings data.resource_provider_earnings
} else { } else {
Vec::default() Vec::default()
} }
} }
/// Get farmer settings for a user /// Get resource_provider settings for a user
pub fn get_farmer_settings(user_email: &str) -> Option<crate::models::user::FarmerSettings> { pub fn get_resource_provider_settings(user_email: &str) -> Option<crate::models::user::FarmerSettings> {
if let Some(data) = Self::load_user_data(user_email) { if let Some(data) = Self::load_user_data(user_email) {
data.farmer_settings data.resource_provider_settings
} else { } else {
None None
} }

View File

@@ -1,12 +1,12 @@
// Dashboard Farmer JavaScript // Dashboard ResourceProvider JavaScript
// Handles farmer dashboard functionality including automatic slice management, grid integration, and node management // Handles resource_provider dashboard functionality including automatic slice management, grid integration, and node management
if (window.farmerDashboardInitialized) { if (window.resourceProviderDashboardInitialized) {
console.debug('Farmer dashboard already initialized; skipping'); console.debug('ResourceProvider dashboard already initialized; skipping');
} else { } else {
window.farmerDashboardInitialized = true; window.resourceProviderDashboardInitialized = true;
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
console.log('🚜 Farmer Dashboard JavaScript loaded - Automatic Slice System'); console.log('🚜 ResourceProvider Dashboard JavaScript loaded - Automatic Slice System');
// Initialize dashboard // Initialize dashboard
initializeFarmerDashboard(); initializeFarmerDashboard();
@@ -762,7 +762,7 @@ function showNodeDetailsModal(node) {
function loadSliceStatistics() { function loadSliceStatistics() {
console.log('📊 Loading slice statistics'); console.log('📊 Loading slice statistics');
window.apiJson('/api/dashboard/farmer/slice-statistics') window.apiJson('/api/dashboard/resource_provider/slice-statistics')
.then(data => { .then(data => {
// apiJson returns unwrapped data; support either {statistics: {...}} or {...} // apiJson returns unwrapped data; support either {statistics: {...}} or {...}
const stats = (data && data.statistics) ? data.statistics : (data || {}); const stats = (data && data.statistics) ? data.statistics : (data || {});
@@ -1173,12 +1173,12 @@ function createSimpleIndividualPricingForms() {
} }
/** /**
* Initialize farmer dashboard functionality * Initialize resource_provider dashboard functionality
*/ */
function initializeFarmerDashboard() { function initializeFarmerDashboard() {
console.log('🚜 Initializing farmer dashboard'); console.log('🚜 Initializing resource_provider dashboard');
// Load farmer data // Load resource_provider data
loadFarmerData(); loadFarmerData();
// Load slice templates // Load slice templates
@@ -2911,12 +2911,12 @@ function resetSliceConfigurationForm() {
} }
/** /**
* Load farmer data from API * Load resource_provider data from API
*/ */
async function loadFarmerData() { async function loadFarmerData() {
try { try {
const data = await window.apiJson('/api/dashboard/farmer-data'); const data = await window.apiJson('/api/dashboard/resource_provider-data');
console.log('🚜 Loaded farmer data:', data); console.log('🚜 Loaded resource_provider data:', data);
// Load node groups as well // Load node groups as well
const groupsResult = await window.apiJson('/api/dashboard/node-groups'); const groupsResult = await window.apiJson('/api/dashboard/node-groups');
@@ -2924,8 +2924,8 @@ async function loadFarmerData() {
data.nodeGroups = nodeGroups; data.nodeGroups = nodeGroups;
console.log('🚜 Node groups loaded:', nodeGroups); console.log('🚜 Node groups loaded:', nodeGroups);
// Store farmer data globally for slice status checking // Store resource_provider data globally for slice status checking
window.farmerData = data; window.resourceProviderData = data;
// Update dashboard stats // Update dashboard stats
updateDashboardStats(data); updateDashboardStats(data);
@@ -2940,8 +2940,8 @@ async function loadFarmerData() {
loadSliceTemplates(); loadSliceTemplates();
} catch (error) { } catch (error) {
console.error('🚜 Error loading farmer data:', error); console.error('🚜 Error loading resource_provider data:', error);
showNotification('Failed to load farmer data', 'error'); showNotification('Failed to load resource_provider data', 'error');
} }
} }
@@ -3130,13 +3130,13 @@ function showSliceTemplatesError() {
* Returns 'Active' if at least one node is using this slice format, 'Available' otherwise * Returns 'Active' if at least one node is using this slice format, 'Available' otherwise
*/ */
function getSliceFormatStatus(sliceFormatId) { function getSliceFormatStatus(sliceFormatId) {
// Check if we have farmer data loaded // Check if we have resource_provider data loaded
if (!window.farmerData || !window.farmerData.nodes) { if (!window.resourceProviderData || !window.resourceProviderData.nodes) {
return 'Available'; // Default to Available if no data return 'Available'; // Default to Available if no data
} }
// Check if any node has this slice format in their slice_formats array // Check if any node has this slice format in their slice_formats array
const isUsedByAnyNode = window.farmerData.nodes.some(node => { const isUsedByAnyNode = window.resourceProviderData.nodes.some(node => {
return node.slice_formats && return node.slice_formats &&
Array.isArray(node.slice_formats) && Array.isArray(node.slice_formats) &&
node.slice_formats.includes(sliceFormatId); node.slice_formats.includes(sliceFormatId);
@@ -3507,8 +3507,8 @@ function updateNodesTable(nodes) {
// Group info with enhanced display - get actual group name from loaded groups // Group info with enhanced display - get actual group name from loaded groups
let groupInfo = '<span class="badge bg-secondary">Single</span>'; let groupInfo = '<span class="badge bg-secondary">Single</span>';
if (node.node_group_id && window.farmerData && window.farmerData.nodeGroups) { if (node.node_group_id && window.resourceProviderData && window.resourceProviderData.nodeGroups) {
const group = window.farmerData.nodeGroups.find(g => g.id === node.node_group_id); const group = window.resourceProviderData.nodeGroups.find(g => g.id === node.node_group_id);
if (group) { if (group) {
groupInfo = `<span class="badge bg-info">${group.name}</span>`; groupInfo = `<span class="badge bg-info">${group.name}</span>`;
} }
@@ -3966,7 +3966,7 @@ async function addGridNodes() {
// Reset form // Reset form
resetAddNodeForm(); resetAddNodeForm();
// Reload farmer data and node groups with small delay for backend processing // Reload resource_provider data and node groups with small delay for backend processing
setTimeout(async () => { setTimeout(async () => {
await loadFarmerData(); await loadFarmerData();
await loadNodeGroups(); // FARMER FIX: Refresh node groups table after adding new nodes await loadNodeGroups(); // FARMER FIX: Refresh node groups table after adding new nodes
@@ -4155,7 +4155,7 @@ async function confirmNodeDeletion() {
deleteModal.hide(); deleteModal.hide();
} }
// Reload farmer data and node groups with small delay for backend processing // Reload resource_provider data and node groups with small delay for backend processing
setTimeout(() => { setTimeout(() => {
loadFarmerData(); loadFarmerData();
loadNodeGroups(); // FARMER FIX: Refresh node groups table after node deletion loadNodeGroups(); // FARMER FIX: Refresh node groups table after node deletion
@@ -4925,7 +4925,7 @@ async function saveNodeConfiguration() {
modal.hide(); modal.hide();
} }
// Reload farmer data and node groups with small delay for backend processing // Reload resource_provider data and node groups with small delay for backend processing
setTimeout(async () => { setTimeout(async () => {
await loadFarmerData(); await loadFarmerData();
await loadNodeGroups(); // FARMER FIX: Refresh node groups table after node configuration changes await loadNodeGroups(); // FARMER FIX: Refresh node groups table after node configuration changes
@@ -5627,7 +5627,7 @@ function createSliceFormatCard(format, type) {
</div> </div>
`; `;
} else { } else {
// Use persistent data from farmer settings (price_per_hour) instead of hardcoded fallback // Use persistent data from resource_provider settings (price_per_hour) instead of hardcoded fallback
const hourlyPrice = format.price_per_hour || format.price || 10; // Default to 10 if no price found const hourlyPrice = format.price_per_hour || format.price || 10; // Default to 10 if no price found
pricingDisplay = `<small class="text-muted">${hourlyPrice} ${currency}/hour</small>`; pricingDisplay = `<small class="text-muted">${hourlyPrice} ${currency}/hour</small>`;
} }
@@ -5706,15 +5706,15 @@ function getSliceFormatDisplayName(formatId, formatName) {
return formatName; return formatName;
} }
// Look up custom slice products from loaded farmer data // Look up custom slice products from loaded resource_provider data
if (window.farmerData && window.farmerData.slice_products) { if (window.resourceProviderData && window.resourceProviderData.slice_products) {
const sliceProduct = window.farmerData.slice_products.find(product => product.id === formatId); const sliceProduct = window.resourceProviderData.slice_products.find(product => product.id === formatId);
if (sliceProduct && sliceProduct.name) { if (sliceProduct && sliceProduct.name) {
return sliceProduct.name; return sliceProduct.name;
} }
} }
// Look up from globally loaded slice products if farmer data not available // Look up from globally loaded slice products if resource_provider data not available
if (window.loadedSliceProducts) { if (window.loadedSliceProducts) {
const sliceProduct = window.loadedSliceProducts.find(product => product.id === formatId); const sliceProduct = window.loadedSliceProducts.find(product => product.id === formatId);
if (sliceProduct && sliceProduct.name) { if (sliceProduct && sliceProduct.name) {
@@ -7189,7 +7189,7 @@ function clearValidationError(input) {
*/ */
async function updateStakingDisplay() { async function updateStakingDisplay() {
try { try {
const data = await window.apiJson('/api/dashboard/farmer-data'); const data = await window.apiJson('/api/dashboard/resource_provider-data');
const nodes = data.nodes || []; const nodes = data.nodes || [];
// Calculate staking statistics // Calculate staking statistics
@@ -7523,7 +7523,7 @@ function showStakeNodeModal(nodeId) {
console.log('🛡️ Showing stake modal for node:', nodeId); console.log('🛡️ Showing stake modal for node:', nodeId);
// Find the node data // Find the node data
const node = window.farmerData?.nodes?.find(n => n.id === nodeId); const node = window.resourceProviderData?.nodes?.find(n => n.id === nodeId);
if (!node) { if (!node) {
showNotification('Node not found', 'error'); showNotification('Node not found', 'error');
return; return;
@@ -7657,7 +7657,7 @@ async function stakeOnNode(nodeId, modal) {
showNotification(`Successfully staked ${stakeAmount} TFP on node`, 'success'); showNotification(`Successfully staked ${stakeAmount} TFP on node`, 'success');
modal.hide(); modal.hide();
// Refresh farmer data to show updated staking // Refresh resource_provider data to show updated staking
await loadFarmerData(); await loadFarmerData();
// Update wallet balance display // Update wallet balance display
@@ -7683,7 +7683,7 @@ async function unstakeFromNode(nodeId) {
console.log('🛡️ Unstaking TFP from node:', nodeId); console.log('🛡️ Unstaking TFP from node:', nodeId);
// Find the node data // Find the node data
const node = window.farmerData?.nodes?.find(n => n.id === nodeId); const node = window.resourceProviderData?.nodes?.find(n => n.id === nodeId);
if (!node || !node.staking_options || !node.staking_options.staking_enabled) { if (!node || !node.staking_options || !node.staking_options.staking_enabled) {
showNotification('Node is not currently staked', 'error'); showNotification('Node is not currently staked', 'error');
return; return;
@@ -7712,7 +7712,7 @@ async function unstakeFromNode(nodeId) {
const returnedAmount = result?.returned_amount || stakedAmount; const returnedAmount = result?.returned_amount || stakedAmount;
showNotification(`Successfully unstaked ${returnedAmount} TFP from node`, 'success'); showNotification(`Successfully unstaked ${returnedAmount} TFP from node`, 'success');
// Refresh farmer data to show updated staking // Refresh resource_provider data to show updated staking
await loadFarmerData(); await loadFarmerData();
// Update wallet balance display // Update wallet balance display
@@ -7731,7 +7731,7 @@ function showUpdateStakeModal(nodeId) {
console.log('🛡️ Showing update stake modal for node:', nodeId); console.log('🛡️ Showing update stake modal for node:', nodeId);
// Find the node data // Find the node data
const node = window.farmerData?.nodes?.find(n => n.id === nodeId); const node = window.resourceProviderData?.nodes?.find(n => n.id === nodeId);
if (!node || !node.staking_options || !node.staking_options.staking_enabled) { if (!node || !node.staking_options || !node.staking_options.staking_enabled) {
showNotification('Node is not currently staked', 'error'); showNotification('Node is not currently staked', 'error');
return; return;
@@ -7847,7 +7847,7 @@ async function updateNodeStaking(nodeId, modal) {
showNotification(`Successfully updated staking to ${newStakeAmount} TFP`, 'success'); showNotification(`Successfully updated staking to ${newStakeAmount} TFP`, 'success');
modal.hide(); modal.hide();
// Refresh farmer data to show updated staking // Refresh resource_provider data to show updated staking
await loadFarmerData(); await loadFarmerData();
// Update wallet balance display // Update wallet balance display

View File

@@ -31,7 +31,7 @@ class DemoWorkflow {
action: () => this.demoAppDeployment() action: () => this.demoAppDeployment()
}, },
{ {
title: "Farmer: Node Management", title: "ResourceProvider: Node Management",
description: "Manage your farming nodes and monitor capacity.", description: "Manage your farming nodes and monitor capacity.",
action: () => this.demoNodeManagement() action: () => this.demoNodeManagement()
}, },
@@ -265,7 +265,7 @@ class DemoWorkflow {
} }
demoNodeManagement() { demoNodeManagement() {
showNotification('Demo: Simulating farmer node management...', 'info'); showNotification('Demo: Simulating resource_provider node management...', 'info');
setTimeout(() => { setTimeout(() => {
// Simulate node status change // Simulate node status change

View File

@@ -431,7 +431,7 @@ class MarketplaceIntegration {
if (!sessionStorage.getItem('marketplaceSlices')) { if (!sessionStorage.getItem('marketplaceSlices')) {
// Get real users from user database // Get real users from user database
const alexUser = userDB.getUser('user-001'); // Alex Thompson - Farmer const alexUser = userDB.getUser('user-001'); // Alex Thompson - ResourceProvider
const mockSlices = [ const mockSlices = [
{ {

View File

@@ -12,11 +12,11 @@ class UserDatabase {
const mockUsers = [ const mockUsers = [
{ {
id: 'user-001', id: 'user-001',
username: 'sara_farmer', username: 'sara_resource_provider',
display_name: 'Sara Nicks', display_name: 'Sara Nicks',
email: 'user1@example.com', email: 'user1@example.com',
password: 'password', password: 'password',
role: 'farmer', role: 'resource_provider',
location: 'Amsterdam, Netherlands', location: 'Amsterdam, Netherlands',
joined_date: '2024-01-15', joined_date: '2024-01-15',
reputation: 4.8, reputation: 4.8,
@@ -84,7 +84,7 @@ class UserDatabase {
display_name: 'Jordan Mitchell', display_name: 'Jordan Mitchell',
email: 'user5@example.com', email: 'user5@example.com',
password: 'password', password: 'password',
role: 'multi', // Can be farmer, app_provider, service_provider, user role: 'multi', // Can be resource_provider, app_provider, service_provider, user
location: 'Toronto, Canada', location: 'Toronto, Canada',
joined_date: new Date().toISOString().split('T')[0], joined_date: new Date().toISOString().split('T')[0],
reputation: 5.0, reputation: 5.0,

View File

@@ -14,7 +14,7 @@ impl DataValidator {
if let Value::Object(ref mut obj) = value { if let Value::Object(ref mut obj) = value {
Self::repair_user_activities(obj)?; Self::repair_user_activities(obj)?;
Self::repair_farmer_settings(obj)?; Self::repair_resource_provider_settings(obj)?;
Self::ensure_required_fields(obj)?; Self::ensure_required_fields(obj)?;
} }
@@ -47,20 +47,20 @@ impl DataValidator {
Ok(()) Ok(())
} }
/// Repairs farmer settings to include all required fields /// Repairs resource_provider settings to include all required fields
fn repair_farmer_settings(obj: &mut Map<String, Value>) -> Result<(), String> { fn repair_resource_provider_settings(obj: &mut Map<String, Value>) -> Result<(), String> {
if let Some(Value::Object(ref mut farmer_settings)) = obj.get_mut("farmer_settings") { if let Some(Value::Object(ref mut resource_provider_settings)) = obj.get_mut("resource_provider_settings") {
// Ensure minimum_deployment_duration exists // Ensure minimum_deployment_duration exists
if !farmer_settings.contains_key("minimum_deployment_duration") { if !resource_provider_settings.contains_key("minimum_deployment_duration") {
farmer_settings.insert( resource_provider_settings.insert(
"minimum_deployment_duration".to_string(), "minimum_deployment_duration".to_string(),
Value::Number(serde_json::Number::from(24)) Value::Number(serde_json::Number::from(24))
); );
} }
// Ensure preferred_regions exists // Ensure preferred_regions exists
if !farmer_settings.contains_key("preferred_regions") { if !resource_provider_settings.contains_key("preferred_regions") {
farmer_settings.insert( resource_provider_settings.insert(
"preferred_regions".to_string(), "preferred_regions".to_string(),
Value::Array(vec![ Value::Array(vec![
Value::String("NA".to_string()), Value::String("NA".to_string()),
@@ -83,7 +83,7 @@ impl DataValidator {
("apps", Value::Array(vec![])), ("apps", Value::Array(vec![])),
("app_deployments", Value::Array(vec![])), ("app_deployments", Value::Array(vec![])),
("nodes", Value::Array(vec![])), ("nodes", Value::Array(vec![])),
("farmer_earnings", Value::Array(vec![])), ("resource_provider_earnings", Value::Array(vec![])),
("user_activities", Value::Array(vec![])), ("user_activities", Value::Array(vec![])),
("pool_positions", Value::Object(Map::new())), ("pool_positions", Value::Object(Map::new())),
]; ];

View File

@@ -78,7 +78,7 @@
</a> </a>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
<a href="/dashboard/farmer" class="btn btn-outline-info w-100 mb-2"> <a href="/dashboard/resource_provider" class="btn btn-outline-info w-100 mb-2">
<i class="bi bi-hdd-rack me-2"></i> Add a Mycelium Node <i class="bi bi-hdd-rack me-2"></i> Add a Mycelium Node
</a> </a>
</div> </div>
@@ -117,11 +117,11 @@
</div> </div>
<div class="col-md-6 col-lg-3 mb-4"> <div class="col-md-6 col-lg-3 mb-4">
<div class="dashboard-card"> <div class="dashboard-card">
<span class="badge bg-success badge-role">FARMER</span> <span class="badge bg-success badge-role">RESOURCE PROVIDER</span>
<h4>Farmer Dashboard</h4> <h4>Resource Provider Dashboard</h4>
<p>Manage your nodes, create slices, set pricing, and track earnings.</p> <p>Manage your nodes, create slices, set pricing, and track earnings.</p>
<div class="d-grid"> <div class="d-grid">
<a href="/dashboard/farmer" class="btn btn-sm btn-outline-success">Access Farmer Dashboard</a> <a href="/dashboard/resource_provider" class="btn btn-sm btn-outline-success">Access Resource Provider Dashboard</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -28,9 +28,9 @@
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link {% if active_section == 'farmer' %}active{% endif %}" href="/dashboard/farmer"> <a class="nav-link {% if active_section == 'resource_provider' %}active{% endif %}" href="/dashboard/resource_provider">
<i class="bi bi-hdd-rack me-1"></i> <i class="bi bi-hdd-rack me-1"></i>
Farmer Resource Provider
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">

View File

@@ -1,10 +1,10 @@
{% extends "dashboard/layout.html" %} {% extends "dashboard/layout.html" %}
{% block title %}ThreeFold Dashboard - Farmer{% endblock %} {% block title %}ThreeFold Dashboard - Resource Provider{% endblock %}
{% block dashboard_content %} {% block dashboard_content %}
<div class="my-4"> <div class="my-4">
<h1>Farmer Dashboard</h1> <h1>Resource Provider Dashboard</h1>
<p class="lead">Manage your nodes, configure slices, and monitor earnings</p> <p class="lead">Manage your nodes, configure slices, and monitor earnings</p>
<!-- Status Summary --> <!-- Status Summary -->
@@ -13,8 +13,8 @@
<div class="stats-card success"> <div class="stats-card success">
<h5 class="card-title">Active Nodes</h5> <h5 class="card-title">Active Nodes</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="active-nodes-count">{{ farmer_stats.online_nodes }}</h2> <h2 class="mb-0" id="active-nodes-count">{{ resource provider_stats.online_nodes }}</h2>
<small class="text-muted">of {{ farmer_stats.total_nodes }} total</small> <small class="text-muted">of {{ resource provider_stats.total_nodes }} total</small>
</div> </div>
</div> </div>
</div> </div>
@@ -22,8 +22,8 @@
<div class="stats-card primary"> <div class="stats-card primary">
<h5 class="card-title">Allocated Slices</h5> <h5 class="card-title">Allocated Slices</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="active-slices-count">{{ farmer_stats.allocated_base_slices }}</h2> <h2 class="mb-0" id="active-slices-count">{{ resource provider_stats.allocated_base_slices }}</h2>
<small class="text-muted">of {{ farmer_stats.total_base_slices }} total</small> <small class="text-muted">of {{ resource provider_stats.total_base_slices }} total</small>
</div> </div>
</div> </div>
</div> </div>
@@ -31,7 +31,7 @@
<div class="stats-card warning"> <div class="stats-card warning">
<h5 class="card-title">Monthly Earnings</h5> <h5 class="card-title">Monthly Earnings</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="monthly-earnings">{{ farmer_stats.monthly_earnings }}</h2> <h2 class="mb-0" id="monthly-earnings">{{ resource provider_stats.monthly_earnings }}</h2>
<small class="text-muted">$/month</small> <small class="text-muted">$/month</small>
</div> </div>
</div> </div>
@@ -187,7 +187,7 @@
<div class="stats-card primary"> <div class="stats-card primary">
<h6 class="card-title">Total Base Slices</h6> <h6 class="card-title">Total Base Slices</h6>
<div class="d-flex justify-content-between align-items-end"> <div class="d-flex justify-content-between align-items-end">
<h3 class="mb-0" id="total-base-slices">{{ farmer_stats.total_base_slices }}</h3> <h3 class="mb-0" id="total-base-slices">{{ resource provider_stats.total_base_slices }}</h3>
<small class="text-muted">Available</small> <small class="text-muted">Available</small>
</div> </div>
</div> </div>
@@ -196,7 +196,7 @@
<div class="stats-card success"> <div class="stats-card success">
<h6 class="card-title">Allocated Slices</h6> <h6 class="card-title">Allocated Slices</h6>
<div class="d-flex justify-content-between align-items-end"> <div class="d-flex justify-content-between align-items-end">
<h3 class="mb-0" id="allocated-base-slices">{{ farmer_stats.allocated_base_slices }}</h3> <h3 class="mb-0" id="allocated-base-slices">{{ resource provider_stats.allocated_base_slices }}</h3>
<small class="text-muted">Rented</small> <small class="text-muted">Rented</small>
</div> </div>
</div> </div>
@@ -205,7 +205,7 @@
<div class="stats-card info"> <div class="stats-card info">
<h6 class="card-title">Available Slices</h6> <h6 class="card-title">Available Slices</h6>
<div class="d-flex justify-content-between align-items-end"> <div class="d-flex justify-content-between align-items-end">
<h3 class="mb-0" id="available-base-slices">{{ farmer_stats.available_base_slices }}</h3> <h3 class="mb-0" id="available-base-slices">{{ resource provider_stats.available_base_slices }}</h3>
<small class="text-muted">For Rent</small> <small class="text-muted">For Rent</small>
</div> </div>
</div> </div>
@@ -214,7 +214,7 @@
<div class="stats-card warning"> <div class="stats-card warning">
<h6 class="card-title">Utilization</h6> <h6 class="card-title">Utilization</h6>
<div class="d-flex justify-content-between align-items-end"> <div class="d-flex justify-content-between align-items-end">
<h3 class="mb-0" id="slice-utilization">{{ farmer_stats.slice_utilization_percentage }}%</h3> <h3 class="mb-0" id="slice-utilization">{{ resource provider_stats.slice_utilization_percentage }}%</h3>
<small class="text-muted">Capacity</small> <small class="text-muted">Capacity</small>
</div> </div>
</div> </div>
@@ -238,8 +238,8 @@
</tr> </tr>
</thead> </thead>
<tbody id="node-slices-table"> <tbody id="node-slices-table">
{% if farmer_nodes %} {% if resource provider_nodes %}
{% for node in farmer_nodes %} {% for node in resource provider_nodes %}
<tr> <tr>
<td> <td>
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
@@ -396,8 +396,8 @@
{{ super() }} {{ super() }}
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.1/dist/chart.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.1/dist/chart.min.js"></script>
<!-- Load farmer dashboard JavaScript --> <!-- Load resource provider dashboard JavaScript -->
<script src="/static/js/dashboard-farmer.js"></script> <script src="/static/js/dashboard-resource_provider.js"></script>
<style> <style>
/* Ensure charts have consistent sizes */ /* Ensure charts have consistent sizes */

View File

@@ -55,7 +55,7 @@
<div class="display-4 mb-3 text-success"> <div class="display-4 mb-3 text-success">
<i class="bi bi-hdd-rack"></i> <i class="bi bi-hdd-rack"></i>
</div> </div>
<h5>As a Farmer</h5> <h5>As a Resource Provider</h5>
<p>Manage nodes, configure slices, set pricing</p> <p>Manage nodes, configure slices, set pricing</p>
</div> </div>
</div> </div>

View File

@@ -341,7 +341,7 @@
<div class="card h-100"> <div class="card h-100">
<div class="card-body"> <div class="card-body">
<h5 class="card-title"><i class="bi bi-people me-2 text-success"></i>Community Building</h5> <h5 class="card-title"><i class="bi bi-people me-2 text-success"></i>Community Building</h5>
<p class="card-text">Connects hardware providers with potential farmers</p> <p class="card-text">Connects hardware providers with potential resource providers</p>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -78,7 +78,7 @@
<div class="col-md-6"> <div class="col-md-6">
<div class="card h-100"> <div class="card h-100">
<div class="card-body"> <div class="card-body">
<h5 class="card-title"><i class="bi bi-hdd-rack me-2"></i>Farmers</h5> <h5 class="card-title"><i class="bi bi-hdd-rack me-2"></i>Resource Providers</h5>
<p class="card-text">Contribute compute capacity to the ThreeFold Grid and earn through the platform's ecosystem.</p> <p class="card-text">Contribute compute capacity to the ThreeFold Grid and earn through the platform's ecosystem.</p>
<a href="/docs" class="btn btn-outline-primary">Learn More</a> <a href="/docs" class="btn btn-outline-primary">Learn More</a>
</div> </div>

View File

@@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Farmers Terms and Conditions - Project Mycelium{% endblock %} {% block title %}Resource Providers Terms and Conditions - Project Mycelium{% endblock %}
{% block content %} {% block content %}
<div class="container my-5"> <div class="container my-5">
@@ -9,25 +9,25 @@
<nav aria-label="breadcrumb"> <nav aria-label="breadcrumb">
<ol class="breadcrumb"> <ol class="breadcrumb">
<li class="breadcrumb-item"><a href="/terms">Terms and Conditions</a></li> <li class="breadcrumb-item"><a href="/terms">Terms and Conditions</a></li>
<li class="breadcrumb-item active" aria-current="page">Farmers</li> <li class="breadcrumb-item active" aria-current="page">Resource Providers</li>
</ol> </ol>
</nav> </nav>
<div class="d-flex align-items-center mb-4"> <div class="d-flex align-items-center mb-4">
<i class="bi bi-hdd-rack fs-1 me-3 text-primary"></i> <i class="bi bi-hdd-rack fs-1 me-3 text-primary"></i>
<h1>Farmers Terms and Conditions</h1> <h1>Resource Providers Terms and Conditions</h1>
</div> </div>
<p class="lead mb-4">Last updated: May 22, 2025</p> <p class="lead mb-4">Last updated: May 22, 2025</p>
<div class="alert alert-info"> <div class="alert alert-info">
<p class="mb-0">These terms specifically apply to Farmers (Resource Providers) on the Project Mycelium who contribute capacity to the Mycelium Grid.</p> <p class="mb-0">These terms specifically apply to Resource Providers (Resource Providers) on the Project Mycelium who contribute capacity to the Mycelium Grid.</p>
</div> </div>
<h2>1. Definition of a Farmer</h2> <h2>1. Definition of a Resource Provider</h2>
<p>A "Farmer" refers to any individual or entity that connects hardware resources to the Mycelium Grid, including but not limited to compute nodes (Mycelium Nodes), storage capacity, network infrastructure, or other compatible devices that contribute to the Mycelium Grid's capacity.</p> <p>A "Resource Provider" refers to any individual or entity that connects hardware resources to the Mycelium Grid, including but not limited to compute nodes (Mycelium Nodes), storage capacity, network infrastructure, or other compatible devices that contribute to the Mycelium Grid's capacity.</p>
<h2>2. Farmer Responsibilities</h2> <h2>2. Resource Provider Responsibilities</h2>
<p>As a Farmer on the Project Mycelium, you agree to:</p> <p>As a Resource Provider on the Project Mycelium, you agree to:</p>
<ul> <ul>
<li>Maintain your connected hardware in good working condition with adequate internet connectivity</li> <li>Maintain your connected hardware in good working condition with adequate internet connectivity</li>
<li>Ensure your hardware meets the minimum technical requirements specified in the Farming documentation</li> <li>Ensure your hardware meets the minimum technical requirements specified in the Farming documentation</li>
@@ -37,7 +37,7 @@
</ul> </ul>
<h2>3. Reputation System and Staking</h2> <h2>3. Reputation System and Staking</h2>
<p>The Project Mycelium employs a reputation system that affects farmer visibility and rewards:</p> <p>The Project Mycelium employs a reputation system that affects resource provider visibility and rewards:</p>
<ul> <ul>
<li>Your reputation score is calculated based on multiple factors including uptime, staked Credits, and performance metrics</li> <li>Your reputation score is calculated based on multiple factors including uptime, staked Credits, and performance metrics</li>
<li>Staking Credits increases your reputation score and may qualify you for additional benefits</li> <li>Staking Credits increases your reputation score and may qualify you for additional benefits</li>
@@ -48,10 +48,10 @@
<h2>4. Rewards and Credits</h2> <h2>4. Rewards and Credits</h2>
<p>Compensation for resource contribution is governed by the following principles:</p> <p>Compensation for resource contribution is governed by the following principles:</p>
<ul> <ul>
<li>Farmers receive USD Credits based on the resources utilized from their contributed capacity</li> <li>Resource Providers receive USD Credits based on the resources utilized from their contributed capacity</li>
<li>Credits have a fixed value of 1.0 USD per Credit</li> <li>Credits have a fixed value of 1.0 USD per Credit</li>
<li>Earned Credits can be exchanged for fiat currencies or other supported tokens through the available liquidity pools</li> <li>Earned Credits can be exchanged for fiat currencies or other supported tokens through the available liquidity pools</li>
<li>Payment schedules and minimum thresholds are detailed in the Farmer dashboard</li> <li>Payment schedules and minimum thresholds are detailed in the Resource Provider dashboard</li>
</ul> </ul>
<h2>5. Hardware and Capacity</h2> <h2>5. Hardware and Capacity</h2>
@@ -72,8 +72,8 @@
<li>Slashing penalties may include reputation reduction, temporary suspension, or in severe cases, permanent removal from the marketplace</li> <li>Slashing penalties may include reputation reduction, temporary suspension, or in severe cases, permanent removal from the marketplace</li>
</ul> </ul>
<h2>7. Termination of Farmer Status</h2> <h2>7. Termination of Resource Provider Status</h2>
<p>You may cease being a Farmer by:</p> <p>You may cease being a Resource Provider by:</p>
<ul> <ul>
<li>Disconnecting your hardware from the Mycelium Grid</li> <li>Disconnecting your hardware from the Mycelium Grid</li>
<li>Providing notice through your dashboard at least 30 days prior to complete disconnection</li> <li>Providing notice through your dashboard at least 30 days prior to complete disconnection</li>
@@ -81,7 +81,7 @@
</ul> </ul>
<h2>8. Liability Limitation</h2> <h2>8. Liability Limitation</h2>
<p>As a Farmer, you acknowledge that:</p> <p>As a Resource Provider, you acknowledge that:</p>
<ul> <ul>
<li>ThreeFold is not responsible for any damage to your hardware resulting from normal operation</li> <li>ThreeFold is not responsible for any damage to your hardware resulting from normal operation</li>
<li>ThreeFold does not guarantee minimum income or utilization rates for your contributed capacity</li> <li>ThreeFold does not guarantee minimum income or utilization rates for your contributed capacity</li>
@@ -90,7 +90,7 @@
<div class="alert alert-warning mt-5"> <div class="alert alert-warning mt-5">
<h5 class="alert-heading">Important Note</h5> <h5 class="alert-heading">Important Note</h5>
<p class="mb-0">These Farmer-specific terms are in addition to the <a href="/terms">General Terms and Conditions</a> that apply to all users of the Project Mycelium. Please ensure you have reviewed both documents.</p> <p class="mb-0">These Resource Provider-specific terms are in addition to the <a href="/terms">General Terms and Conditions</a> that apply to all users of the Project Mycelium. Please ensure you have reviewed both documents.</p>
</div> </div>
<div class="text-center mt-5 mb-3"> <div class="text-center mt-5 mb-3">

View File

@@ -18,9 +18,9 @@
<div class="card h-100 shadow-sm"> <div class="card h-100 shadow-sm">
<div class="card-body text-center"> <div class="card-body text-center">
<i class="bi bi-hdd-rack fs-1 mb-3 text-primary"></i> <i class="bi bi-hdd-rack fs-1 mb-3 text-primary"></i>
<h5 class="card-title">Farmers</h5> <h5 class="card-title">Resource Providers</h5>
<p class="card-text">Resource Providers contributing capacity to the ThreeFold Grid</p> <p class="card-text">Resource Providers contributing capacity to the ThreeFold Grid</p>
<a href="/terms/farmers" class="btn btn-outline-primary mt-3">View Terms</a> <a href="/terms/resource providers" class="btn btn-outline-primary mt-3">View Terms</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -129,8 +129,8 @@
</td> </td>
<td> <td>
<div class="provider-name"> <div class="provider-name">
{% if product_data.product.attributes.farmer_email %} {% if product_data.product.attributes.resource provider_email %}
{{ product_data.product.attributes.farmer_email.value | truncate(length=15) }} {{ product_data.product.attributes.resource provider_email.value | truncate(length=15) }}
{% else %} {% else %}
{% if product_data.product.provider %}{{ product_data.product.provider }}{% else %}Unknown{% endif %} {% if product_data.product.provider %}{{ product_data.product.provider }}{% else %}Unknown{% endif %}
{% endif %} {% endif %}

View File

@@ -17,7 +17,7 @@
<h5 class="alert-heading">What are Mycelium Nodes?</h5> <h5 class="alert-heading">What are Mycelium Nodes?</h5>
<p>Mycelium Nodes are the physical hardware units that make up the Mycelium Grid. These certified servers provide compute, storage, and network capacity to the decentralized internet infrastructure.</p> <p>Mycelium Nodes are the physical hardware units that make up the Mycelium Grid. These certified servers provide compute, storage, and network capacity to the decentralized internet infrastructure.</p>
<hr> <hr>
<p class="mb-0">By purchasing a Mycelium Node, you become a farmer in the Mycelium ecosystem, earning MC rewards while contributing to the decentralized internet.</p> <p class="mb-0">By purchasing a Mycelium Node, you become a resource provider in the Mycelium ecosystem, earning MC rewards while contributing to the decentralized internet.</p>
</div> </div>
</div> </div>
</div> </div>
@@ -302,7 +302,7 @@
<div class="col-12"> <div class="col-12">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<h3 class="card-title">Become a Mycelium Farmer</h3> <h3 class="card-title">Become a Mycelium Resource Provider</h3>
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<h5>1. Purchase Your Mycelium Node</h5> <h5>1. Purchase Your Mycelium Node</h5>
@@ -322,7 +322,7 @@
<div class="alert alert-info mt-3"> <div class="alert alert-info mt-3">
<i class="bi bi-info-circle me-2"></i> <i class="bi bi-info-circle me-2"></i>
<strong>ROI Potential:</strong> Mycelium Node farmers typically see return on investment within 2-4 years, depending on grid utilization and MC price. <strong>ROI Potential:</strong> Mycelium Node resource providers typically see return on investment within 2-4 years, depending on grid utilization and MC price.
</div> </div>
</div> </div>
</div> </div>

View File

@@ -24,7 +24,7 @@
<strong>Node:</strong> {{ slice.node_id }} <strong>Node:</strong> {{ slice.node_id }}
</div> </div>
<div class="mb-3"> <div class="mb-3">
<strong>Farmer:</strong> {{ slice.farmer_email }} <strong>Resource Provider:</strong> {{ slice.resource provider_email }}
</div> </div>
<div class="mb-3"> <div class="mb-3">
<strong>Specifications:</strong> <strong>Specifications:</strong>
@@ -54,7 +54,7 @@
<div class="card-body"> <div class="card-body">
<form id="sliceRentalForm" method="POST" action="/marketplace/slice/rent"> <form id="sliceRentalForm" method="POST" action="/marketplace/slice/rent">
<!-- Hidden fields --> <!-- Hidden fields -->
<input type="hidden" name="farmer_email" value="{{ farmer_email }}"> <input type="hidden" name="resource provider_email" value="{{ resource provider_email }}">
<input type="hidden" name="node_id" value="{{ node_id }}"> <input type="hidden" name="node_id" value="{{ node_id }}">
<input type="hidden" name="combination_id" value="{{ combination_id }}"> <input type="hidden" name="combination_id" value="{{ combination_id }}">