Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@

# Rust
/backend/target/
/sdk/rust/target/
**/*.rs.bk
Cargo.lock

# Node.js
/frontend/node_modules/
/frontend/.next/
/frontend/out/
/frontend/build/
.env
.env.local

# IDEs
.vscode/
.idea/

# Rust build artifacts
backend/target/
**/target/
Expand Down Expand Up @@ -25,10 +44,14 @@ frontend/.env.local
*.swo
*~


# OS
.DS_Store
Thumbs.db


# Others

# Logs
*.log
npm-debug.log*
Expand All @@ -41,6 +64,7 @@ coverage/

# Temporary files
smart-contract/contracts/src/simple_test.rs

smart-contract/contracts/test_snapshots/
issue.md
checks.md
Expand Down
3 changes: 2 additions & 1 deletion backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ thiserror = "1.0"
anyhow = "1.0"
config = "0.14"
async-trait = "0.1"
reqwest = { version = "0.11", features = ["json"] }
tokio-retry = "0.3"
# Stellar/Soroban dependencies
soroban-sdk = "21.0"
# OpenAPI documentation
Expand All @@ -30,5 +32,4 @@ utoipa-swagger-ui = { version = "6.0", features = ["axum"] }

[dev-dependencies]
tower-test = "0.4"
reqwest = { version = "0.11", features = ["json"] }
testcontainers = "0.15"
47 changes: 47 additions & 0 deletions backend/migrations/20240103000000_add_resilience_tables.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""-- Create Disruption Predictions Table
CREATE TABLE disruption_predictions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
product_id VARCHAR(255) NOT NULL,
predicted_at TIMESTAMPTZ NOT NULL,
probability FLOAT NOT NULL,
impact_level VARCHAR(50) NOT NULL,
details JSONB NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Create Supplier Risks Table
CREATE TABLE supplier_risks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
supplier_name VARCHAR(255) NOT NULL,
risk_score FLOAT NOT NULL,
risk_factors JSONB NOT NULL,
last_assessed_at TIMESTAMPTZ NOT NULL
);

-- Create Geographic Risks Table
CREATE TABLE geographic_risks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
location VARCHAR(255) NOT NULL,
risk_score FLOAT NOT NULL,
risk_factors JSONB NOT NULL,
last_assessed_at TIMESTAMPTZ NOT NULL
);

-- Create Alternative Sources Table
CREATE TABLE alternative_sources (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
product_id VARCHAR(255) NOT NULL,
alternative_supplier VARCHAR(255) NOT NULL,
viability_score FLOAT NOT NULL,
details JSONB NOT NULL
);

