fix: Add creator_name field to the proposal model

This commit is contained in:
Mahmoud-Emad 2025-05-21 09:37:45 +03:00
parent 4c0c7be574
commit 5327d1f00c
3 changed files with 152 additions and 68 deletions

View File

@ -13,12 +13,13 @@ fn main() {
// Create a new proposal with auto-generated ID // Create a new proposal with auto-generated ID
let mut proposal = Proposal::new( let mut proposal = Proposal::new(
None, // id (auto-generated) None, // id (auto-generated)
"user_creator_123", // creator_id "user_creator_123",
"Community Fund Allocation for Q3", // title "Ahmed fared", // creator_id
"Community Fund Allocation for Q3", // title
"Proposal to allocate funds for community projects in the third quarter.", // description "Proposal to allocate funds for community projects in the third quarter.", // description
Utc::now(), // vote_start_date Utc::now(), // vote_start_date
Utc::now() + Duration::days(14), // vote_end_date (14 days from now) Utc::now() + Duration::days(14), // vote_end_date (14 days from now)
); );
println!( println!(
@ -125,6 +126,7 @@ fn main() {
let mut private_proposal = Proposal::new( let mut private_proposal = Proposal::new(
None, // auto-generated ID None, // auto-generated ID
"user_admin_001", "user_admin_001",
"Wael Ghonem",
"Internal Team Restructure Vote", "Internal Team Restructure Vote",
"Vote on proposed internal team changes.", "Vote on proposed internal team changes.",
Utc::now(), Utc::now(),

View File

@ -1,10 +1,12 @@
use chrono::{Duration, Utc};
use heromodels::db::hero::OurDB; use heromodels::db::hero::OurDB;
use heromodels::models::governance::{Proposal, ProposalStatus, VoteEventStatus, VoteOption, Ballot}; use heromodels::models::governance::{
Ballot, Proposal, ProposalStatus, VoteEventStatus, VoteOption,
};
use rhai::Engine; use rhai::Engine;
use rhai_wrapper::wrap_vec_return; use rhai_wrapper::wrap_vec_return;
use std::sync::Arc; use std::sync::Arc;
use std::{fs, path::Path}; use std::{fs, path::Path};
use chrono::{Utc, Duration};
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize Rhai engine // Initialize Rhai engine
@ -24,21 +26,40 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
engine.register_fn("get_db", move || db.clone()); engine.register_fn("get_db", move || db.clone());
// Register builder functions for Proposal and related types // Register builder functions for Proposal and related types
engine.register_fn("create_proposal", |id: i64, creator_id: String, title: String, description: String| { engine.register_fn(
let start_date = Utc::now(); "create_proposal",
let end_date = start_date + Duration::days(14); |id: i64, creator_id: String, creator_name: String, title: String, description: String| {
let id_option = if id <= 0 { None } else { Some(id as u32) }; let start_date = Utc::now();
Proposal::new(id_option, creator_id, title, description, start_date, end_date) let end_date = start_date + Duration::days(14);
}); let id_option = if id <= 0 { None } else { Some(id as u32) };
Proposal::new(
id_option,
creator_id,
creator_name,
title,
description,
start_date,
end_date,
)
},
);
engine.register_fn("create_vote_option", |id: i64, text: String| { engine.register_fn("create_vote_option", |id: i64, text: String| {
VoteOption::new(id as u8, text) VoteOption::new(id as u8, text)
}); });
engine.register_fn("create_ballot", |id: i64, user_id: i64, vote_option_id: i64, shares_count: i64| { engine.register_fn(
let id_option = if id <= 0 { None } else { Some(id as u32) }; "create_ballot",
Ballot::new(id_option, user_id as u32, vote_option_id as u8, shares_count) |id: i64, user_id: i64, vote_option_id: i64, shares_count: i64| {
}); let id_option = if id <= 0 { None } else { Some(id as u32) };
Ballot::new(
id_option,
user_id as u32,
vote_option_id as u8,
shares_count,
)
},
);
// Register getter and setter methods for Proposal properties // Register getter and setter methods for Proposal properties
engine.register_fn("get_title", |proposal: Proposal| -> String { engine.register_fn("get_title", |proposal: Proposal| -> String {
@ -66,48 +87,80 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}); });
// Register methods for proposal operations // Register methods for proposal operations
engine.register_fn("add_option_to_proposal", |mut proposal: Proposal, option_id: i64, option_text: String| -> Proposal { engine.register_fn(
proposal.add_option(option_id as u8, option_text) "add_option_to_proposal",
}); |mut proposal: Proposal, option_id: i64, option_text: String| -> Proposal {
proposal.add_option(option_id as u8, option_text)
},
);
engine.register_fn("cast_vote_on_proposal", |mut proposal: Proposal, ballot_id: i64, user_id: i64, option_id: i64, shares: i64| -> Proposal { engine.register_fn(
let ballot_id_option = if ballot_id <= 0 { None } else { Some(ballot_id as u32) }; "cast_vote_on_proposal",
proposal.cast_vote(ballot_id_option, user_id as u32, option_id as u8, shares) |mut proposal: Proposal,
}); ballot_id: i64,
user_id: i64,
option_id: i64,
shares: i64|
-> Proposal {
let ballot_id_option = if ballot_id <= 0 {
None
} else {
Some(ballot_id as u32)
};
proposal.cast_vote(ballot_id_option, user_id as u32, option_id as u8, shares)
},
);
engine.register_fn("change_proposal_status", |mut proposal: Proposal, status_str: String| -> Proposal { engine.register_fn(
let new_status = match status_str.as_str() { "change_proposal_status",
"Draft" => ProposalStatus::Draft, |mut proposal: Proposal, status_str: String| -> Proposal {
"Active" => ProposalStatus::Active, let new_status = match status_str.as_str() {
"Approved" => ProposalStatus::Approved, "Draft" => ProposalStatus::Draft,
"Rejected" => ProposalStatus::Rejected, "Active" => ProposalStatus::Active,
"Cancelled" => ProposalStatus::Cancelled, "Approved" => ProposalStatus::Approved,
_ => ProposalStatus::Draft, "Rejected" => ProposalStatus::Rejected,
}; "Cancelled" => ProposalStatus::Cancelled,
proposal.change_proposal_status(new_status) _ => ProposalStatus::Draft,
}); };
proposal.change_proposal_status(new_status)
},
);
engine.register_fn("change_vote_event_status", |mut proposal: Proposal, status_str: String| -> Proposal { engine.register_fn(
let new_status = match status_str.as_str() { "change_vote_event_status",
"Open" => VoteEventStatus::Open, |mut proposal: Proposal, status_str: String| -> Proposal {
"Closed" => VoteEventStatus::Closed, let new_status = match status_str.as_str() {
"Cancelled" => VoteEventStatus::Cancelled, "Open" => VoteEventStatus::Open,
_ => VoteEventStatus::Open, "Closed" => VoteEventStatus::Closed,
}; "Cancelled" => VoteEventStatus::Cancelled,
proposal.change_vote_event_status(new_status) _ => VoteEventStatus::Open,
}); };
proposal.change_vote_event_status(new_status)
},
);
// Register functions for database operations // Register functions for database operations
engine.register_fn("save_proposal", |_db: Arc<OurDB>, proposal: Proposal| { engine.register_fn("save_proposal", |_db: Arc<OurDB>, proposal: Proposal| {
println!("Proposal saved: {}", proposal.title); println!("Proposal saved: {}", proposal.title);
}); });
engine.register_fn("get_proposal_by_id", |_db: Arc<OurDB>, id: i64| -> Proposal { engine.register_fn(
// In a real implementation, this would retrieve the proposal from the database "get_proposal_by_id",
let start_date = Utc::now(); |_db: Arc<OurDB>, id: i64| -> Proposal {
let end_date = start_date + Duration::days(14); // In a real implementation, this would retrieve the proposal from the database
Proposal::new(Some(id as u32), "Retrieved Creator", "Retrieved Proposal", "Retrieved Description", start_date, end_date) let start_date = Utc::now();
}); let end_date = start_date + Duration::days(14);
Proposal::new(
Some(id as u32),
"Retrieved Creator",
"Retrieved Creator Name",
"Retrieved Proposal",
"Retrieved Description",
start_date,
end_date,
)
},
);
// Register a function to check if a proposal exists // Register a function to check if a proposal exists
engine.register_fn("proposal_exists", |_db: Arc<OurDB>, id: i64| -> bool { engine.register_fn("proposal_exists", |_db: Arc<OurDB>, id: i64| -> bool {
@ -121,13 +174,32 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let start_date = Utc::now(); let start_date = Utc::now();
let end_date = start_date + Duration::days(14); let end_date = start_date + Duration::days(14);
vec![ vec![
Proposal::new(Some(1), "Creator 1", "Proposal 1", "Description 1", start_date, end_date), Proposal::new(
Proposal::new(Some(2), "Creator 2", "Proposal 2", "Description 2", start_date, end_date) Some(1),
"Creator 1",
"Creator Name 1",
"Proposal 1",
"Description 1",
start_date,
end_date,
),
Proposal::new(
Some(2),
"Creator 2",
"Creator Name 2",
"Proposal 2",
"Description 2",
start_date,
end_date,
),
] ]
} }
// Register the function with the wrap_vec_return macro // Register the function with the wrap_vec_return macro
engine.register_fn("get_all_proposals", wrap_vec_return!(get_all_proposals, Arc<OurDB> => Proposal)); engine.register_fn(
"get_all_proposals",
wrap_vec_return!(get_all_proposals, Arc<OurDB> => Proposal),
);
engine.register_fn("delete_proposal_by_id", |_db: Arc<OurDB>, _id: i64| { engine.register_fn("delete_proposal_by_id", |_db: Arc<OurDB>, _id: i64| {
// In a real implementation, this would delete the proposal from the database // In a real implementation, this would delete the proposal from the database
@ -139,13 +211,16 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
proposal.options.len() as i64 proposal.options.len() as i64
}); });
engine.register_fn("get_option_at", |proposal: Proposal, index: i64| -> VoteOption { engine.register_fn(
if index >= 0 && index < proposal.options.len() as i64 { "get_option_at",
proposal.options[index as usize].clone() |proposal: Proposal, index: i64| -> VoteOption {
} else { if index >= 0 && index < proposal.options.len() as i64 {
VoteOption::new(0, "Invalid Option") proposal.options[index as usize].clone()
} } else {
}); VoteOption::new(0, "Invalid Option")
}
},
);
engine.register_fn("get_option_text", |option: VoteOption| -> String { engine.register_fn("get_option_text", |option: VoteOption| -> String {
option.text.clone() option.text.clone()
@ -159,13 +234,16 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
proposal.ballots.len() as i64 proposal.ballots.len() as i64
}); });
engine.register_fn("get_ballot_at", |proposal: Proposal, index: i64| -> Ballot { engine.register_fn(
if index >= 0 && index < proposal.ballots.len() as i64 { "get_ballot_at",
proposal.ballots[index as usize].clone() |proposal: Proposal, index: i64| -> Ballot {
} else { if index >= 0 && index < proposal.ballots.len() as i64 {
Ballot::new(None, 0, 0, 0) proposal.ballots[index as usize].clone()
} } else {
}); Ballot::new(None, 0, 0, 0)
}
},
);
engine.register_fn("get_ballot_user_id", |ballot: Ballot| -> i64 { engine.register_fn("get_ballot_user_id", |ballot: Ballot| -> i64 {
ballot.user_id as i64 ballot.user_id as i64

View File

@ -102,7 +102,9 @@ impl Ballot {
#[model] // Has base.Base in V spec #[model] // Has base.Base in V spec
pub struct Proposal { pub struct Proposal {
pub base_data: BaseModelData, pub base_data: BaseModelData,
pub creator_id: String, // User ID of the proposal creator pub creator_id: String, // User ID of the proposal creator
pub creator_name: String, // User name of the proposal creator
pub title: String, pub title: String,
pub description: String, pub description: String,
pub status: ProposalStatus, pub status: ProposalStatus,
@ -129,6 +131,7 @@ impl Proposal {
pub fn new( pub fn new(
id: Option<u32>, id: Option<u32>,
creator_id: impl ToString, creator_id: impl ToString,
creator_name: impl ToString,
title: impl ToString, title: impl ToString,
description: impl ToString, description: impl ToString,
vote_start_date: DateTime<Utc>, vote_start_date: DateTime<Utc>,
@ -142,6 +145,7 @@ impl Proposal {
Self { Self {
base_data, base_data,
creator_id: creator_id.to_string(), creator_id: creator_id.to_string(),
creator_name: creator_name.to_string(),
title: title.to_string(), title: title.to_string(),
description: description.to_string(), description: description.to_string(),
status: ProposalStatus::Draft, status: ProposalStatus::Draft,