hostbasket/actix_mvc_app/src/models/asset.rs
2025-05-05 11:32:09 +03:00

283 lines
8.6 KiB
Rust

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
/// Asset types representing different categories of digital assets
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum AssetType {
Artwork,
Token,
RealEstate,
Commodity,
Share,
Bond,
IntellectualProperty,
Other,
}
impl AssetType {
pub fn as_str(&self) -> &str {
match self {
AssetType::Artwork => "Artwork",
AssetType::Token => "Token",
AssetType::RealEstate => "Real Estate",
AssetType::Commodity => "Commodity",
AssetType::Share => "Share",
AssetType::Bond => "Bond",
AssetType::IntellectualProperty => "Intellectual Property",
AssetType::Other => "Other",
}
}
}
/// Status of an asset
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum AssetStatus {
Active,
Locked,
ForSale,
Transferred,
Archived,
}
impl AssetStatus {
pub fn as_str(&self) -> &str {
match self {
AssetStatus::Active => "Active",
AssetStatus::Locked => "Locked",
AssetStatus::ForSale => "For Sale",
AssetStatus::Transferred => "Transferred",
AssetStatus::Archived => "Archived",
}
}
}
/// Blockchain information for an asset
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BlockchainInfo {
pub blockchain: String,
pub token_id: String,
pub contract_address: String,
pub owner_address: String,
pub transaction_hash: Option<String>,
pub block_number: Option<u64>,
pub timestamp: Option<DateTime<Utc>>,
}
/// Valuation history point for an asset
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValuationPoint {
pub id: String,
pub date: DateTime<Utc>,
pub value: f64,
pub currency: String,
pub source: String,
pub notes: Option<String>,
}
/// Transaction history for an asset
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AssetTransaction {
pub id: String,
pub transaction_type: String,
pub date: DateTime<Utc>,
pub from_address: Option<String>,
pub to_address: Option<String>,
pub amount: Option<f64>,
pub currency: Option<String>,
pub transaction_hash: Option<String>,
pub notes: Option<String>,
}
/// Main Asset model
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Asset {
pub id: String,
pub name: String,
pub description: String,
pub asset_type: AssetType,
pub status: AssetStatus,
pub owner_id: String,
pub owner_name: String,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub blockchain_info: Option<BlockchainInfo>,
pub current_valuation: Option<f64>,
pub valuation_currency: Option<String>,
pub valuation_date: Option<DateTime<Utc>>,
pub valuation_history: Vec<ValuationPoint>,
pub transaction_history: Vec<AssetTransaction>,
pub metadata: serde_json::Value,
pub image_url: Option<String>,
pub external_url: Option<String>,
}
impl Asset {
/// Creates a new asset
pub fn new(
name: &str,
description: &str,
asset_type: AssetType,
owner_id: &str,
owner_name: &str,
) -> Self {
let now = Utc::now();
Self {
id: format!("asset-{}", Uuid::new_v4().to_string()[..8].to_string()),
name: name.to_string(),
description: description.to_string(),
asset_type,
status: AssetStatus::Active,
owner_id: owner_id.to_string(),
owner_name: owner_name.to_string(),
created_at: now,
updated_at: now,
blockchain_info: None,
current_valuation: None,
valuation_currency: None,
valuation_date: None,
valuation_history: Vec::new(),
transaction_history: Vec::new(),
metadata: serde_json::json!({}),
image_url: None,
external_url: None,
}
}
/// Adds blockchain information to the asset
pub fn add_blockchain_info(&mut self, blockchain_info: BlockchainInfo) {
self.blockchain_info = Some(blockchain_info);
self.updated_at = Utc::now();
}
/// Adds a valuation point to the asset's history
pub fn add_valuation(&mut self, value: f64, currency: &str, source: &str, notes: Option<String>) {
let valuation = ValuationPoint {
id: format!("val-{}", Uuid::new_v4().to_string()[..8].to_string()),
date: Utc::now(),
value,
currency: currency.to_string(),
source: source.to_string(),
notes,
};
self.current_valuation = Some(value);
self.valuation_currency = Some(currency.to_string());
self.valuation_date = Some(valuation.date);
self.valuation_history.push(valuation);
self.updated_at = Utc::now();
}
/// Adds a transaction to the asset's history
pub fn add_transaction(
&mut self,
transaction_type: &str,
from_address: Option<String>,
to_address: Option<String>,
amount: Option<f64>,
currency: Option<String>,
transaction_hash: Option<String>,
notes: Option<String>,
) {
let transaction = AssetTransaction {
id: format!("tx-{}", Uuid::new_v4().to_string()[..8].to_string()),
transaction_type: transaction_type.to_string(),
date: Utc::now(),
from_address,
to_address,
amount,
currency,
transaction_hash,
notes,
};
self.transaction_history.push(transaction);
self.updated_at = Utc::now();
}
/// Updates the status of the asset
pub fn update_status(&mut self, status: AssetStatus) {
self.status = status;
self.updated_at = Utc::now();
}
/// Gets the latest valuation point
pub fn latest_valuation(&self) -> Option<&ValuationPoint> {
self.valuation_history.last()
}
/// Gets the latest transaction
pub fn latest_transaction(&self) -> Option<&AssetTransaction> {
self.transaction_history.last()
}
/// Gets the valuation history sorted by date
pub fn sorted_valuation_history(&self) -> Vec<&ValuationPoint> {
let mut history = self.valuation_history.iter().collect::<Vec<_>>();
history.sort_by(|a, b| a.date.cmp(&b.date));
history
}
/// Gets the transaction history sorted by date
pub fn sorted_transaction_history(&self) -> Vec<&AssetTransaction> {
let mut history = self.transaction_history.iter().collect::<Vec<_>>();
history.sort_by(|a, b| a.date.cmp(&b.date));
history
}
}
/// Filter for assets
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AssetFilter {
pub asset_type: Option<AssetType>,
pub status: Option<AssetStatus>,
pub owner_id: Option<String>,
pub min_valuation: Option<f64>,
pub max_valuation: Option<f64>,
pub valuation_currency: Option<String>,
pub search_query: Option<String>,
}
/// Statistics for assets
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AssetStatistics {
pub total_assets: usize,
pub total_value: f64,
pub value_by_type: std::collections::HashMap<String, f64>,
pub assets_by_type: std::collections::HashMap<String, usize>,
pub assets_by_status: std::collections::HashMap<String, usize>,
}
impl AssetStatistics {
pub fn new(assets: &[Asset]) -> Self {
let mut total_value = 0.0;
let mut value_by_type = std::collections::HashMap::new();
let mut assets_by_type = std::collections::HashMap::new();
let mut assets_by_status = std::collections::HashMap::new();
for asset in assets {
if let Some(valuation) = asset.current_valuation {
total_value += valuation;
let asset_type = asset.asset_type.as_str().to_string();
*value_by_type.entry(asset_type.clone()).or_insert(0.0) += valuation;
*assets_by_type.entry(asset_type).or_insert(0) += 1;
} else {
let asset_type = asset.asset_type.as_str().to_string();
*assets_by_type.entry(asset_type).or_insert(0) += 1;
}
let status = asset.status.as_str().to_string();
*assets_by_status.entry(status).or_insert(0) += 1;
}
Self {
total_assets: assets.len(),
total_value,
value_by_type,
assets_by_type,
assets_by_status,
}
}
}