Merge branch 'development_add_incremental_mode_to_heromodels'
This commit is contained in:
		
							
								
								
									
										524
									
								
								heromodels/src/models/governance/activity.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										524
									
								
								heromodels/src/models/governance/activity.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,524 @@
 | 
			
		||||
// heromodels/src/models/governance/activity.rs
 | 
			
		||||
 | 
			
		||||
use chrono::{DateTime, Utc};
 | 
			
		||||
use heromodels_derive::model;
 | 
			
		||||
use rhai::{CustomType, TypeBuilder};
 | 
			
		||||
use rhai_autobind_macros::rhai_model_export;
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
// use std::collections::HashMap;
 | 
			
		||||
 | 
			
		||||
use heromodels_core::BaseModelData;
 | 
			
		||||
 | 
			
		||||
/// ActivityType defines the different types of governance activities that can be tracked
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
 | 
			
		||||
pub enum ActivityType {
 | 
			
		||||
    ProposalCreated,
 | 
			
		||||
    ProposalStatusChanged,
 | 
			
		||||
    VotingStarted,
 | 
			
		||||
    VotingEnded,
 | 
			
		||||
    VoteCast,
 | 
			
		||||
    VoteOptionAdded,
 | 
			
		||||
    ProposalDeleted,
 | 
			
