diff --git a/actix_mvc_app/src/controllers/asset.rs b/actix_mvc_app/src/controllers/asset.rs index b34249c..7e90d13 100644 --- a/actix_mvc_app/src/controllers/asset.rs +++ b/actix_mvc_app/src/controllers/asset.rs @@ -447,174 +447,232 @@ impl AssetController { let now = Utc::now(); let mut assets = Vec::new(); - // Create NFT asset - let mut nft = Asset { - id: "asset-nft12345".to_string(), - name: "CryptoKitty #12345".to_string(), - description: "A unique digital cat collectible".to_string(), - asset_type: AssetType::NFT, - status: AssetStatus::Active, - owner_id: "user-123".to_string(), - owner_name: "John Doe".to_string(), - created_at: now - Duration::days(30), - updated_at: now, - blockchain_info: None, - current_valuation: Some(600.0), - valuation_currency: Some("USD".to_string()), - valuation_date: Some(now - Duration::days(1)), - valuation_history: Vec::new(), - transaction_history: Vec::new(), - metadata: serde_json::json!({}), - image_url: Some("https://example.com/cryptokitty12345.png".to_string()), - external_url: Some("https://www.cryptokitties.co/kitty/12345".to_string()), - }; - - nft.add_blockchain_info(BlockchainInfo { - blockchain: "Ethereum".to_string(), - token_id: "12345".to_string(), - contract_address: "0x06012c8cf97BEaD5deAe237070F9587f8E7A266d".to_string(), - owner_address: "0xb794f5ea0ba39494ce839613fffba74279579268".to_string(), - transaction_hash: Some("0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234".to_string()), - block_number: Some(12345678), - timestamp: Some(now - Duration::days(30)), - }); - - nft.add_valuation(500.0, "USD", "OpenSea", Some("Initial valuation".to_string())); - nft.add_valuation(550.0, "USD", "OpenSea", Some("Market increase".to_string())); - nft.add_valuation(600.0, "USD", "OpenSea", None); - - nft.add_transaction( - "Purchase", - Some("0xa1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2".to_string()), - Some("0xb794f5ea0ba39494ce839613fffba74279579268".to_string()), - Some(500.0), - Some("USD".to_string()), - Some("0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234".to_string()), - None, - ); - - assets.push(nft); - - // Create Real Estate asset - let mut real_estate = Asset { - id: "asset-realestate789".to_string(), - name: "Apartment 123, New York".to_string(), - description: "A luxury apartment in downtown Manhattan".to_string(), + // Create Tokenized Real Estate asset + let mut zanzibar_resort = Asset { + id: "asset-zanzibar-resort".to_string(), + name: "Zanzibar Coastal Resort".to_string(), + description: "A tokenized luxury eco-resort on the eastern coast of Zanzibar with 20 villas and sustainable energy infrastructure".to_string(), asset_type: AssetType::RealEstate, status: AssetStatus::Active, - owner_id: "user-456".to_string(), - owner_name: "Jane Smith".to_string(), - created_at: now - Duration::days(60), - updated_at: now, + owner_id: "entity-oceanview-holdings".to_string(), + owner_name: "OceanView Holdings Ltd.".to_string(), + created_at: now - Duration::days(120), + updated_at: now - Duration::days(5), blockchain_info: None, - current_valuation: Some(1050000.0), + current_valuation: Some(3750000.0), valuation_currency: Some("USD".to_string()), - valuation_date: Some(now - Duration::days(5)), + valuation_date: Some(now - Duration::days(15)), valuation_history: Vec::new(), transaction_history: Vec::new(), - metadata: serde_json::json!({}), - image_url: Some("https://example.com/apartment123.jpg".to_string()), - external_url: None, + metadata: serde_json::json!({ + "location": "East Coast, Zanzibar", + "property_size": "5.2 hectares", + "buildings": 22, + "tokenization_date": (now - Duration::days(120)).to_rfc3339(), + "total_tokens": 10000, + "token_price": 375.0 + }), + image_url: Some("https://example.com/zanzibar_resort.jpg".to_string()), + external_url: Some("https://oceanviewholdings.zaz/resort".to_string()), }; - real_estate.add_blockchain_info(BlockchainInfo { + zanzibar_resort.add_blockchain_info(BlockchainInfo { blockchain: "Ethereum".to_string(), - token_id: "RE789".to_string(), + token_id: "ZRESORT".to_string(), contract_address: "0x123456789abcdef123456789abcdef12345678ab".to_string(), owner_address: "0xc3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4".to_string(), transaction_hash: Some("0xabcdef123456789abcdef123456789abcdef123456789abcdef123456789abcd".to_string()), block_number: Some(9876543), - timestamp: Some(now - Duration::days(60)), + timestamp: Some(now - Duration::days(120)), }); - real_estate.add_valuation(1000000.0, "USD", "Property Appraisal", Some("Initial valuation".to_string())); - real_estate.add_valuation(1050000.0, "USD", "Property Appraisal", Some("Annual update".to_string())); + zanzibar_resort.add_valuation(3500000.0, "USD", "ZAZ Property Registry", Some("Initial tokenization valuation".to_string())); + zanzibar_resort.add_valuation(3650000.0, "USD", "International Property Appraisers", Some("Independent third-party valuation".to_string())); + zanzibar_resort.add_valuation(3750000.0, "USD", "ZAZ Property Registry", Some("Updated valuation after infrastructure improvements".to_string())); - real_estate.add_transaction( + zanzibar_resort.add_transaction( "Tokenization", None, Some("0xc3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4".to_string()), - Some(1000000.0), + Some(3500000.0), Some("USD".to_string()), Some("0xabcdef123456789abcdef123456789abcdef123456789abcdef123456789abcd".to_string()), - Some("Initial tokenization of property".to_string()), + Some("Initial property tokenization under ZAZ Property Registry".to_string()), ); - assets.push(real_estate); + zanzibar_resort.add_transaction( + "Token Sale", + Some("0xc3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4".to_string()), + Some("0x7a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b".to_string()), + Some(375000.0), + Some("USD".to_string()), + Some("0xdef123456789abcdef123456789abcdef123456789abcdef123456789abcdef".to_string()), + Some("Sale of 10% ownership tokens to Zanzibar Investment Collective".to_string()), + ); - // Create Token asset - let mut token = Asset { - id: "asset-token456".to_string(), - name: "OurWorld Token".to_string(), - description: "Utility token for the OurWorld platform".to_string(), + assets.push(zanzibar_resort); + + // Create ZAZ Governance Token + let mut zaz_token = Asset { + id: "asset-zaz-governance".to_string(), + name: "ZAZ Governance Token".to_string(), + description: "Official governance token of the Zanzibar Autonomous Zone, used for voting on proposals and zone-wide decisions".to_string(), asset_type: AssetType::Token, status: AssetStatus::Active, - owner_id: "user-789".to_string(), - owner_name: "Alice Johnson".to_string(), - created_at: now - Duration::days(90), - updated_at: now, + owner_id: "entity-zaz-foundation".to_string(), + owner_name: "Zanzibar Autonomous Zone Foundation".to_string(), + created_at: now - Duration::days(365), + updated_at: now - Duration::days(2), blockchain_info: None, - current_valuation: Some(110000.0), - valuation_currency: Some("TFT".to_string()), - valuation_date: Some(now - Duration::days(2)), + current_valuation: Some(12500000.0), + valuation_currency: Some("USD".to_string()), + valuation_date: Some(now - Duration::days(3)), valuation_history: Vec::new(), transaction_history: Vec::new(), - metadata: serde_json::json!({}), - image_url: Some("https://example.com/ourworld_token.png".to_string()), - external_url: Some("https://ourworld.tf/token".to_string()), + metadata: serde_json::json!({ + "total_supply": 10000000, + "circulating_supply": 7500000, + "governance_weight": 1.0, + "minimum_holding_for_proposals": 10000, + "launch_date": (now - Duration::days(365)).to_rfc3339() + }), + image_url: Some("https://example.com/zaz_token.png".to_string()), + external_url: Some("https://governance.zaz/token".to_string()), }; - token.add_blockchain_info(BlockchainInfo { + zaz_token.add_blockchain_info(BlockchainInfo { blockchain: "ThreeFold".to_string(), - token_id: "TFT".to_string(), + token_id: "ZAZT".to_string(), contract_address: "0xf6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1".to_string(), owner_address: "0xe5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6".to_string(), transaction_hash: None, block_number: None, - timestamp: Some(now - Duration::days(90)), + timestamp: Some(now - Duration::days(365)), }); - token.add_valuation(100000.0, "TFT", "ThreeFold Exchange", None); - token.add_valuation(120000.0, "TFT", "ThreeFold Exchange", None); - token.add_valuation(110000.0, "TFT", "ThreeFold Exchange", None); + zaz_token.add_valuation(8000000.0, "USD", "ZAZ Token Exchange", Some("Initial valuation at launch".to_string())); + zaz_token.add_valuation(10500000.0, "USD", "ZAZ Token Exchange", Some("Valuation after successful governance implementation".to_string())); + zaz_token.add_valuation(12500000.0, "USD", "ZAZ Token Exchange", Some("Current market valuation".to_string())); - token.add_transaction( - "Transfer", - Some("0xd4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5".to_string()), + zaz_token.add_transaction( + "Distribution", Some("0xe5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6".to_string()), - Some(100000.0), - Some("TFT".to_string()), - None, - Some("Initial allocation".to_string()), + Some("0x9a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b".to_string()), + Some(1000000.0), + Some("ZAZT".to_string()), + Some("0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234".to_string()), + Some("Initial token distribution to founding members".to_string()), ); - assets.push(token); + zaz_token.add_transaction( + "Distribution", + Some("0xe5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6".to_string()), + Some("0x8b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c".to_string()), + Some(2500000.0), + Some("ZAZT".to_string()), + Some("0x234567890abcdef123456789abcdef123456789abcdef123456789abcdef1234".to_string()), + Some("Public token sale for zone participants".to_string()), + ); - // Create Intellectual Property asset - let mut ip = Asset { - id: "asset-ip987654".to_string(), - name: "Patent #987654".to_string(), - description: "A patent for a new renewable energy technology".to_string(), - asset_type: AssetType::IntellectualProperty, + assets.push(zaz_token); + + // Create Spice Trade Venture Shares + let mut spice_trade_shares = Asset { + id: "asset-spice-trade-shares".to_string(), + name: "Zanzibar Spice Trade Ventures".to_string(), + description: "Equity shares in Zanzibar Spice Trade Ventures, a leading exporter of organic spices from the Zanzibar region".to_string(), + asset_type: AssetType::Share, status: AssetStatus::Active, - owner_id: "user-321".to_string(), - owner_name: "Bob Williams".to_string(), - created_at: now - Duration::days(120), - updated_at: now, + owner_id: "entity-spice-trade".to_string(), + owner_name: "Zanzibar Spice Trade Ventures Ltd.".to_string(), + created_at: now - Duration::days(180), + updated_at: now - Duration::days(7), blockchain_info: None, - current_valuation: Some(300000.0), + current_valuation: Some(4250000.0), valuation_currency: Some("USD".to_string()), - valuation_date: Some(now - Duration::days(10)), + valuation_date: Some(now - Duration::days(7)), valuation_history: Vec::new(), transaction_history: Vec::new(), - metadata: serde_json::json!({}), - image_url: None, - external_url: None, + metadata: serde_json::json!({ + "total_shares": 1000000, + "share_type": "Common", + "business_sector": "Agriculture & Export", + "dividend_yield": 5.2, + "last_dividend_date": (now - Duration::days(30)).to_rfc3339(), + "incorporation_date": (now - Duration::days(180)).to_rfc3339() + }), + image_url: Some("https://example.com/spice_trade_logo.png".to_string()), + external_url: Some("https://spicetrade.zaz".to_string()), }; - ip.add_blockchain_info(BlockchainInfo { + spice_trade_shares.add_blockchain_info(BlockchainInfo { + blockchain: "Ethereum".to_string(), + token_id: "SPICE".to_string(), + contract_address: "0x3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4".to_string(), + owner_address: "0x6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b".to_string(), + transaction_hash: Some("0x789abcdef123456789abcdef123456789abcdef123456789abcdef123456789a".to_string()), + block_number: Some(7654321), + timestamp: Some(now - Duration::days(180)), + }); + + spice_trade_shares.add_valuation(3800000.0, "USD", "ZAZ Business Registry", Some("Initial company valuation at incorporation".to_string())); + spice_trade_shares.add_valuation(4000000.0, "USD", "ZAZ Business Registry", Some("Valuation after first export contracts".to_string())); + spice_trade_shares.add_valuation(4250000.0, "USD", "ZAZ Business Registry", Some("Current valuation after expansion to European markets".to_string())); + + spice_trade_shares.add_transaction( + "Share Issuance", + None, + Some("0x6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b".to_string()), + Some(3800000.0), + Some("USD".to_string()), + Some("0x789abcdef123456789abcdef123456789abcdef123456789abcdef123456789a".to_string()), + Some("Initial share issuance at company formation".to_string()), + ); + + spice_trade_shares.add_transaction( + "Share Transfer", + Some("0x6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b".to_string()), + Some("0x7b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c".to_string()), + Some(950000.0), + Some("USD".to_string()), + Some("0x89abcdef123456789abcdef123456789abcdef123456789abcdef123456789ab".to_string()), + Some("Sale of 25% equity to East African Growth Partners".to_string()), + ); + + assets.push(spice_trade_shares); + + // Create Sustainable Energy Patent + let mut tidal_energy_patent = Asset { + id: "asset-tidal-energy-patent".to_string(), + name: "Zanzibar Tidal Energy System Patent".to_string(), + description: "Patent for an innovative tidal energy harvesting system designed specifically for the coastal conditions of Zanzibar".to_string(), + asset_type: AssetType::IntellectualProperty, + status: AssetStatus::Active, + owner_id: "entity-zaz-energy-innovations".to_string(), + owner_name: "ZAZ Energy Innovations".to_string(), + created_at: now - Duration::days(210), + updated_at: now - Duration::days(30), + blockchain_info: None, + current_valuation: Some(2800000.0), + valuation_currency: Some("USD".to_string()), + valuation_date: Some(now - Duration::days(30)), + valuation_history: Vec::new(), + transaction_history: Vec::new(), + metadata: serde_json::json!({ + "patent_number": "ZAZ-PAT-2024-0142", + "filing_date": (now - Duration::days(210)).to_rfc3339(), + "grant_date": (now - Duration::days(120)).to_rfc3339(), + "patent_type": "Utility", + "jurisdiction": "Zanzibar Autonomous Zone", + "inventors": ["Dr. Amina Juma", "Eng. Ibrahim Hassan", "Dr. Sarah Mbeki"] + }), + image_url: Some("https://example.com/tidal_energy_diagram.png".to_string()), + external_url: Some("https://patents.zaz/ZAZ-PAT-2024-0142".to_string()), + }; + + tidal_energy_patent.add_blockchain_info(BlockchainInfo { blockchain: "Polygon".to_string(), - token_id: "IP987654".to_string(), + token_id: "TIDALIP".to_string(), contract_address: "0x2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3".to_string(), owner_address: "0x4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f".to_string(), transaction_hash: Some("0x56789abcdef123456789abcdef123456789abcdef123456789abcdef12345678".to_string()), @@ -622,69 +680,96 @@ impl AssetController { timestamp: Some(now - Duration::days(120)), }); - ip.add_valuation(250000.0, "USD", "Patent Valuation Service", Some("Initial valuation".to_string())); - ip.add_valuation(300000.0, "USD", "Patent Valuation Service", Some("After successful testing".to_string())); + tidal_energy_patent.add_valuation(1500000.0, "USD", "ZAZ IP Registry", Some("Initial patent valuation upon filing".to_string())); + tidal_energy_patent.add_valuation(2200000.0, "USD", "ZAZ IP Registry", Some("Valuation after successful prototype testing".to_string())); + tidal_energy_patent.add_valuation(2800000.0, "USD", "ZAZ IP Registry", Some("Current valuation after pilot implementation".to_string())); - ip.add_transaction( + tidal_energy_patent.add_transaction( + "Registration", + None, + Some("0x4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f".to_string()), + Some(1500000.0), + Some("USD".to_string()), + Some("0x56789abcdef123456789abcdef123456789abcdef123456789abcdef12345678".to_string()), + Some("Initial patent registration and tokenization".to_string()), + ); + + tidal_energy_patent.add_transaction( "Licensing", Some("0x4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f".to_string()), Some("0x5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a".to_string()), - Some(50000.0), + Some(450000.0), Some("USD".to_string()), Some("0x6789abcdef123456789abcdef123456789abcdef123456789abcdef123456789".to_string()), - Some("Annual licensing fee".to_string()), + Some("Licensing agreement with Coastal Energy Solutions".to_string()), ); - assets.push(ip); + assets.push(tidal_energy_patent); - // Create Share asset - let mut share = Asset { - id: "asset-share123".to_string(), - name: "OurWorld Inc. Shares".to_string(), - description: "Equity shares in OurWorld Inc.".to_string(), - asset_type: AssetType::Share, + // Create Digital Art NFT + let mut zanzibar_heritage_nft = Asset { + id: "asset-heritage-nft".to_string(), + name: "Zanzibar Heritage Collection #1".to_string(), + description: "Limited edition digital art NFT showcasing Zanzibar's cultural heritage, created by renowned local artist Fatma Busaidy".to_string(), + asset_type: AssetType::NFT, status: AssetStatus::Active, - owner_id: "user-654".to_string(), - owner_name: "Charlie Brown".to_string(), - created_at: now - Duration::days(150), - updated_at: now, + owner_id: "entity-zaz-digital-arts".to_string(), + owner_name: "ZAZ Digital Arts Collective".to_string(), + created_at: now - Duration::days(90), + updated_at: now - Duration::days(10), blockchain_info: None, - current_valuation: Some(1300.0), + current_valuation: Some(15000.0), valuation_currency: Some("USD".to_string()), - valuation_date: Some(now - Duration::days(3)), + valuation_date: Some(now - Duration::days(10)), valuation_history: Vec::new(), transaction_history: Vec::new(), - metadata: serde_json::json!({}), - image_url: None, - external_url: Some("https://ourworld.tf/shares".to_string()), + metadata: serde_json::json!({ + "artist": "Fatma Busaidy", + "edition": "1 of 10", + "medium": "Digital Mixed Media", + "dimensions": "4000x3000 px", + "creation_date": (now - Duration::days(95)).to_rfc3339(), + "authenticity_certificate": "ZAZ-ART-CERT-2024-089" + }), + image_url: Some("https://example.com/zanzibar_heritage_nft.jpg".to_string()), + external_url: Some("https://digitalarts.zaz/collections/heritage/1".to_string()), }; - share.add_blockchain_info(BlockchainInfo { + zanzibar_heritage_nft.add_blockchain_info(BlockchainInfo { blockchain: "Ethereum".to_string(), - token_id: "OWSHARE".to_string(), - contract_address: "0x3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4".to_string(), - owner_address: "0x6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b".to_string(), - transaction_hash: Some("0x789abcdef123456789abcdef123456789abcdef123456789abcdef123456789a".to_string()), - block_number: Some(7654321), - timestamp: Some(now - Duration::days(150)), + token_id: "HERITAGE1".to_string(), + contract_address: "0x06012c8cf97BEaD5deAe237070F9587f8E7A266d".to_string(), + owner_address: "0xb794f5ea0ba39494ce839613fffba74279579268".to_string(), + transaction_hash: Some("0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234".to_string()), + block_number: Some(12345678), + timestamp: Some(now - Duration::days(90)), }); - share.add_valuation(1000.0, "USD", "Stock Exchange", None); - share.add_valuation(1200.0, "USD", "Stock Exchange", None); - share.add_valuation(1150.0, "USD", "Stock Exchange", None); - share.add_valuation(1300.0, "USD", "Stock Exchange", None); + zanzibar_heritage_nft.add_valuation(12000.0, "USD", "ZAZ NFT Marketplace", Some("Initial offering price".to_string())); + zanzibar_heritage_nft.add_valuation(13500.0, "USD", "ZAZ NFT Marketplace", Some("Valuation after artist exhibition".to_string())); + zanzibar_heritage_nft.add_valuation(15000.0, "USD", "ZAZ NFT Marketplace", Some("Current market valuation".to_string())); - share.add_transaction( - "Purchase", - Some("0x7b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c".to_string()), - Some("0x6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b".to_string()), - Some(1000.0), - Some("USD".to_string()), - Some("0x89abcdef123456789abcdef123456789abcdef123456789abcdef123456789ab".to_string()), + zanzibar_heritage_nft.add_transaction( + "Minting", None, + Some("0xb794f5ea0ba39494ce839613fffba74279579268".to_string()), + Some(0.0), + Some("ETH".to_string()), + Some("0x123456789abcdef123456789abcdef123456789abcdef123456789abcdef1234".to_string()), + Some("Initial NFT minting by artist".to_string()), ); - assets.push(share); + zanzibar_heritage_nft.add_transaction( + "Sale", + Some("0xb794f5ea0ba39494ce839613fffba74279579268".to_string()), + Some("0xa1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2".to_string()), + Some(12000.0), + Some("USD".to_string()), + Some("0x234567890abcdef123456789abcdef123456789abcdef123456789abcdef1234".to_string()), + Some("Primary sale to ZAZ Digital Arts Collective".to_string()), + ); + + assets.push(zanzibar_heritage_nft); assets } diff --git a/actix_mvc_app/src/controllers/contract.rs b/actix_mvc_app/src/controllers/contract.rs index d53bbfd..0f125f0 100644 --- a/actix_mvc_app/src/controllers/contract.rs +++ b/actix_mvc_app/src/controllers/contract.rs @@ -1,9 +1,10 @@ -use actix_web::{web, HttpResponse, Result}; +use actix_web::{web, HttpResponse, Result, Error}; use tera::{Context, Tera}; use chrono::{Utc, Duration}; use serde::Deserialize; +use serde_json::json; -use crate::models::contract::{Contract, ContractStatus, ContractType, ContractStatistics, SignerStatus}; +use crate::models::contract::{Contract, ContractStatus, ContractType, ContractStatistics, ContractSigner, ContractRevision, SignerStatus}; use crate::utils::render_template; #[derive(Debug, Deserialize)] @@ -24,7 +25,7 @@ pub struct ContractController; impl ContractController { // Display the contracts dashboard - pub async fn index(tmpl: web::Data) -> Result { + pub async fn index(tmpl: web::Data) -> Result { let mut context = Context::new(); let contracts = Self::get_mock_contracts(); @@ -67,7 +68,7 @@ impl ContractController { } // Display the list of all contracts - pub async fn list(tmpl: web::Data) -> Result { + pub async fn list(tmpl: web::Data) -> Result { let mut context = Context::new(); let contracts = Self::get_mock_contracts(); @@ -86,7 +87,7 @@ impl ContractController { } // Display the list of user's contracts - pub async fn my_contracts(tmpl: web::Data) -> Result { + pub async fn my_contracts(tmpl: web::Data) -> Result { let mut context = Context::new(); let contracts = Self::get_mock_contracts(); @@ -104,7 +105,7 @@ impl ContractController { } // Display a specific contract - pub async fn detail(tmpl: web::Data, path: web::Path) -> Result { + pub async fn detail(tmpl: web::Data, path: web::Path) -> Result { let contract_id = path.into_inner(); let mut context = Context::new(); @@ -113,26 +114,39 @@ impl ContractController { // Find the contract by ID let contracts = Self::get_mock_contracts(); - let contract = contracts.iter().find(|c| c.id == contract_id); - match contract { - Some(contract) => { - // Convert contract to JSON - let contract_json = Self::contract_to_json(contract); - - context.insert("contract", &contract_json); - context.insert("user_has_signed", &false); // Mock data - - render_template(&tmpl, "contracts/contract_detail.html", &context) - }, - None => { - Ok(HttpResponse::NotFound().finish()) - } - } + // For demo purposes, if the ID doesn't match exactly, just show the first contract + // In a real app, we would return a 404 if the contract is not found + let contract = if let Some(found) = contracts.iter().find(|c| c.id == contract_id) { + found + } else { + // For demo, just use the first contract + contracts.first().unwrap() + }; + + // Convert contract to JSON + let contract_json = Self::contract_to_json(contract); + + // Add contract to context + context.insert("contract", &contract_json); + + // Count signed signers for the template + let signed_signers = contract.signers.iter().filter(|s| s.status == SignerStatus::Signed).count(); + context.insert("signed_signers", &signed_signers); + + // Count pending signers for the template + let pending_signers = contract.signers.iter().filter(|s| s.status == SignerStatus::Pending).count(); + context.insert("pending_signers", &pending_signers); + + // For demo purposes, set user_has_signed to false + // In a real app, we would check if the current user has already signed + context.insert("user_has_signed", &false); + + render_template(&tmpl, "contracts/contract_detail.html", &context) } // Display the create contract form - pub async fn create_form(tmpl: web::Data) -> Result { + pub async fn create_form(tmpl: web::Data) -> Result { let mut context = Context::new(); // Add active_page for navigation highlighting @@ -156,7 +170,7 @@ impl ContractController { pub async fn create( _tmpl: web::Data, _form: web::Form, - ) -> Result { + ) -> Result { // In a real application, we would save the contract to the database // For now, we'll just redirect to the contracts list @@ -167,14 +181,22 @@ impl ContractController { fn contract_to_json(contract: &Contract) -> serde_json::Map { let mut map = serde_json::Map::new(); + // Basic contract info map.insert("id".to_string(), serde_json::Value::String(contract.id.clone())); map.insert("title".to_string(), serde_json::Value::String(contract.title.clone())); map.insert("description".to_string(), serde_json::Value::String(contract.description.clone())); - map.insert("status".to_string(), serde_json::Value::String(format!("{:?}", contract.status))); - map.insert("contract_type".to_string(), serde_json::Value::String(format!("{:?}", contract.contract_type))); + map.insert("status".to_string(), serde_json::Value::String(contract.status.as_str().to_string())); + map.insert("contract_type".to_string(), serde_json::Value::String(contract.contract_type.as_str().to_string())); + map.insert("created_by".to_string(), serde_json::Value::String(contract.created_by.clone())); map.insert("created_at".to_string(), serde_json::Value::String(contract.created_at.format("%Y-%m-%d").to_string())); map.insert("updated_at".to_string(), serde_json::Value::String(contract.updated_at.format("%Y-%m-%d").to_string())); - map.insert("created_by".to_string(), serde_json::Value::String("John Doe".to_string())); // Mock data + + // Organization info + if let Some(org) = &contract.organization_id { + map.insert("organization".to_string(), serde_json::Value::String(org.clone())); + } else { + map.insert("organization".to_string(), serde_json::Value::Null); + } // Add signers let signers: Vec = contract.signers.iter() @@ -183,10 +205,23 @@ impl ContractController { signer_map.insert("id".to_string(), serde_json::Value::String(s.id.clone())); signer_map.insert("name".to_string(), serde_json::Value::String(s.name.clone())); signer_map.insert("email".to_string(), serde_json::Value::String(s.email.clone())); - signer_map.insert("status".to_string(), serde_json::Value::String(format!("{:?}", s.status))); + signer_map.insert("status".to_string(), serde_json::Value::String(s.status.as_str().to_string())); if let Some(signed_at) = s.signed_at { signer_map.insert("signed_at".to_string(), serde_json::Value::String(signed_at.format("%Y-%m-%d").to_string())); + } else { + // For display purposes, add a placeholder date for pending signers + if s.status == SignerStatus::Pending { + signer_map.insert("signed_at".to_string(), serde_json::Value::String("Pending".to_string())); + } else if s.status == SignerStatus::Rejected { + signer_map.insert("signed_at".to_string(), serde_json::Value::String("Rejected".to_string())); + } + } + + if let Some(comments) = &s.comments { + signer_map.insert("comments".to_string(), serde_json::Value::String(comments.clone())); + } else { + signer_map.insert("comments".to_string(), serde_json::Value::String("".to_string())); } serde_json::Value::Object(signer_map) @@ -195,14 +230,14 @@ impl ContractController { map.insert("signers".to_string(), serde_json::Value::Array(signers)); - // Add signed_signers count for templates - let signed_signers = contract.signers.iter().filter(|s| s.status == SignerStatus::Signed).count(); - map.insert("signed_signers".to_string(), serde_json::Value::Number(serde_json::Number::from(signed_signers))); - // Add pending_signers count for templates let pending_signers = contract.signers.iter().filter(|s| s.status == SignerStatus::Pending).count(); map.insert("pending_signers".to_string(), serde_json::Value::Number(serde_json::Number::from(pending_signers))); + // Add signed_signers count for templates + let signed_signers = contract.signers.iter().filter(|s| s.status == SignerStatus::Signed).count(); + map.insert("signed_signers".to_string(), serde_json::Value::Number(serde_json::Number::from(signed_signers))); + // Add revisions let revisions: Vec = contract.revisions.iter() .map(|r| { @@ -216,13 +251,63 @@ impl ContractController { revision_map.insert("comments".to_string(), serde_json::Value::String(comments.clone())); // Add notes field using comments since ContractRevision doesn't have a notes field revision_map.insert("notes".to_string(), serde_json::Value::String(comments.clone())); + } else { + revision_map.insert("comments".to_string(), serde_json::Value::String("".to_string())); + revision_map.insert("notes".to_string(), serde_json::Value::String("".to_string())); } serde_json::Value::Object(revision_map) }) .collect(); - map.insert("revisions".to_string(), serde_json::Value::Array(revisions)); + map.insert("revisions".to_string(), serde_json::Value::Array(revisions.clone())); + + // Add current_version + map.insert("current_version".to_string(), serde_json::Value::Number(serde_json::Number::from(contract.current_version))); + + // Add latest_revision as an object + if !contract.revisions.is_empty() { + // Find the latest revision based on version number + if let Some(latest) = contract.revisions.iter().max_by_key(|r| r.version) { + let mut latest_revision_map = serde_json::Map::new(); + latest_revision_map.insert("version".to_string(), serde_json::Value::Number(serde_json::Number::from(latest.version))); + latest_revision_map.insert("content".to_string(), serde_json::Value::String(latest.content.clone())); + latest_revision_map.insert("created_at".to_string(), serde_json::Value::String(latest.created_at.format("%Y-%m-%d").to_string())); + latest_revision_map.insert("created_by".to_string(), serde_json::Value::String(latest.created_by.clone())); + + if let Some(comments) = &latest.comments { + latest_revision_map.insert("comments".to_string(), serde_json::Value::String(comments.clone())); + latest_revision_map.insert("notes".to_string(), serde_json::Value::String(comments.clone())); + } else { + latest_revision_map.insert("comments".to_string(), serde_json::Value::String("".to_string())); + latest_revision_map.insert("notes".to_string(), serde_json::Value::String("".to_string())); + } + + map.insert("latest_revision".to_string(), serde_json::Value::Object(latest_revision_map)); + } else { + // Create an empty latest_revision object to avoid template errors + let mut empty_revision = serde_json::Map::new(); + empty_revision.insert("version".to_string(), serde_json::Value::Number(serde_json::Number::from(0))); + empty_revision.insert("content".to_string(), serde_json::Value::String("No content available".to_string())); + empty_revision.insert("created_at".to_string(), serde_json::Value::String("N/A".to_string())); + empty_revision.insert("created_by".to_string(), serde_json::Value::String("N/A".to_string())); + empty_revision.insert("comments".to_string(), serde_json::Value::String("".to_string())); + empty_revision.insert("notes".to_string(), serde_json::Value::String("".to_string())); + + map.insert("latest_revision".to_string(), serde_json::Value::Object(empty_revision)); + } + } else { + // Create an empty latest_revision object to avoid template errors + let mut empty_revision = serde_json::Map::new(); + empty_revision.insert("version".to_string(), serde_json::Value::Number(serde_json::Number::from(0))); + empty_revision.insert("content".to_string(), serde_json::Value::String("No content available".to_string())); + empty_revision.insert("created_at".to_string(), serde_json::Value::String("N/A".to_string())); + empty_revision.insert("created_by".to_string(), serde_json::Value::String("N/A".to_string())); + empty_revision.insert("comments".to_string(), serde_json::Value::String("".to_string())); + empty_revision.insert("notes".to_string(), serde_json::Value::String("".to_string())); + + map.insert("latest_revision".to_string(), serde_json::Value::Object(empty_revision)); + } // Add effective and expiration dates if present if let Some(effective_date) = &contract.effective_date { @@ -238,95 +323,269 @@ impl ContractController { // Generate mock contracts for testing fn get_mock_contracts() -> Vec { - let now = Utc::now(); - let mut contracts = Vec::new(); - // Contract 1 - Draft - let mut contract1 = Contract::new( - "Employment Agreement - Marketing Manager".to_string(), - "Standard employment contract for the Marketing Manager position".to_string(), - ContractType::Employment, - "John Doe".to_string(), - Some("Acme Corp".to_string()) - ); + // Mock contract 1 - Signed Service Agreement + let mut contract1 = Contract { + id: "contract-001".to_string(), + title: "Digital Hub Service Agreement".to_string(), + description: "Service agreement for cloud hosting and digital infrastructure services provided by the Zanzibar Digital Hub.".to_string(), + status: ContractStatus::Signed, + contract_type: ContractType::Service, + created_by: "Wei Chen".to_string(), + created_at: Utc::now() - Duration::days(30), + updated_at: Utc::now() - Duration::days(5), + organization_id: Some("Zanzibar Digital Hub".to_string()), + effective_date: Some(Utc::now() - Duration::days(5)), + expiration_date: Some(Utc::now() + Duration::days(365)), + signers: Vec::new(), + revisions: Vec::new(), + current_version: 2, + }; - contract1.effective_date = Some(now + Duration::days(30)); - contract1.expiration_date = Some(now + Duration::days(395)); // ~1 year + // Add signers to contract 1 + contract1.signers.push(ContractSigner { + id: "signer-001".to_string(), + name: "Wei Chen".to_string(), + email: "wei.chen@example.com".to_string(), + status: SignerStatus::Signed, + signed_at: Some(Utc::now() - Duration::days(5)), + comments: Some("Approved as per our discussion.".to_string()), + }); - contract1.add_revision( - "

This is a draft employment contract for the Marketing Manager position.

".to_string(), - "John Doe".to_string(), - Some("Initial draft".to_string()) - ); + contract1.signers.push(ContractSigner { + id: "signer-002".to_string(), + name: "Nala Okafor".to_string(), + email: "nala.okafor@example.com".to_string(), + status: SignerStatus::Signed, + signed_at: Some(Utc::now() - Duration::days(6)), + comments: Some("Terms look good. Happy to proceed.".to_string()), + }); - // Contract 2 - Pending Signatures - let mut contract2 = Contract::new( - "Non-Disclosure Agreement - Vendor XYZ".to_string(), - "NDA for our partnership with Vendor XYZ".to_string(), - ContractType::NDA, - "John Doe".to_string(), - Some("Acme Corp".to_string()) - ); + // Add revisions to contract 1 + contract1.revisions.push(ContractRevision { + version: 1, + content: "

Digital Hub Service Agreement

This Service Agreement (the \"Agreement\") is entered into between Zanzibar Digital Hub (\"Provider\") and the undersigned client (\"Client\").

1. Services

Provider agrees to provide Client with cloud hosting and digital infrastructure services as specified in Appendix A.

2. Term

This Agreement shall commence on the Effective Date and continue for a period of one (1) year unless terminated earlier in accordance with the terms herein.

3. Fees

Client agrees to pay Provider the fees set forth in Appendix B. All fees are due within thirty (30) days of invoice date.

4. Confidentiality

Each party agrees to maintain the confidentiality of any proprietary information received from the other party during the term of this Agreement.

".to_string(), + created_at: Utc::now() - Duration::days(35), + created_by: "Wei Chen".to_string(), + comments: Some("Initial draft of the service agreement.".to_string()), + }); - contract2.effective_date = Some(now); - contract2.expiration_date = Some(now + Duration::days(730)); // 2 years + contract1.revisions.push(ContractRevision { + version: 2, + content: "

Digital Hub Service Agreement

This Service Agreement (the \"Agreement\") is entered into between Zanzibar Digital Hub (\"Provider\") and the undersigned client (\"Client\").

1. Services

Provider agrees to provide Client with cloud hosting and digital infrastructure services as specified in Appendix A.

2. Term

This Agreement shall commence on the Effective Date and continue for a period of one (1) year unless terminated earlier in accordance with the terms herein.

3. Fees

Client agrees to pay Provider the fees set forth in Appendix B. All fees are due within thirty (30) days of invoice date.

4. Confidentiality

Each party agrees to maintain the confidentiality of any proprietary information received from the other party during the term of this Agreement.

5. Data Protection

Provider shall implement appropriate technical and organizational measures to ensure a level of security appropriate to the risk, including encryption of personal data, and shall comply with all applicable data protection laws.

".to_string(), + created_at: Utc::now() - Duration::days(30), + created_by: "Wei Chen".to_string(), + comments: Some("Added data protection clause as requested by legal.".to_string()), + }); - contract2.add_revision( - "

This is the first version of the NDA with Vendor XYZ.

".to_string(), - "John Doe".to_string(), - Some("Initial draft".to_string()) - ); + // Mock contract 2 - Pending Signatures + let mut contract2 = Contract { + id: "contract-002".to_string(), + title: "Software Development Agreement".to_string(), + description: "Agreement for custom software development services for the Zanzibar Digital Marketplace platform.".to_string(), + status: ContractStatus::PendingSignatures, + contract_type: ContractType::SLA, + created_by: "Dr. Raj Patel".to_string(), + created_at: Utc::now() - Duration::days(10), + updated_at: Utc::now() - Duration::days(2), + organization_id: Some("Global Tech Solutions".to_string()), + effective_date: None, + expiration_date: None, + signers: Vec::new(), + revisions: Vec::new(), + current_version: 1, + }; - contract2.add_revision( - "

This is the revised version of the NDA with Vendor XYZ.

".to_string(), - "John Doe".to_string(), - Some("Added confidentiality period".to_string()) - ); + // Add signers to contract 2 + contract2.signers.push(ContractSigner { + id: "signer-003".to_string(), + name: "Dr. Raj Patel".to_string(), + email: "raj.patel@example.com".to_string(), + status: SignerStatus::Signed, + signed_at: Some(Utc::now() - Duration::days(2)), + comments: None, + }); - contract2.add_signer("Jane Smith".to_string(), "jane@example.com".to_string()); - contract2.add_signer("Bob Johnson".to_string(), "bob@vendorxyz.com".to_string()); + contract2.signers.push(ContractSigner { + id: "signer-004".to_string(), + name: "Maya Rodriguez".to_string(), + email: "maya.rodriguez@example.com".to_string(), + status: SignerStatus::Pending, + signed_at: None, + comments: None, + }); - // Mark Jane as signed - if let Some(signer) = contract2.signers.iter_mut().next() { - signer.sign(None); - } + contract2.signers.push(ContractSigner { + id: "signer-005".to_string(), + name: "Jamal Washington".to_string(), + email: "jamal.washington@example.com".to_string(), + status: SignerStatus::Pending, + signed_at: None, + comments: None, + }); - // Send for signatures - let _ = contract2.send_for_signatures(); + // Add revisions to contract 2 + contract2.revisions.push(ContractRevision { + version: 1, + content: "

Software Development Agreement

This Software Development Agreement (the \"Agreement\") is entered into between Global Tech Solutions (\"Developer\") and Zanzibar Digital Hub (\"Client\").

1. Scope of Work

Developer agrees to design, develop, and implement a digital marketplace platform as specified in the attached Statement of Work.

2. Timeline

Developer shall complete the development according to the timeline set forth in Appendix A.

3. Compensation

Client agrees to pay Developer the fees set forth in Appendix B according to the payment schedule therein.

4. Intellectual Property

Upon full payment, Client shall own all rights, title, and interest in the developed software.

".to_string(), + created_at: Utc::now() - Duration::days(10), + created_by: "Dr. Raj Patel".to_string(), + comments: Some("Initial draft of the development agreement.".to_string()), + }); - // Contract 3 - Signed - let mut contract3 = Contract::new( - "Service Agreement - Website Maintenance".to_string(), - "Agreement for ongoing website maintenance services".to_string(), - ContractType::Service, - "John Doe".to_string(), - Some("Acme Corp".to_string()) - ); + // Mock contract 3 - Draft + let mut contract3 = Contract { + id: "contract-003".to_string(), + title: "Digital Asset Tokenization Agreement".to_string(), + description: "Framework agreement for tokenizing real estate assets on the Zanzibar blockchain network.".to_string(), + status: ContractStatus::Draft, + contract_type: ContractType::Partnership, + created_by: "Nala Okafor".to_string(), + created_at: Utc::now() - Duration::days(3), + updated_at: Utc::now() - Duration::days(1), + organization_id: Some("Zanzibar Property Consortium".to_string()), + effective_date: None, + expiration_date: None, + signers: Vec::new(), + revisions: Vec::new(), + current_version: 1, + }; - contract3.effective_date = Some(now - Duration::days(7)); - contract3.expiration_date = Some(now + Duration::days(358)); // ~1 year from effective date + // Add potential signers to contract 3 (still in draft) + contract3.signers.push(ContractSigner { + id: "signer-006".to_string(), + name: "Nala Okafor".to_string(), + email: "nala.okafor@example.com".to_string(), + status: SignerStatus::Pending, + signed_at: None, + comments: None, + }); - contract3.add_revision( - "

This is a service agreement for website maintenance.

".to_string(), - "John Doe".to_string(), - Some("Initial version".to_string()) - ); + contract3.signers.push(ContractSigner { + id: "signer-007".to_string(), + name: "Ibrahim Al-Farsi".to_string(), + email: "ibrahim.alfarsi@example.com".to_string(), + status: SignerStatus::Pending, + signed_at: None, + comments: None, + }); - contract3.add_signer("Jane Smith".to_string(), "jane@example.com".to_string()); - contract3.add_signer("Alice Brown".to_string(), "alice@webmaintenance.com".to_string()); + // Add revisions to contract 3 + contract3.revisions.push(ContractRevision { + version: 1, + content: "

Digital Asset Tokenization Agreement

This Digital Asset Tokenization Agreement (the \"Agreement\") is entered into between Zanzibar Property Consortium (\"Tokenizer\") and the property owners listed in Appendix A (\"Owners\").

1. Purpose

The purpose of this Agreement is to establish the terms and conditions for tokenizing real estate assets on the Zanzibar blockchain network.

2. Tokenization Process

Tokenizer shall create digital tokens representing ownership interests in the properties listed in Appendix A according to the specifications in Appendix B.

3. Revenue Sharing

Revenue generated from the tokenized properties shall be distributed according to the formula set forth in Appendix C.

4. Governance

Decisions regarding the management of tokenized properties shall be made according to the governance framework outlined in Appendix D.

".to_string(), + created_at: Utc::now() - Duration::days(3), + created_by: "Nala Okafor".to_string(), + comments: Some("Initial draft of the tokenization agreement.".to_string()), + }); - // Mark both signers as signed - for signer in contract3.signers.iter_mut() { - signer.sign(None); - } + // Mock contract 4 - Rejected + let mut contract4 = Contract { + id: "contract-004".to_string(), + title: "Data Sharing Agreement".to_string(), + description: "Agreement governing the sharing of anonymized data between Zanzibar Digital Hub and research institutions.".to_string(), + status: ContractStatus::Draft, + contract_type: ContractType::NDA, + created_by: "Wei Chen".to_string(), + created_at: Utc::now() - Duration::days(15), + updated_at: Utc::now() - Duration::days(8), + organization_id: Some("Zanzibar Digital Hub".to_string()), + effective_date: None, + expiration_date: None, + signers: Vec::new(), + revisions: Vec::new(), + current_version: 1, + }; - // Mark as signed - contract3.status = ContractStatus::Signed; + // Add signers to contract 4 with a rejection + contract4.signers.push(ContractSigner { + id: "signer-008".to_string(), + name: "Wei Chen".to_string(), + email: "wei.chen@example.com".to_string(), + status: SignerStatus::Signed, + signed_at: Some(Utc::now() - Duration::days(10)), + comments: None, + }); + contract4.signers.push(ContractSigner { + id: "signer-009".to_string(), + name: "Dr. Amina Diallo".to_string(), + email: "amina.diallo@example.com".to_string(), + status: SignerStatus::Rejected, + signed_at: Some(Utc::now() - Duration::days(8)), + comments: Some("Cannot agree to these terms due to privacy concerns. Please revise section 3.2 regarding data retention.".to_string()), + }); + + // Add revisions to contract 4 + contract4.revisions.push(ContractRevision { + version: 1, + content: "

Data Sharing Agreement

This Data Sharing Agreement (the \"Agreement\") is entered into between Zanzibar Digital Hub (\"Provider\") and the research institutions listed in Appendix A (\"Recipients\").

1. Purpose

The purpose of this Agreement is to establish the terms and conditions for sharing anonymized data for research purposes.

2. Data Description

Provider shall share the data described in Appendix B, which shall be anonymized according to the protocol in Appendix C.

3. Data Use

Recipients may use the shared data solely for the research purposes described in Appendix D.

3.1 Publication

Recipients may publish research findings based on the shared data, provided that they acknowledge Provider as the data source.

3.2 Data Retention

Recipients shall retain the shared data for a period of five (5) years, after which they shall securely delete all copies.

".to_string(), + created_at: Utc::now() - Duration::days(15), + created_by: "Wei Chen".to_string(), + comments: Some("Initial draft of the data sharing agreement.".to_string()), + }); + + // Mock contract 5 - Active + let mut contract5 = Contract { + id: "contract-005".to_string(), + title: "Digital Identity Verification Service Agreement".to_string(), + description: "Agreement for providing digital identity verification services to businesses operating in the Zanzibar Autonomous Zone.".to_string(), + status: ContractStatus::Active, + contract_type: ContractType::Service, + created_by: "Maya Rodriguez".to_string(), + created_at: Utc::now() - Duration::days(60), + updated_at: Utc::now() - Duration::days(45), + organization_id: Some("Zanzibar Digital Hub".to_string()), + effective_date: Some(Utc::now() - Duration::days(45)), + expiration_date: Some(Utc::now() + Duration::days(305)), + signers: Vec::new(), + revisions: Vec::new(), + current_version: 2, + }; + + // Add signers to contract 5 + contract5.signers.push(ContractSigner { + id: "signer-010".to_string(), + name: "Maya Rodriguez".to_string(), + email: "maya.rodriguez@example.com".to_string(), + status: SignerStatus::Signed, + signed_at: Some(Utc::now() - Duration::days(47)), + comments: None, + }); + + contract5.signers.push(ContractSigner { + id: "signer-011".to_string(), + name: "Li Wei".to_string(), + email: "li.wei@example.com".to_string(), + status: SignerStatus::Signed, + signed_at: Some(Utc::now() - Duration::days(45)), + comments: Some("Approved after legal review.".to_string()), + }); + + // Add revisions to contract 5 + contract5.revisions.push(ContractRevision { + version: 1, + content: "

Digital Identity Verification Service Agreement

This Service Agreement (the \"Agreement\") is entered into between Zanzibar Digital Hub (\"Provider\") and the businesses listed in Appendix A (\"Clients\").

1. Services

Provider agrees to provide Clients with digital identity verification services as specified in Appendix B.

2. Term

This Agreement shall commence on the Effective Date and continue for a period of one (1) year unless terminated earlier in accordance with the terms herein.

3. Fees

Clients agree to pay Provider the fees set forth in Appendix C. All fees are due within thirty (30) days of invoice date.

4. Service Level Agreement

Provider shall maintain a service uptime of at least 99.9% as measured on a monthly basis.

".to_string(), + created_at: Utc::now() - Duration::days(60), + created_by: "Maya Rodriguez".to_string(), + comments: Some("Initial draft of the identity verification service agreement.".to_string()), + }); + + contract5.revisions.push(ContractRevision { + version: 2, + content: "

Digital Identity Verification Service Agreement

This Service Agreement (the \"Agreement\") is entered into between Zanzibar Digital Hub (\"Provider\") and the businesses listed in Appendix A (\"Clients\").

1. Services

Provider agrees to provide Clients with digital identity verification services as specified in Appendix B.

2. Term

This Agreement shall commence on the Effective Date and continue for a period of one (1) year unless terminated earlier in accordance with the terms herein.

3. Fees

Clients agree to pay Provider the fees set forth in Appendix C. All fees are due within thirty (30) days of invoice date.

4. Service Level Agreement

Provider shall maintain a service uptime of at least 99.9% as measured on a monthly basis.

5. Compliance

Provider shall comply with all applicable laws and regulations regarding identity verification and data protection, including but not limited to the Zanzibar Digital Economy Act.

".to_string(), + created_at: Utc::now() - Duration::days(50), + created_by: "Maya Rodriguez".to_string(), + comments: Some("Added compliance clause as requested by legal.".to_string()), + }); + + // Add all contracts to the vector contracts.push(contract1); contracts.push(contract2); contracts.push(contract3); + contracts.push(contract4); + contracts.push(contract5); contracts } diff --git a/actix_mvc_app/src/controllers/flow.rs b/actix_mvc_app/src/controllers/flow.rs index 9816296..423f50a 100644 --- a/actix_mvc_app/src/controllers/flow.rs +++ b/actix_mvc_app/src/controllers/flow.rs @@ -187,226 +187,421 @@ impl FlowController { // Create a few mock flows let mut flow1 = Flow { id: "flow-1".to_string(), - name: "Deploy Website".to_string(), - description: "Deploy a new website to production".to_string(), - flow_type: FlowType::ServiceActivation, + name: "ZAZ Business Entity Registration".to_string(), + description: "Register a new business entity within the Zanzibar Autonomous Zone legal framework".to_string(), + flow_type: FlowType::CompanyRegistration, status: FlowStatus::InProgress, owner_id: "user-1".to_string(), - owner_name: "John Doe".to_string(), + owner_name: "Ibrahim Faraji".to_string(), steps: vec![ FlowStep { id: "step-1-1".to_string(), - name: "Build".to_string(), - description: "Build the website".to_string(), + name: "Document Submission".to_string(), + description: "Submit required business registration documents including business plan, ownership structure, and KYC information".to_string(), order: 1, status: StepStatus::Completed, - started_at: Some(Utc::now() - Duration::days(1)), - completed_at: Some(Utc::now() - Duration::hours(23)), + started_at: Some(Utc::now() - Duration::days(5)), + completed_at: Some(Utc::now() - Duration::days(4)), logs: vec![ FlowLog { id: "log-1-1-1".to_string(), - message: "Build started".to_string(), - timestamp: Utc::now() - Duration::days(1), + message: "Initial document package submitted".to_string(), + timestamp: Utc::now() - Duration::days(5), }, FlowLog { id: "log-1-1-2".to_string(), - message: "Build completed successfully".to_string(), - timestamp: Utc::now() - Duration::hours(23), + message: "Additional ownership verification documents requested".to_string(), + timestamp: Utc::now() - Duration::days(4) - Duration::hours(12), + }, + FlowLog { + id: "log-1-1-3".to_string(), + message: "Additional documents submitted and verified".to_string(), + timestamp: Utc::now() - Duration::days(4), }, ], }, FlowStep { id: "step-1-2".to_string(), - name: "Test".to_string(), - description: "Run tests on the website".to_string(), + name: "Regulatory Review".to_string(), + description: "ZAZ Business Registry review of submitted documents and compliance with regulatory requirements".to_string(), order: 2, status: StepStatus::InProgress, - started_at: Some(Utc::now() - Duration::hours(22)), + started_at: Some(Utc::now() - Duration::days(3)), completed_at: None, logs: vec![ FlowLog { id: "log-1-2-1".to_string(), - message: "Tests started".to_string(), - timestamp: Utc::now() - Duration::hours(22), + message: "Regulatory review initiated by ZAZ Business Registry".to_string(), + timestamp: Utc::now() - Duration::days(3), + }, + FlowLog { + id: "log-1-2-2".to_string(), + message: "Preliminary compliance assessment completed".to_string(), + timestamp: Utc::now() - Duration::days(2), + }, + FlowLog { + id: "log-1-2-3".to_string(), + message: "Awaiting final approval from regulatory committee".to_string(), + timestamp: Utc::now() - Duration::days(1), }, ], }, FlowStep { id: "step-1-3".to_string(), - name: "Deploy".to_string(), - description: "Deploy the website to production".to_string(), + name: "Digital Identity Creation".to_string(), + description: "Creation of the entity's digital identity and blockchain credentials within the ZAZ ecosystem".to_string(), order: 3, status: StepStatus::Pending, started_at: None, completed_at: None, logs: vec![], }, + FlowStep { + id: "step-1-4".to_string(), + name: "License and Certificate Issuance".to_string(), + description: "Issuance of business licenses, certificates, and digital credentials".to_string(), + order: 4, + status: StepStatus::Pending, + started_at: None, + completed_at: None, + logs: vec![], + }, ], - created_at: Utc::now() - Duration::days(1), - updated_at: Utc::now() - Duration::hours(22), + created_at: Utc::now() - Duration::days(5), + updated_at: Utc::now() - Duration::days(1), completed_at: None, - progress_percentage: 33, + progress_percentage: 40, current_step: None, }; // Update the current step flow1.current_step = flow1.steps.iter().find(|s| s.status == StepStatus::InProgress).cloned(); - let flow2 = Flow { + let mut flow2 = Flow { id: "flow-2".to_string(), - name: "Database Migration".to_string(), - description: "Migrate database to new schema".to_string(), - flow_type: FlowType::CompanyRegistration, + name: "Digital Asset Tokenization Approval".to_string(), + description: "Process for approving the tokenization of a real estate asset within the ZAZ regulatory framework".to_string(), + flow_type: FlowType::AssetTokenization, status: FlowStatus::Completed, owner_id: "user-2".to_string(), - owner_name: "Jane Smith".to_string(), + owner_name: "Amina Salim".to_string(), steps: vec![ FlowStep { id: "step-2-1".to_string(), - name: "Backup".to_string(), - description: "Backup the database".to_string(), + name: "Asset Verification".to_string(), + description: "Verification of the underlying asset ownership and valuation".to_string(), order: 1, status: StepStatus::Completed, - started_at: Some(Utc::now() - Duration::days(3)), - completed_at: Some(Utc::now() - Duration::days(3) + Duration::hours(2)), + started_at: Some(Utc::now() - Duration::days(30)), + completed_at: Some(Utc::now() - Duration::days(25)), logs: vec![ FlowLog { id: "log-2-1-1".to_string(), - message: "Backup started".to_string(), - timestamp: Utc::now() - Duration::days(3), + message: "Asset documentation submitted for verification".to_string(), + timestamp: Utc::now() - Duration::days(30), }, FlowLog { id: "log-2-1-2".to_string(), - message: "Backup completed successfully".to_string(), - timestamp: Utc::now() - Duration::days(3) + Duration::hours(2), + message: "Independent valuation completed by ZAZ Property Registry".to_string(), + timestamp: Utc::now() - Duration::days(27), + }, + FlowLog { + id: "log-2-1-3".to_string(), + message: "Asset ownership and valuation verified".to_string(), + timestamp: Utc::now() - Duration::days(25), }, ], }, FlowStep { id: "step-2-2".to_string(), - name: "Migrate".to_string(), - description: "Run migration scripts".to_string(), + name: "Tokenization Structure Review".to_string(), + description: "Review of the proposed token structure, distribution model, and compliance with ZAZ tokenization standards".to_string(), order: 2, status: StepStatus::Completed, - started_at: Some(Utc::now() - Duration::days(3) + Duration::hours(3)), - completed_at: Some(Utc::now() - Duration::days(3) + Duration::hours(5)), + started_at: Some(Utc::now() - Duration::days(24)), + completed_at: Some(Utc::now() - Duration::days(20)), logs: vec![ FlowLog { id: "log-2-2-1".to_string(), - message: "Migration started".to_string(), - timestamp: Utc::now() - Duration::days(3) + Duration::hours(3), + message: "Tokenization proposal submitted for review".to_string(), + timestamp: Utc::now() - Duration::days(24), }, FlowLog { id: "log-2-2-2".to_string(), - message: "Migration completed successfully".to_string(), - timestamp: Utc::now() - Duration::days(3) + Duration::hours(5), + message: "Technical review completed by ZAZ Digital Assets Committee".to_string(), + timestamp: Utc::now() - Duration::days(22), + }, + FlowLog { + id: "log-2-2-3".to_string(), + message: "Tokenization structure approved with minor modifications".to_string(), + timestamp: Utc::now() - Duration::days(20), }, ], }, FlowStep { id: "step-2-3".to_string(), - name: "Verify".to_string(), - description: "Verify the migration".to_string(), + name: "Smart Contract Deployment".to_string(), + description: "Deployment and verification of the asset tokenization smart contracts".to_string(), order: 3, status: StepStatus::Completed, - started_at: Some(Utc::now() - Duration::days(3) + Duration::hours(6)), - completed_at: Some(Utc::now() - Duration::days(3) + Duration::hours(7)), + started_at: Some(Utc::now() - Duration::days(19)), + completed_at: Some(Utc::now() - Duration::days(15)), logs: vec![ FlowLog { id: "log-2-3-1".to_string(), - message: "Verification started".to_string(), - timestamp: Utc::now() - Duration::days(3) + Duration::hours(6), + message: "Smart contract code submitted for audit".to_string(), + timestamp: Utc::now() - Duration::days(19), }, FlowLog { id: "log-2-3-2".to_string(), - message: "Verification completed successfully".to_string(), - timestamp: Utc::now() - Duration::days(3) + Duration::hours(7), + message: "Security audit completed with no critical issues".to_string(), + timestamp: Utc::now() - Duration::days(17), + }, + FlowLog { + id: "log-2-3-3".to_string(), + message: "Smart contracts deployed to ZAZ-approved blockchain".to_string(), + timestamp: Utc::now() - Duration::days(15), + }, + ], + }, + FlowStep { + id: "step-2-4".to_string(), + name: "Final Approval and Listing".to_string(), + description: "Final regulatory approval and listing on the ZAZ Digital Asset Exchange".to_string(), + order: 4, + status: StepStatus::Completed, + started_at: Some(Utc::now() - Duration::days(14)), + completed_at: Some(Utc::now() - Duration::days(10)), + logs: vec![ + FlowLog { + id: "log-2-4-1".to_string(), + message: "Final documentation package submitted for approval".to_string(), + timestamp: Utc::now() - Duration::days(14), + }, + FlowLog { + id: "log-2-4-2".to_string(), + message: "Regulatory approval granted by ZAZ Financial Authority".to_string(), + timestamp: Utc::now() - Duration::days(12), + }, + FlowLog { + id: "log-2-4-3".to_string(), + message: "Asset tokens listed on ZAZ Digital Asset Exchange".to_string(), + timestamp: Utc::now() - Duration::days(10), }, ], }, ], - created_at: Utc::now() - Duration::days(3), - updated_at: Utc::now() - Duration::days(3) + Duration::hours(7), - completed_at: Some(Utc::now() - Duration::days(3) + Duration::hours(7)), + created_at: Utc::now() - Duration::days(30), + updated_at: Utc::now() - Duration::days(10), + completed_at: Some(Utc::now() - Duration::days(10)), progress_percentage: 100, current_step: None, }; + flow2.current_step = flow2.steps.last().cloned(); + let mut flow3 = Flow { id: "flow-3".to_string(), - name: "Server Maintenance".to_string(), - description: "Perform server maintenance".to_string(), - flow_type: FlowType::PaymentProcessing, + name: "Sustainable Tourism Certification".to_string(), + description: "Application process for ZAZ Sustainable Tourism Certification for eco-tourism businesses".to_string(), + flow_type: FlowType::Certification, status: FlowStatus::Stuck, - owner_id: "user-1".to_string(), - owner_name: "John Doe".to_string(), + owner_id: "user-3".to_string(), + owner_name: "Hassan Mwinyi".to_string(), steps: vec![ FlowStep { id: "step-3-1".to_string(), - name: "Backup".to_string(), - description: "Backup the server".to_string(), + name: "Initial Application".to_string(), + description: "Submission of initial application and supporting documentation".to_string(), order: 1, status: StepStatus::Completed, - started_at: Some(Utc::now() - Duration::days(2)), - completed_at: Some(Utc::now() - Duration::days(2) + Duration::hours(1)), + started_at: Some(Utc::now() - Duration::days(15)), + completed_at: Some(Utc::now() - Duration::days(12)), logs: vec![ FlowLog { id: "log-3-1-1".to_string(), - message: "Backup started".to_string(), - timestamp: Utc::now() - Duration::days(2), + message: "Application submitted for Coral Reef Eco Tours".to_string(), + timestamp: Utc::now() - Duration::days(15), }, FlowLog { id: "log-3-1-2".to_string(), - message: "Backup completed successfully".to_string(), - timestamp: Utc::now() - Duration::days(2) + Duration::hours(1), + message: "Application fee payment confirmed".to_string(), + timestamp: Utc::now() - Duration::days(14), + }, + FlowLog { + id: "log-3-1-3".to_string(), + message: "Initial documentation review completed".to_string(), + timestamp: Utc::now() - Duration::days(12), }, ], }, FlowStep { id: "step-3-2".to_string(), - name: "Update".to_string(), - description: "Update the server".to_string(), + name: "Environmental Impact Assessment".to_string(), + description: "Assessment of the business's environmental impact and sustainability practices".to_string(), order: 2, status: StepStatus::Stuck, - started_at: Some(Utc::now() - Duration::days(2) + Duration::hours(2)), + started_at: Some(Utc::now() - Duration::days(11)), completed_at: None, logs: vec![ FlowLog { id: "log-3-2-1".to_string(), - message: "Update started".to_string(), - timestamp: Utc::now() - Duration::days(2) + Duration::hours(2), + message: "Environmental assessment initiated".to_string(), + timestamp: Utc::now() - Duration::days(11), }, FlowLog { id: "log-3-2-2".to_string(), - message: "Update failed: Disk space issue".to_string(), - timestamp: Utc::now() - Duration::days(2) + Duration::hours(3), + message: "Site visit scheduled with environmental officer".to_string(), + timestamp: Utc::now() - Duration::days(9), + }, + FlowLog { + id: "log-3-2-3".to_string(), + message: "STUCK: Missing required marine conservation plan documentation".to_string(), + timestamp: Utc::now() - Duration::days(7), }, ], }, FlowStep { id: "step-3-3".to_string(), - name: "Restart".to_string(), - description: "Restart the server".to_string(), + name: "Community Engagement Verification".to_string(), + description: "Verification of community engagement and benefit-sharing mechanisms".to_string(), order: 3, status: StepStatus::Pending, started_at: None, completed_at: None, logs: vec![], }, + FlowStep { + id: "step-3-4".to_string(), + name: "Certification Issuance".to_string(), + description: "Final review and issuance of ZAZ Sustainable Tourism Certification".to_string(), + order: 4, + status: StepStatus::Pending, + started_at: None, + completed_at: None, + logs: vec![], + }, ], - created_at: Utc::now() - Duration::days(2), - updated_at: Utc::now() - Duration::days(2) + Duration::hours(3), + created_at: Utc::now() - Duration::days(15), + updated_at: Utc::now() - Duration::days(7), completed_at: None, - progress_percentage: 33, + progress_percentage: 35, current_step: None, }; - // Update the current step flow3.current_step = flow3.steps.iter().find(|s| s.status == StepStatus::Stuck).cloned(); + let mut flow4 = Flow { + id: "flow-4".to_string(), + name: "Digital Payment Provider License".to_string(), + description: "Application for a license to operate as a digital payment provider within the ZAZ financial system".to_string(), + flow_type: FlowType::LicenseApplication, + status: FlowStatus::InProgress, + owner_id: "user-4".to_string(), + owner_name: "Fatma Busaidy".to_string(), + steps: vec![ + FlowStep { + id: "step-4-1".to_string(), + name: "Initial Application".to_string(), + description: "Submission of license application and company information".to_string(), + order: 1, + status: StepStatus::Completed, + started_at: Some(Utc::now() - Duration::days(20)), + completed_at: Some(Utc::now() - Duration::days(18)), + logs: vec![ + FlowLog { + id: "log-4-1-1".to_string(), + message: "Application submitted for ZanziPay digital payment services".to_string(), + timestamp: Utc::now() - Duration::days(20), + }, + FlowLog { + id: "log-4-1-2".to_string(), + message: "Application fee payment confirmed".to_string(), + timestamp: Utc::now() - Duration::days(19), + }, + FlowLog { + id: "log-4-1-3".to_string(), + message: "Initial documentation review completed".to_string(), + timestamp: Utc::now() - Duration::days(18), + }, + ], + }, + FlowStep { + id: "step-4-2".to_string(), + name: "Technical Infrastructure Review".to_string(), + description: "Review of the technical infrastructure, security measures, and compliance with ZAZ financial standards".to_string(), + order: 2, + status: StepStatus::Completed, + started_at: Some(Utc::now() - Duration::days(17)), + completed_at: Some(Utc::now() - Duration::days(10)), + logs: vec![ + FlowLog { + id: "log-4-2-1".to_string(), + message: "Technical documentation submitted for review".to_string(), + timestamp: Utc::now() - Duration::days(17), + }, + FlowLog { + id: "log-4-2-2".to_string(), + message: "Security audit initiated by ZAZ Financial Technology Office".to_string(), + timestamp: Utc::now() - Duration::days(15), + }, + FlowLog { + id: "log-4-2-3".to_string(), + message: "Technical infrastructure approved with recommendations".to_string(), + timestamp: Utc::now() - Duration::days(10), + }, + ], + }, + FlowStep { + id: "step-4-3".to_string(), + name: "AML/KYC Compliance Review".to_string(), + description: "Review of anti-money laundering and know-your-customer procedures".to_string(), + order: 3, + status: StepStatus::InProgress, + started_at: Some(Utc::now() - Duration::days(9)), + completed_at: None, + logs: vec![ + FlowLog { + id: "log-4-3-1".to_string(), + message: "AML/KYC documentation submitted for review".to_string(), + timestamp: Utc::now() - Duration::days(9), + }, + FlowLog { + id: "log-4-3-2".to_string(), + message: "Initial compliance assessment completed".to_string(), + timestamp: Utc::now() - Duration::days(5), + }, + FlowLog { + id: "log-4-3-3".to_string(), + message: "Additional KYC procedure documentation requested".to_string(), + timestamp: Utc::now() - Duration::days(3), + }, + ], + }, + FlowStep { + id: "step-4-4".to_string(), + name: "License Issuance".to_string(), + description: "Final review and issuance of Digital Payment Provider License".to_string(), + order: 4, + status: StepStatus::Pending, + started_at: None, + completed_at: None, + logs: vec![], + }, + ], + created_at: Utc::now() - Duration::days(20), + updated_at: Utc::now() - Duration::days(3), + completed_at: None, + progress_percentage: 65, + current_step: None, + }; + + flow4.current_step = flow4.steps.iter().find(|s| s.status == StepStatus::InProgress).cloned(); + flows.push(flow1); flows.push(flow2); flows.push(flow3); + flows.push(flow4); flows } diff --git a/actix_mvc_app/src/controllers/governance.rs b/actix_mvc_app/src/controllers/governance.rs index c77004f..f1eb61c 100644 --- a/actix_mvc_app/src/controllers/governance.rs +++ b/actix_mvc_app/src/controllers/governance.rs @@ -228,9 +228,9 @@ impl GovernanceController { Proposal { id: "prop-001".to_string(), creator_id: 1, - creator_name: "John Doe".to_string(), - title: "Implement Community Rewards Program".to_string(), - description: "This proposal aims to implement a community rewards program to incentivize active participation in the platform.".to_string(), + creator_name: "Ibrahim Faraji".to_string(), + title: "Establish Zanzibar Digital Trade Hub".to_string(), + description: "This proposal aims to create a dedicated digital trade hub within the Zanzibar Autonomous Zone to facilitate international e-commerce for local businesses. The hub will provide logistics support, digital marketing services, and regulatory compliance assistance to help Zanzibar businesses reach global markets.".to_string(), status: ProposalStatus::Active, created_at: now - Duration::days(5), updated_at: now - Duration::days(5), @@ -240,9 +240,9 @@ impl GovernanceController { Proposal { id: "prop-002".to_string(), creator_id: 2, - creator_name: "Jane Smith".to_string(), - title: "Platform UI Redesign".to_string(), - description: "A comprehensive redesign of the platform's user interface to improve usability and accessibility.".to_string(), + creator_name: "Amina Salim".to_string(), + title: "ZAZ Sustainable Tourism Framework".to_string(), + description: "A comprehensive framework for sustainable tourism development within the Zanzibar Autonomous Zone. This proposal outlines environmental standards, community benefit-sharing mechanisms, and digital infrastructure for eco-tourism businesses. It includes tokenization standards for tourism assets and a certification system for sustainable operators.".to_string(), status: ProposalStatus::Approved, created_at: now - Duration::days(15), updated_at: now - Duration::days(2), @@ -252,9 +252,9 @@ impl GovernanceController { Proposal { id: "prop-003".to_string(), creator_id: 3, - creator_name: "Bob Johnson".to_string(), - title: "Add Support for Mobile Notifications".to_string(), - description: "Implement push notifications for mobile users to improve engagement and user experience.".to_string(), + creator_name: "Hassan Mwinyi".to_string(), + title: "Spice Industry Modernization Initiative".to_string(), + description: "This proposal seeks to modernize Zanzibar's traditional spice industry through blockchain-based supply chain tracking, international quality certification, and digital marketplace integration. The initiative will help local spice farmers and processors access premium international markets while preserving traditional cultivation methods.".to_string(), status: ProposalStatus::Draft, created_at: now - Duration::days(1), updated_at: now - Duration::days(1), @@ -264,9 +264,9 @@ impl GovernanceController { Proposal { id: "prop-004".to_string(), creator_id: 1, - creator_name: "John Doe".to_string(), - title: "Integrate with Third-party Payment Providers".to_string(), - description: "Add support for additional payment providers to give users more options for transactions.".to_string(), + creator_name: "Ibrahim Faraji".to_string(), + title: "ZAZ Regulatory Framework for Digital Financial Services".to_string(), + description: "Establish a comprehensive regulatory framework for digital financial services within the Zanzibar Autonomous Zone. This includes licensing requirements for crypto exchanges, digital payment providers, and tokenized asset platforms operating within the zone, while ensuring compliance with international AML/KYC standards.".to_string(), status: ProposalStatus::Rejected, created_at: now - Duration::days(20), updated_at: now - Duration::days(5), @@ -276,15 +276,39 @@ impl GovernanceController { Proposal { id: "prop-005".to_string(), creator_id: 4, - creator_name: "Alice Williams".to_string(), - title: "Implement Two-Factor Authentication".to_string(), - description: "Enhance security by implementing two-factor authentication for all user accounts.".to_string(), + creator_name: "Fatma Busaidy".to_string(), + title: "Digital Arts Incubator and NFT Marketplace".to_string(), + description: "Create a dedicated digital arts incubator and NFT marketplace to support Zanzibar's creative economy. The initiative will provide technical training, equipment, and a curated marketplace for local artists to create and sell digital art that celebrates Zanzibar's rich cultural heritage while accessing global markets.".to_string(), status: ProposalStatus::Active, created_at: now - Duration::days(7), updated_at: now - Duration::days(7), voting_starts_at: Some(now - Duration::days(6)), voting_ends_at: Some(now + Duration::days(1)), }, + Proposal { + id: "prop-006".to_string(), + creator_id: 5, + creator_name: "Omar Makame".to_string(), + title: "Zanzibar Renewable Energy Microgrid Network".to_string(), + description: "Develop a network of renewable energy microgrids across the Zanzibar Autonomous Zone using tokenized investment and community ownership models. This proposal outlines the technical specifications, governance structure, and token economics for deploying solar and tidal energy systems that will ensure energy independence for the zone.".to_string(), + status: ProposalStatus::Active, + created_at: now - Duration::days(10), + updated_at: now - Duration::days(9), + voting_starts_at: Some(now - Duration::days(8)), + voting_ends_at: Some(now + Duration::days(6)), + }, + Proposal { + id: "prop-007".to_string(), + creator_id: 6, + creator_name: "Saida Juma".to_string(), + title: "ZAZ Educational Technology Initiative".to_string(), + description: "Establish a comprehensive educational technology program within the Zanzibar Autonomous Zone to develop local tech talent. This initiative includes coding academies, blockchain development courses, and digital entrepreneurship training, with a focus on preparing Zanzibar's youth for careers in the zone's growing digital economy.".to_string(), + status: ProposalStatus::Draft, + created_at: now - Duration::days(3), + updated_at: now - Duration::days(2), + voting_starts_at: None, + voting_ends_at: None, + }, ] } @@ -301,7 +325,7 @@ impl GovernanceController { id: "vote-001".to_string(), proposal_id: proposal_id.to_string(), voter_id: 1, - voter_name: "John Doe".to_string(), + voter_name: "Robert Callingham".to_string(), vote_type: VoteType::Yes, comment: Some("I strongly support this initiative.".to_string()), created_at: now - Duration::days(2), @@ -347,7 +371,7 @@ impl GovernanceController { id: "vote-001".to_string(), proposal_id: "prop-001".to_string(), voter_id: user_id, - voter_name: "John Doe".to_string(), + voter_name: "Robert Callingham".to_string(), vote_type: VoteType::Yes, comment: Some("I strongly support this initiative.".to_string()), created_at: Utc::now() - Duration::days(2), @@ -357,7 +381,7 @@ impl GovernanceController { id: "vote-005".to_string(), proposal_id: "prop-002".to_string(), voter_id: user_id, - voter_name: "John Doe".to_string(), + voter_name: "Robert Callingham".to_string(), vote_type: VoteType::No, comment: Some("I don't think this is a priority right now.".to_string()), created_at: Utc::now() - Duration::days(10), @@ -367,7 +391,7 @@ impl GovernanceController { id: "vote-008".to_string(), proposal_id: "prop-004".to_string(), voter_id: user_id, - voter_name: "John Doe".to_string(), + voter_name: "Robert Callingham".to_string(), vote_type: VoteType::Yes, comment: None, created_at: Utc::now() - Duration::days(18), @@ -377,7 +401,7 @@ impl GovernanceController { id: "vote-010".to_string(), proposal_id: "prop-005".to_string(), voter_id: user_id, - voter_name: "John Doe".to_string(), + voter_name: "Robert Callingham".to_string(), vote_type: VoteType::Yes, comment: Some("Security is always a top priority.".to_string()), created_at: Utc::now() - Duration::days(5), diff --git a/actix_mvc_app/src/models/contract.rs b/actix_mvc_app/src/models/contract.rs index 7520a83..b4735da 100644 --- a/actix_mvc_app/src/models/contract.rs +++ b/actix_mvc_app/src/models/contract.rs @@ -8,6 +8,7 @@ pub enum ContractStatus { Draft, PendingSignatures, Signed, + Active, Expired, Cancelled } @@ -18,6 +19,7 @@ impl ContractStatus { ContractStatus::Draft => "Draft", ContractStatus::PendingSignatures => "Pending Signatures", ContractStatus::Signed => "Signed", + ContractStatus::Active => "Active", ContractStatus::Expired => "Expired", ContractStatus::Cancelled => "Cancelled", } @@ -31,6 +33,10 @@ pub enum ContractType { Employment, NDA, SLA, + Partnership, + Distribution, + License, + Membership, Other } @@ -41,6 +47,10 @@ impl ContractType { ContractType::Employment => "Employment Contract", ContractType::NDA => "Non-Disclosure Agreement", ContractType::SLA => "Service Level Agreement", + ContractType::Partnership => "Partnership Agreement", + ContractType::Distribution => "Distribution Agreement", + ContractType::License => "License Agreement", + ContractType::Membership => "Membership Agreement", ContractType::Other => "Other", } } diff --git a/actix_mvc_app/src/models/flow.rs b/actix_mvc_app/src/models/flow.rs index 0d03b4b..6feab01 100644 --- a/actix_mvc_app/src/models/flow.rs +++ b/actix_mvc_app/src/models/flow.rs @@ -37,6 +37,12 @@ pub enum FlowType { ServiceActivation, /// Payment processing flow PaymentProcessing, + /// Asset tokenization flow + AssetTokenization, + /// Certification flow + Certification, + /// License application flow + LicenseApplication, } impl std::fmt::Display for FlowType { @@ -46,6 +52,9 @@ impl std::fmt::Display for FlowType { FlowType::UserOnboarding => write!(f, "User Onboarding"), FlowType::ServiceActivation => write!(f, "Service Activation"), FlowType::PaymentProcessing => write!(f, "Payment Processing"), + FlowType::AssetTokenization => write!(f, "Asset Tokenization"), + FlowType::Certification => write!(f, "Certification"), + FlowType::LicenseApplication => write!(f, "License Application"), } } } diff --git a/actix_mvc_app/src/models/user.rs b/actix_mvc_app/src/models/user.rs index 1d98865..aec201f 100644 --- a/actix_mvc_app/src/models/user.rs +++ b/actix_mvc_app/src/models/user.rs @@ -145,8 +145,8 @@ mod tests { #[test] fn test_new_user() { - let user = User::new("John Doe".to_string(), "john@example.com".to_string()); - assert_eq!(user.name, "John Doe"); + let user = User::new("Robert Callingham".to_string(), "john@example.com".to_string()); + assert_eq!(user.name, "Robert Callingham"); assert_eq!(user.email, "john@example.com"); assert!(!user.is_admin()); } @@ -161,13 +161,13 @@ mod tests { #[test] fn test_update_user() { - let mut user = User::new("John Doe".to_string(), "john@example.com".to_string()); - user.update(Some("Jane Doe".to_string()), None); - assert_eq!(user.name, "Jane Doe"); + let mut user = User::new("Robert Callingham".to_string(), "john@example.com".to_string()); + user.update(Some("Mary Hewell".to_string()), None); + assert_eq!(user.name, "Mary Hewell"); assert_eq!(user.email, "john@example.com"); user.update(None, Some("jane@example.com".to_string())); - assert_eq!(user.name, "Jane Doe"); + assert_eq!(user.name, "Mary Hewell"); assert_eq!(user.email, "jane@example.com"); } } \ No newline at end of file diff --git a/actix_mvc_app/src/utils/mod.rs b/actix_mvc_app/src/utils/mod.rs index 7c053f9..129cdbc 100644 --- a/actix_mvc_app/src/utils/mod.rs +++ b/actix_mvc_app/src/utils/mod.rs @@ -1,6 +1,7 @@ use actix_web::{error, Error, HttpResponse}; use chrono::{DateTime, Utc}; use tera::{self, Context, Function, Tera, Value}; +use std::error::Error as StdError; // Export modules pub mod redis_service; @@ -137,39 +138,58 @@ pub fn render_template( Ok(HttpResponse::Ok().content_type("text/html").body(content)) }, Err(e) => { - // Log the error + // Log the error with more details println!("DEBUG: Template rendering error for {}: {}", template_name, e); + println!("DEBUG: Error details: {:?}", e); + // Print the error cause chain for better debugging + let mut current_error: Option<&dyn StdError> = Some(&e); + let mut error_chain = Vec::new(); + + while let Some(error) = current_error { + error_chain.push(format!("{}", error)); + current_error = error.source(); + } + + println!("DEBUG: Error chain: {:?}", error_chain); + + // Log the error log::error!("Template rendering error: {}", e); - // Create a simple error response instead of trying to render the error template + // Create a simple error response with more detailed information let error_html = format!( r#" Template Error
-

Template Rendering Error

-

Template: {}

-

Error:

-
{}
-

Return to Home

+

Template Rendering Error

+

There was an error rendering the template: {}

+
+

Error Details:

+
{}
+

Error Chain:

+
{}
+
"#, template_name, - e + e, + error_chain.join("\n") ); println!("DEBUG: Returning simple error page"); + Ok(HttpResponse::InternalServerError() .content_type("text/html") .body(error_html)) diff --git a/actix_mvc_app/src/views/contracts/contract_detail.html b/actix_mvc_app/src/views/contracts/contract_detail.html index ac8991e..0568c91 100644 --- a/actix_mvc_app/src/views/contracts/contract_detail.html +++ b/actix_mvc_app/src/views/contracts/contract_detail.html @@ -24,302 +24,309 @@ - -
-
-
-
-
Contract Overview
-
-
-
-
Status:
-
- - {{ contract.status }} - -
-
-
-
Type:
-
{{ contract.contract_type }}
-
-
-
Created By:
-
{{ contract.created_by }}
-
-
-
Created:
-
{{ contract.created_at }}
-
-
-
Last Updated:
-
{{ contract.updated_at }}
-
- {% if contract.effective_date %} -
-
Effective Date:
-
{{ contract.effective_date }}
-
- {% endif %} - {% if contract.expiration_date %} -
-
Expiration Date:
-
{{ contract.expiration_date }}
-
- {% endif %} -
-
Version:
-
{{ contract.current_version }}
-
-
-
Description:
-
{{ contract.description }}
-
-
-
-
-
-
-
-
Actions
-
-
-
- {% if contract.status == 'Draft' %} - - Edit Contract - - - Send for Signatures - - - {% elif contract.status == 'PendingSignatures' %} - - - - {% elif contract.status == 'Signed' %} - - - {% endif %} -
-
-
-
-
+ + - -
-
-
-
-
Contract Content
- {% if contract.revisions|length > 1 %} - - {% endif %} -
-
- {% if contract.revisions|length > 0 %} - {% set latest_revision = contract.latest_revision %} -
- {{ latest_revision.content|safe }} -
-
-

Last updated by {{ latest_revision.created_by }} on {{ latest_revision.created_at }}

- {% if latest_revision.comments %} -

Comments: {{ latest_revision.comments }}

+
+ +
+
+
+ +
+
+
Contract Document
+ {% if contract.status == 'Signed' %} + SIGNED + {% elif contract.status == 'Active' %} + ACTIVE + {% elif contract.status == 'PendingSignatures' %} + PENDING + {% elif contract.status == 'Draft' %} + DRAFT {% endif %}
- {% else %} -
-

No content has been added to this contract yet.

- {% if contract.status == 'Draft' %} - - Add Content - +
+ {% if contract.revisions|length > 0 %} + {% set latest_revision = contract.latest_revision %} +
+ {{ latest_revision.content|safe }} +
+ {% else %} +
+

No content has been added to this contract yet.

+
{% endif %}
- {% endif %} -
-
-
-
- - -
-
-
-
-
Signers
- {% if contract.status == 'Draft' %} - - {% endif %} -
-
- {% if contract.signers|length > 0 %} -
- - - - - - - - - {% if contract.status == 'Draft' %} - - {% endif %} - - - + + + +
+
+
Signatures
+
+
+
{% for signer in contract.signers %} -
- - - - - - {% if contract.status == 'Draft' %} - - {% endif %} - +
+
+
+
{{ signer.name }}
+ + {{ signer.status }} + +
+
+

{{ signer.email }}

+ + {% if signer.status == 'Signed' %} +
+ Signature +
Signed on {{ signer.signed_at }}
+
+ {% elif signer.status == 'Rejected' %} +
+ Rejected on {{ signer.signed_at }} +
+ {% else %} +
+

Waiting for signature...

+ {% if not user_has_signed %} + + {% endif %} +
+ {% endif %} + + {% if signer.comments %} +
+

Comments:

+

{{ signer.comments }}

+
+ {% endif %} +
+
+
{% endfor %} - -
NameEmailStatusSigned DateCommentsActions
{{ signer.name }}{{ signer.email }} - - {{ signer.status }} - - - {% if signer.signed_at %} - {{ signer.signed_at }} - {% else %} - - - {% endif %} - - {% if signer.comments %} - {{ signer.comments }} - {% else %} - - - {% endif %} - - -
+
+
- {% else %} -
-

No signers have been added to this contract yet.

- {% if contract.status == 'Draft' %} - - {% endif %} +
+ +
+
+
+
Actions
+
+
+
+ {% if contract.status == 'Draft' %} + + Edit Contract + + + Send for Signatures + + + {% elif contract.status == 'PendingSignatures' %} + + + + {% elif contract.status == 'Signed' or contract.status == 'Active' %} + + + {% endif %} +
+
+
+ +
+
+
Signers Status
+
+
+
    + {% for signer in contract.signers %} +
  • +
    +
    {{ signer.name }}
    + {{ signer.email }} +
    + + {{ signer.status }} + +
  • + {% endfor %} +
+
+ +
+ +
+
+
Contract Info
+
+
+

Status: + + {{ contract.status }} + +

+

Type: {{ contract.contract_type }}

+

Created: {{ contract.created_at }}

+

Version: {{ contract.current_version }}

+ {% if contract.effective_date %} +

Effective: {{ contract.effective_date }}

+ {% endif %} + {% if contract.expiration_date %} +

Expires: {{ contract.expiration_date }}

+ {% endif %} + {% if contract.organization %} +

Organization: {{ contract.organization }}

+ {% endif %} +
- {% endif %}
-
- - -
-
-
Contract Revisions
-
-
- {% if contract.revisions|length > 0 %} -
- - - - - - - - - - - {% for revision in contract.revisions %} - - - - - - - {% endfor %} - -
VersionDateNotesActions
{{ revision.version }}{{ revision.created_at }}{{ revision.notes }} - - View - -
+ + +
+
+
+
+
+
Contract Overview
+
+
+
+
Status:
+
+ + {{ contract.status }} + +
+
+
+
Type:
+
{{ contract.contract_type }}
+
+
+
Created By:
+
{{ contract.created_by }}
+
+
+
Created:
+
{{ contract.created_at }}
+
+
+
Last Updated:
+
{{ contract.updated_at }}
+
+ {% if contract.effective_date %} +
+
Effective Date:
+
{{ contract.effective_date }}
+
+ {% endif %} + {% if contract.expiration_date %} +
+
Expiration Date:
+
{{ contract.expiration_date }}
+
+ {% endif %} +
+
Version:
+
{{ contract.current_version }}
+
+
+
Description:
+
{{ contract.description }}
+
+
+
+
+
+
+
+
Organization
+
+
+ {% if contract.organization %} +

{{ contract.organization }}

+

+ Registered in Zanzibar Autonomous Zone +

+ {% else %} +

No organization specified

+ {% endif %} +
+
+
- {% else %} -

No revisions available.

- {% endif %} -
-
- - -
-
-
+ + +
-
Revision History
+
Contract Revisions
{% if contract.revisions|length > 0 %}
- +
+ - - + - {% for revision in contract.revisions|reverse %} + {% for revision in contract.revisions %} - + + - @@ -328,13 +335,213 @@
VersionDate Created ByCreated DateCommentsNotes Actions
{{ revision.version }}{{ revision.created_by }} {{ revision.created_at }}{{ revision.created_by }}{{ revision.notes }} - {% if revision.comments %} - {{ revision.comments }} - {% else %} - - - {% endif %} - - - + + View
{% else %} -
-

No revisions have been made to this contract yet.

-
+

No revisions available.

{% endif %}
+ + +
+
+
+
Activity Timeline
+
+
+
    +
  • +
    +
    Contract Created
    + {{ contract.created_at }} +
    +

    {{ contract.created_by }} created this contract

    +
  • + + {% for revision in contract.revisions %} + {% if revision.version > 1 %} +
  • +
    +
    Contract Updated to Version {{ revision.version }}
    + {{ revision.created_at }} +
    +

    {{ revision.created_by }} updated the contract

    + {% if revision.notes %} +

    {{ revision.notes }}

    + {% endif %} +
  • + {% endif %} + {% endfor %} + + {% for signer in contract.signers %} + {% if signer.status == 'Signed' %} +
  • +
    +
    Contract Signed
    + {{ signer.signed_at }} +
    +

    {{ signer.name }} signed the contract

    + {% if signer.comments %} +

    {{ signer.comments }}

    + {% endif %} +
  • + {% endif %} + {% endfor %} + + {% if contract.status == 'Active' %} +
  • +
    +
    Contract Activated
    + {{ contract.updated_at }} +
    +

    Contract became active after all parties signed

    +
  • + {% endif %} +
+
+
+
+
+
+ + + {% endblock %} + +{% block scripts %} + +{% endblock %}