-- Create Inventory Recommendations Table
CREATE TABLE inventory_recommendations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
product_id VARCHAR(255) NOT NULL,
recommended_safety_stock INT NOT NULL,
rationale TEXT NOT NULL,
generated_at TIMESTAMPTZ NOT NULL
);
"""
14 changes: 14 additions & 0 deletions backend/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod services;
mod models;
mod database;
mod utils;
mod resilience;
mod error;
mod docs;
mod blockchain;
Expand All @@ -20,7 +21,11 @@ mod compliance;

use config::Config;
use database::Database;

use services::{ProductService, EventService, UserService, ApiKeyService, SyncService, FinancialService, AnalyticsService, ResilienceService};

use services::{ProductService, EventService, UserService, ApiKeyService, SyncService, FinancialService, AnalyticsService, CarbonService};

use utils::CronService;
use error::AppError;

Expand All @@ -34,6 +39,8 @@ pub struct AppState {
pub sync_service: Arc<SyncService>,
pub financial_service: Arc<FinancialService>,
pub analytics_service: Arc<AnalyticsService>,
Chain-Resilience
pub resilience_service: Arc<ResilienceService>,
pub carbon_service: Arc<CarbonService>,
pub config: Config,
}
Expand All @@ -59,6 +66,8 @@ impl AppState {
db.pool().clone(),
config.redis.url.clone(),
));

let resilience_service = Arc::new(ResilienceService::new(db.pool().clone()));
let carbon_service = Arc::new(CarbonService::new(db.pool().clone()));

Ok(Self {
Expand All @@ -70,7 +79,11 @@ impl AppState {
sync_service,
financial_service,
analytics_service,

resilience_service,

carbon_service,

config,
})
}
Expand All @@ -94,6 +107,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let app = Router::new()
.merge(crate::routes::health_routes())
.merge(crate::routes::api_routes())
.merge(crate::routes::resilience::resilience_routes())
.merge(crate::docs::create_swagger_ui())
.layer(
ServiceBuilder::new()
Expand Down
3 changes: 3 additions & 0 deletions backend/src/models/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod analytics;
pub mod resilience;
pub mod product;
11 changes: 11 additions & 0 deletions backend/src/models/product.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, sqlx::FromRow)]
pub struct Product {
pub id: String,
pub name: String,
pub latitude: f64,
pub longitude: f64,
pub country_code: String,
}
"""
60 changes: 60 additions & 0 deletions backend/src/models/resilience.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[derive(Debug, Serialize, Deserialize, sqlx::FromRow)]
pub struct DisruptionPrediction {
pub id: Uuid,
pub product_id: String,
pub predicted_at: DateTime<Utc>,
pub probability: f64,
pub impact_level: String,
pub details: serde_json::Value,
pub created_at: DateTime<Utc>,
}

#[derive(Debug, Serialize, Deserialize, sqlx::FromRow)]
pub struct SupplierRisk {
pub id: Uuid,
pub supplier_name: String,
pub risk_score: f64,
pub risk_factors: serde_json::Value,
pub last_assessed_at: DateTime<Utc>,
}

#[derive(Debug, Serialize, Deserialize, sqlx::FromRow)]
pub struct GeographicRisk {
pub id: Uuid,
pub location: String,
pub risk_score: f64,
pub risk_factors: serde_json::Value,
pub last_assessed_at: DateTime<Utc>,
}

#[derive(Debug, Serialize, Deserialize, sqlx::FromRow)]
pub struct AlternativeSource {
pub id: Uuid,
pub product_id: String,
pub alternative_supplier: String,
pub viability_score: f64,
pub details: serde_json::Value,
}

#[derive(Debug, Serialize, Deserialize, sqlx::FromRow)]
pub struct InventoryRecommendation {
pub id: Uuid,
pub product_id: String,
pub recommended_safety_stock: i32,
pub rationale: String,
pub generated_at: DateTime<Utc>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ResilienceMetrics {
pub disruption_predictions: Vec<DisruptionPrediction>,
pub supplier_risks: Vec<SupplierRisk>,
pub geographic_risks: Vec<GeographicRisk>,
pub alternative_sources: Vec<AlternativeSource>,
pub inventory_recommendations: Vec<InventoryRecommendation>,
}
""
2 changes: 2 additions & 0 deletions backend/src/routes/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod analytics;
pub mod resilience;
24 changes: 24 additions & 0 deletions backend/src/routes/resilience.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""use axum::{
extract::{State, Path},
routing::get,
Json,
Router,
};
use std::sync::Arc;

use crate::error::AppError;
use crate::models::resilience::ResilienceMetrics;
use crate::AppState;

pub fn resilience_routes() -> Router<AppState> {
Router::new().route("/resilience/:product_id", get(get_resilience_metrics))
}

async fn get_resilience_metrics(
State(state): State<AppState>,
Path(product_id): Path<String>,
) -> Result<Json<ResilienceMetrics>, AppError> {
let metrics = state.resilience_service.get_resilience_metrics(&product_id).await?;
Ok(Json(metrics))
}
"""
2 changes: 2 additions & 0 deletions backend/src/services/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod analytics_service;
pub mod resilience_service;
Loading
Loading