		||||
    Custom,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for ActivityType {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        ActivityType::Custom
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// ActivityStatus defines the status of an activity
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
 | 
			
		||||
pub enum ActivityStatus {
 | 
			
		||||
    Pending,    // Activity is scheduled but not yet executed
 | 
			
		||||
    InProgress, // Activity is currently being executed
 | 
			
		||||
    Completed,  // Activity has been successfully completed
 | 
			
		||||
    Failed,     // Activity failed to complete
 | 
			
		||||
    Cancelled,  // Activity was cancelled before completion
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for ActivityStatus {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        ActivityStatus::Completed
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// GovernanceActivity represents a single activity or event in the governance system
 | 
			
		||||
/// This model tracks all significant actions and changes for audit and transparency purposes
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize, CustomType)]
 | 
			
		||||
#[rhai_model_export(db_type = "std::sync::Arc<crate::db::hero::OurDB>")]
 | 
			
		||||
#[model]
 | 
			
		||||
pub struct GovernanceActivity {
 | 
			
		||||
    pub base_data: BaseModelData,
 | 
			
		||||
 | 
			
		||||
    /// Type of activity that occurred
 | 
			
		||||
    pub activity_type: ActivityType,
 | 
			
		||||
 | 
			
		||||
    /// Status of the activity
 | 
			
		||||
    pub status: ActivityStatus,
 | 
			
		||||
 | 
			
		||||
    /// ID of the user who initiated this activity (if applicable)
 | 
			
		||||
    pub actor_id: Option<String>,
 | 
			
		||||
 | 
			
		||||
    /// Name of the user who initiated this activity (for display purposes)
 | 
			
		||||
    pub actor_name: Option<String>,
 | 
			
		||||
 | 
			
		||||
    /// ID of the target object (e.g., proposal_id, ballot_id, etc.)
 | 
			
		||||
    pub target_id: Option<u32>,
 | 
			
		||||
 | 
			
		||||
    /// Type of the target object (e.g., "proposal", "ballot", "vote_option")
 | 
			
		||||
    pub target_type: Option<String>,
 | 
			
		||||
 | 
			
		||||
    /// Title or brief description of the activity
 | 
			
		||||
    pub title: String,
 | 
			
		||||
 | 
			
		||||
    /// Detailed description of what happened
 | 
			
		||||
    pub description: String,
 | 
			
		||||
 | 
			
		||||
    /// Additional metadata as a simple string
 | 
			
		||||
    pub metadata: String,
 | 
			
		||||
 | 
			
		||||
    /// When the activity occurred
 | 
			
		||||
    pub occurred_at: DateTime<Utc>,
 | 
			
		||||
 | 
			
		||||
    /// When the activity was recorded in the system
 | 
			
		||||
    pub recorded_at: DateTime<Utc>,
 | 
			
		||||
 | 
			
		||||
    /// Optional reference to related activities
 | 
			
		||||
    pub related_activity_ids: Vec<u32>,
 | 
			
		||||
 | 
			
		||||
    /// Tags for categorization and filtering
 | 
			
		||||
    pub tags: Vec<String>,
 | 
			
		||||
 | 
			
		||||
    /// Severity level of the activity (for filtering and alerting)
 | 
			
		||||
    pub severity: ActivitySeverity,
 | 
			
		||||
 | 
			
		||||
    /// Whether this activity should be publicly visible
 | 
			
		||||
    pub is_public: bool,
 | 
			
		||||
 | 
			
		||||
    /// Optional expiration date for temporary activities
 | 
			
		||||
    pub expires_at: Option<DateTime<Utc>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// ActivitySeverity defines the importance level of an activity
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
 | 
			
		||||
pub enum ActivitySeverity {
 | 
			
		||||
    Low,      // Routine activities
 | 
			
		||||
    Normal,   // Standard activities
 | 
			
		||||
    High,     // Important activities
 | 
			
		||||
    Critical, // Critical activities that require attention
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for ActivitySeverity {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        ActivitySeverity::Normal
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl GovernanceActivity {
 | 
			
		||||
    /// Create a new governance activity with auto-generated ID
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Arguments
 | 
			
		||||
    /// * `id` - Optional ID for the activity (use None for auto-generated ID)
 | 
			
		||||
    /// * `activity_type` - Type of activity that occurred
 | 
			
		||||
    /// * `title` - Brief title of the activity
 | 
			
		||||
    /// * `description` - Detailed description of the activity
 | 
			
		||||
    /// * `actor_id` - Optional ID of the user who initiated the activity
 | 
			
		||||
    /// * `actor_name` - Optional name of the user who initiated the activity
 | 
			
		||||
    pub fn new(
 | 
			
		||||
        id: Option<u32>,
 | 
			
		||||
        activity_type: ActivityType,
 | 
			
		||||
        title: impl ToString,
 | 
			
		||||
        description: impl ToString,
 | 
			
		||||
        actor_id: Option<impl ToString>,
 | 
			
		||||
        actor_name: Option<impl ToString>,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        let mut base_data = BaseModelData::new();
 | 
			
		||||
        if let Some(id) = id {
 | 
			
		||||
            base_data.update_id(id);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let now = Utc::now();
 | 
			
		||||
 | 
			
		||||
        Self {
 | 
			
		||||
            base_data,
 | 
			
		||||
            activity_type,
 | 
			
		||||
            status: ActivityStatus::Completed,
 | 
			
		||||
            actor_id: actor_id.map(|id| id.to_string()),
 | 
			
		||||
            actor_name: actor_name.map(|name| name.to_string()),
 | 
			
		||||
            target_id: None,
 | 
			
		||||
            target_type: None,
 | 
			
		||||
            title: title.to_string(),
 | 
			
		||||
            description: description.to_string(),
 | 
			
		||||
            metadata: String::new(),
 | 
			
		||||
            occurred_at: now,
 | 
			
		||||
            recorded_at: now,
 | 
			
		||||
            related_activity_ids: Vec::new(),
 | 
			
		||||
            tags: Vec::new(),
 | 
			
		||||
            severity: ActivitySeverity::Normal,
 | 
			
		||||
            is_public: true,
 | 
			
		||||
            expires_at: None,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Set the target of this activity
 | 
			
		||||
    pub fn with_target(mut self, target_id: u32, target_type: impl ToString) -> Self {
 | 
			
		||||
        self.target_id = Some(target_id);
 | 
			
		||||
        self.target_type = Some(target_type.to_string());
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Set the status of this activity
 | 
			
		||||
    pub fn with_status(mut self, status: ActivityStatus) -> Self {
 | 
			
		||||
        self.status = status;
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Set the severity of this activity
 | 
			
		||||
    pub fn with_severity(mut self, severity: ActivitySeverity) -> Self {
 | 
			
		||||
        self.severity = severity;
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Set the occurred_at timestamp
 | 
			
		||||
    pub fn with_occurred_at(mut self, occurred_at: DateTime<Utc>) -> Self {
 | 
			
		||||
        self.occurred_at = occurred_at;
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Add metadata to this activity
 | 
			
		||||
    pub fn with_metadata(mut self, key: impl ToString, value: impl ToString) -> Self {
 | 
			
		||||
        if !self.metadata.is_empty() {
 | 
			
		||||
            self.metadata.push_str(", ");
 | 
			
		||||
        }
 | 
			
		||||
        self.metadata
 | 
			
		||||
            .push_str(&format!("{}={}", key.to_string(), value.to_string()));
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Add a tag to this activity
 | 
			
		||||
    pub fn with_tag(mut self, tag: impl ToString) -> Self {
 | 
			
		||||
        let tag_str = tag.to_string();
 | 
			
		||||
        if !self.tags.contains(&tag_str) {
 | 
			
		||||
            self.tags.push(tag_str);
 | 
			
		||||
        }
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Add multiple tags to this activity
 | 
			
		||||
    pub fn with_tags(mut self, tags: Vec<String>) -> Self {
 | 
			
		||||
        for tag in tags {
 | 
			
		||||
            if !self.tags.contains(&tag) {
 | 
			
		||||
                self.tags.push(tag);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Set whether this activity is public
 | 
			
		||||
    pub fn with_visibility(mut self, is_public: bool) -> Self {
 | 
			
		||||
        self.is_public = is_public;
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Set an expiration date for this activity
 | 
			
		||||
    pub fn with_expiration(mut self, expires_at: DateTime<Utc>) -> Self {
 | 
			
		||||
        self.expires_at = Some(expires_at);
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Add a related activity ID
 | 
			
		||||
    pub fn with_related_activity(mut self, activity_id: u32) -> Self {
 | 
			
		||||
        if !self.related_activity_ids.contains(&activity_id) {
 | 
			
		||||
            self.related_activity_ids.push(activity_id);
 | 
			
		||||
        }
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Check if this activity has expired
 | 
			
		||||
    pub fn is_expired(&self) -> bool {
 | 
			
		||||
        if let Some(expires_at) = self.expires_at {
 | 
			
		||||
            Utc::now() > expires_at
 | 
			
		||||
        } else {
 | 
			
		||||
            false
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Get a formatted summary of this activity
 | 
			
		||||
    pub fn summary(&self) -> String {
 | 
			
		||||
        format!(
 | 
			
		||||
            "[{}] {} - {} (by {})",
 | 
			
		||||
            self.occurred_at.format("%Y-%m-%d %H:%M:%S UTC"),
 | 
			
		||||
            self.title,
 | 
			
		||||
            self.description,
 | 
			
		||||
            self.actor_name.as_deref().unwrap_or("System")
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Factory methods for creating common governance activities
 | 
			
		||||
impl GovernanceActivity {
 | 
			
		||||
    /// Create an activity for proposal creation
 | 
			
		||||
    pub fn proposal_created(
 | 
			
		||||
        proposal_id: u32,
 | 
			
		||||
        proposal_title: impl ToString,
 | 
			
		||||
        creator_id: impl ToString,
 | 
			
		||||
        creator_name: impl ToString,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        let creator_name_str = creator_name.to_string();
 | 
			
		||||
        let proposal_title_str = proposal_title.to_string();
 | 
			
		||||
 | 
			
		||||
        Self::new(
 | 
			
		||||
            None,
 | 
			
		||||
            ActivityType::ProposalCreated,
 | 
			
		||||
            format!("{} created a new proposal", creator_name_str),
 | 
			
		||||
            format!(
 | 
			
		||||
                "{} created a new proposal titled '{}' for community consideration",
 | 
			
		||||
                creator_name_str, proposal_title_str
 | 
			
		||||
            ),
 | 
			
		||||
            Some(creator_id),
 | 
			
		||||
            Some(creator_name_str),
 | 
			
		||||
        )
 | 
			
		||||
        .with_target(proposal_id, "proposal")
 | 
			
		||||
        .with_metadata("proposal_title", proposal_title_str)
 | 
			
		||||
        .with_tag("proposal")
 | 
			
		||||
        .with_tag("creation")
 | 
			
		||||
        .with_severity(ActivitySeverity::Normal)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Create an activity for proposal status change
 | 
			
		||||
    pub fn proposal_status_changed(
 | 
			
		||||
        proposal_id: u32,
 | 
			
		||||
        proposal_title: impl ToString,
 | 
			
		||||
        old_status: impl ToString,
 | 
			
		||||
        new_status: impl ToString,
 | 
			
		||||
        actor_id: Option<impl ToString>,
 | 
			
		||||
        actor_name: Option<impl ToString>,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        let proposal_title_str = proposal_title.to_string();
 | 
			
		||||
        let old_status_str = old_status.to_string();
 | 
			
		||||
        let new_status_str = new_status.to_string();
 | 
			
		||||
        let actor_name_str = actor_name
 | 
			
		||||
            .map(|n| n.to_string())
 | 
			
		||||
            .unwrap_or_else(|| "System".to_string());
 | 
			
		||||
 | 
			
		||||
        Self::new(
 | 
			
		||||
            None,
 | 
			
		||||
            ActivityType::ProposalStatusChanged,
 | 
			
		||||
            format!(
 | 
			
		||||
                "{} changed proposal status to {}",
 | 
			
		||||
                actor_name_str, new_status_str
 | 
			
		||||
            ),
 | 
			
		||||
            format!(
 | 
			
		||||
                "{} changed the status of proposal '{}' from {} to {}",
 | 
			
		||||
                actor_name_str, proposal_title_str, old_status_str, new_status_str
 | 
			
		||||
            ),
 | 
			
		||||
            actor_id,
 | 
			
		||||
            Some(actor_name_str),
 | 
			
		||||
        )
 | 
			
		||||
        .with_target(proposal_id, "proposal")
 | 
			
		||||
        .with_metadata("proposal_title", proposal_title_str)
 | 
			
		||||
        .with_metadata("old_status", old_status_str)
 | 
			
		||||
        .with_metadata("new_status", new_status_str)
 | 
			
		||||
        .with_tag("proposal")
 | 
			
		||||
        .with_tag("status_change")
 | 
			
		||||
        .with_severity(ActivitySeverity::High)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Create an activity for vote casting
 | 
			
		||||
    pub fn vote_cast(
 | 
			
		||||
        proposal_id: u32,
 | 
			
		||||
        proposal_title: impl ToString,
 | 
			
		||||
        ballot_id: u32,
 | 
			
		||||
        voter_id: impl ToString,
 | 
			
		||||
        voter_name: impl ToString,
 | 
			
		||||
        option_text: impl ToString,
 | 
			
		||||
        shares: i64,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        let voter_name_str = voter_name.to_string();
 | 
			
		||||
        let option_text_str = option_text.to_string();
 | 
			
		||||
        let proposal_title_str = proposal_title.to_string();
 | 
			
		||||
 | 
			
		||||
        // Create a more natural vote description
 | 
			
		||||
        let vote_description = if option_text_str.to_lowercase().contains("approve")
 | 
			
		||||
            || option_text_str.to_lowercase().contains("yes")
 | 
			
		||||
        {
 | 
			
		||||
            format!(
 | 
			
		||||
                "{} voted YES on proposal '{}'",
 | 
			
		||||
                voter_name_str, proposal_title_str
 | 
			
		||||
            )
 | 
			
		||||
        } else if option_text_str.to_lowercase().contains("reject")
 | 
			
		||||
            || option_text_str.to_lowercase().contains("no")
 | 
			
		||||
        {
 | 
			
		||||
            format!(
 | 
			
		||||
                "{} voted NO on proposal '{}'",
 | 
			
		||||
                voter_name_str, proposal_title_str
 | 
			
		||||
            )
 | 
			
		||||
        } else if option_text_str.to_lowercase().contains("abstain") {
 | 
			
		||||
            format!(
 | 
			
		||||
                "{} abstained from voting on proposal '{}'",
 | 
			
		||||
                voter_name_str, proposal_title_str
 | 
			
		||||
            )
 | 
			
		||||
        } else {
 | 
			
		||||
            format!(
 | 
			
		||||
                "{} voted '{}' on proposal '{}'",
 | 
			
		||||
                voter_name_str, option_text_str, proposal_title_str
 | 
			
		||||
            )
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        Self::new(
 | 
			
		||||
            None,
 | 
			
		||||
            ActivityType::VoteCast,
 | 
			
		||||
            format!("{} submitted a vote", voter_name_str),
 | 
			
		||||
            format!("{} with {} voting shares", vote_description, shares),
 | 
			
		||||
            Some(voter_id),
 | 
			
		||||
            Some(voter_name_str),
 | 
			
		||||
        )
 | 
			
		||||
        .with_target(proposal_id, "proposal")
 | 
			
		||||
        .with_metadata("ballot_id", ballot_id.to_string())
 | 
			
		||||
        .with_metadata("option_text", option_text_str)
 | 
			
		||||
        .with_metadata("shares", shares.to_string())
 | 
			
		||||
        .with_metadata("proposal_title", proposal_title_str)
 | 
			
		||||
        .with_tag("vote")
 | 
			
		||||
        .with_tag("ballot")
 | 
			
		||||
        .with_severity(ActivitySeverity::Normal)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Create an activity for voting period start
 | 
			
		||||
    pub fn voting_started(
 | 
			
		||||
        proposal_id: u32,
 | 
			
		||||
        proposal_title: impl ToString,
 | 
			
		||||
        start_date: DateTime<Utc>,
 | 
			
		||||
        end_date: DateTime<Utc>,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        let proposal_title_str = proposal_title.to_string();
 | 
			
		||||
 | 
			
		||||
        Self::new(
 | 
			
		||||
            None,
 | 
			
		||||
            ActivityType::VotingStarted,
 | 
			
		||||
            format!("Voting opened for '{}'", proposal_title_str),
 | 
			
		||||
            format!(
 | 
			
		||||
                "Community voting has opened for proposal '{}' and will close on {}",
 | 
			
		||||
                proposal_title_str,
 | 
			
		||||
                end_date.format("%B %d, %Y at %H:%M UTC")
 | 
			
		||||
            ),
 | 
			
		||||
            None::<String>,
 | 
			
		||||
            Some("System"),
 | 
			
		||||
        )
 | 
			
		||||
        .with_target(proposal_id, "proposal")
 | 
			
		||||
        .with_metadata("proposal_title", proposal_title_str)
 | 
			
		||||
        .with_metadata("start_date", start_date.to_rfc3339())
 | 
			
		||||
        .with_metadata("end_date", end_date.to_rfc3339())
 | 
			
		||||
        .with_tag("voting")
 | 
			
		||||
        .with_tag("period_start")
 | 
			
		||||
        .with_severity(ActivitySeverity::High)
 | 
			
		||||
        .with_occurred_at(start_date)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Create an activity for voting period end
 | 
			
		||||
    pub fn voting_ended(
 | 
			
		||||
        proposal_id: u32,
 | 
			
		||||
        proposal_title: impl ToString,
 | 
			
		||||
        total_votes: usize,
 | 
			
		||||
        total_shares: i64,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        let proposal_title_str = proposal_title.to_string();
 | 
			
		||||
 | 
			
		||||
        Self::new(
 | 
			
		||||
            None,
 | 
			
		||||
            ActivityType::VotingEnded,
 | 
			
		||||
            format!("Voting closed for '{}'", proposal_title_str),
 | 
			
		||||
            format!(
 | 
			
		||||
                "Community voting has ended for proposal '{}'. Final results: {} votes cast representing {} total voting shares",
 | 
			
		||||
                proposal_title_str,
 | 
			
		||||
                total_votes,
 | 
			
		||||
                total_shares
 | 
			
		||||
            ),
 | 
			
		||||
            None::<String>,
 | 
			
		||||
            Some("System"),
 | 
			
		||||
        )
 | 
			
		||||
        .with_target(proposal_id, "proposal")
 | 
			
		||||
        .with_metadata("proposal_title", proposal_title_str)
 | 
			
		||||
        .with_metadata("total_votes", total_votes.to_string())
 | 
			
		||||
        .with_metadata("total_shares", total_shares.to_string())
 | 
			
		||||
        .with_tag("voting")
 | 
			
		||||
        .with_tag("period_end")
 | 
			
		||||
        .with_severity(ActivitySeverity::High)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Create an activity for vote option addition
 | 
			
		||||
    pub fn vote_option_added(
 | 
			
		||||
        proposal_id: u32,
 | 
			
		||||
        proposal_title: impl ToString,
 | 
			
		||||
        option_id: u8,
 | 
			
		||||
        option_text: impl ToString,
 | 
			
		||||
        actor_id: Option<impl ToString>,
 | 
			
		||||
        actor_name: Option<impl ToString>,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        let proposal_title_str = proposal_title.to_string();
 | 
			
		||||
        let option_text_str = option_text.to_string();
 | 
			
		||||
        let actor_name_str = actor_name
 | 
			
		||||
            .map(|n| n.to_string())
 | 
			
		||||
            .unwrap_or_else(|| "System".to_string());
 | 
			
		||||
 | 
			
		||||
        Self::new(
 | 
			
		||||
            None,
 | 
			
		||||
            ActivityType::VoteOptionAdded,
 | 
			
		||||
            format!("{} added a voting option", actor_name_str),
 | 
			
		||||
            format!(
 | 
			
		||||
                "{} added the voting option '{}' to proposal '{}'",
 | 
			
		||||
                actor_name_str, option_text_str, proposal_title_str
 | 
			
		||||
            ),
 | 
			
		||||
            actor_id,
 | 
			
		||||
            Some(actor_name_str),
 | 
			
		||||
        )
 | 
			
		||||
        .with_target(proposal_id, "proposal")
 | 
			
		||||
        .with_metadata("proposal_title", proposal_title_str)
 | 
			
		||||
        .with_metadata("option_id", option_id.to_string())
 | 
			
		||||
        .with_metadata("option_text", option_text_str)
 | 
			
		||||
        .with_tag("vote_option")
 | 
			
		||||
        .with_tag("addition")
 | 
			
		||||
        .with_severity(ActivitySeverity::Normal)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Create an activity for proposal deletion
 | 
			
		||||
    pub fn proposal_deleted(
 | 
			
		||||
        proposal_id: u32,
 | 
			
		||||
        proposal_title: impl ToString,
 | 
			
		||||
        actor_id: impl ToString,
 | 
			
		||||
        actor_name: impl ToString,
 | 
			
		||||
        reason: Option<impl ToString>,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        let proposal_title_str = proposal_title.to_string();
 | 
			
		||||
        let actor_name_str = actor_name.to_string();
 | 
			
		||||
 | 
			
		||||
        let description = if let Some(reason) = reason {
 | 
			
		||||
            format!(
 | 
			
		||||
                "{} deleted proposal '{}'. Reason: {}",
 | 
			
		||||
                actor_name_str,
 | 
			
		||||
                proposal_title_str,
 | 
			
		||||
                reason.to_string()
 | 
			
		||||
            )
 | 
			
		||||
        } else {
 | 
			
		||||
            format!(
 | 
			
		||||
                "{} deleted proposal '{}'",
 | 
			
		||||
                actor_name_str, proposal_title_str
 | 
			
		||||
            )
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        Self::new(
 | 
			
		||||
            None,
 | 
			
		||||
            ActivityType::ProposalDeleted,
 | 
			
		||||
            format!("{} deleted a proposal", actor_name_str),
 | 
			
		||||
            description,
 | 
			
		||||
            Some(actor_id),
 | 
			
		||||
            Some(actor_name_str),
 | 
			
		||||
        )
 | 
			
		||||
        .with_target(proposal_id, "proposal")
 | 
			
		||||
        .with_metadata("proposal_title", proposal_title_str)
 | 
			
		||||
        .with_tag("proposal")
 | 
			
		||||
        .with_tag("deletion")
 | 
			
		||||
        .with_severity(ActivitySeverity::Critical)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// heromodels/src/models/governance/mod.rs
 | 
			
		||||
// This module will contain the Proposal model and related types.
 | 
			
		||||
pub mod activity;
 | 
			
		||||
pub mod proposal;
 | 
			
		||||
 | 
			
		||||
pub use self::proposal::{
 | 
			
		||||
    Activity, ActivityType, Ballot, Proposal, ProposalStatus, VoteEventStatus, VoteOption,
 | 
			
		||||
};
 | 
			
		||||
pub use self::activity::{ActivityStatus, ActivityType, GovernanceActivity};
 | 
			
		||||
pub use self::proposal::{Ballot, Proposal, ProposalStatus, VoteEventStatus, VoteOption};
 | 
			
		||||
 
 | 
			
		||||
@@ -31,3 +31,10 @@ pub use flow::register_flow_rhai_module;
 | 
			
		||||
pub use legal::register_legal_rhai_module;
 | 
			
		||||
#[cfg(feature = "rhai")]
 | 
			
		||||
pub use projects::register_projects_rhai_module;
 | 
			
		||||
pub use calendar::{AttendanceStatus, Attendee, Calendar, Event};
 | 
			
		||||
pub use finance::marketplace::{Bid, BidStatus, Listing, ListingStatus, ListingType};
 | 
			
		||||
pub use finance::{Account, Asset, AssetType};
 | 
			
		||||
pub use governance::{
 | 
			
		||||
    ActivityStatus, ActivityType, Ballot, GovernanceActivity, Proposal, ProposalStatus,
 | 
			
		||||
    VoteEventStatus, VoteOption,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user