Skip to content

Commit 157c805

Browse files
committed
feat: implement group rating system with aggregation and GroupRated event
1 parent cae0977 commit 157c805

4 files changed

Lines changed: 543 additions & 0 deletions

File tree

contracts/stellar-save/src/events.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,17 @@ pub struct AutoContributionFailed {
253253
pub failed_at: u64,
254254
}
255255

256+
/// Event emitted when a member rates a group after completion.
257+
#[contracttype]
258+
#[derive(Clone, Debug, Eq, PartialEq)]
259+
pub struct GroupRated {
260+
pub group_id: u64,
261+
pub member: Address,
262+
pub stars: u32,
263+
pub comment: String,
264+
pub rated_at: u64,
265+
}
266+
256267
/// Event emitted when a penalty is applied to a member for a missed contribution.
257268
#[contracttype]
258269
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -681,6 +692,25 @@ impl EventEmitter {
681692
};
682693
env.events().publish(("auto_contribution_failed",), event);
683694
}
695+
696+
/// Emits an event when a member rates a group.
697+
pub fn emit_group_rated(
698+
env: &Env,
699+
group_id: u64,
700+
member: Address,
701+
stars: u32,
702+
comment: String,
703+
rated_at: u64,
704+
) {
705+
let event = GroupRated {
706+
group_id,
707+
member,
708+
stars,
709+
comment,
710+
rated_at,
711+
};
712+
env.events().publish(("group_rated",), event);
713+
}
684714
}
685715

686716
#[cfg(test)]

contracts/stellar-save/src/lib.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub mod payout;
2828
pub mod payout_executor;
2929
pub mod penalty;
3030
pub mod pool;
31+
pub mod rating;
3132
pub mod status;
3233
pub mod storage;
3334
pub mod token;
@@ -51,6 +52,7 @@ pub use events::*;
5152
pub use group::{Group, GroupStatus};
5253
pub use payout::PayoutRecord;
5354
pub use pool::{PoolCalculator, PoolInfo};
55+
pub use rating::{GroupRating, RatingAggregate, RatingEntry};
5456
#[cfg(test)]
5557
use soroban_sdk::testutils::{Events, Ledger};
5658
use soroban_sdk::{contract, contractimpl, contracttype, Address, Env, String, Symbol, Vec};
@@ -2659,6 +2661,51 @@ impl StellarSaveContract {
26592661
env.storage().persistent().get(&key).unwrap_or(0)
26602662
}
26612663

2664+
/// Submits a 1–5 star rating (with optional comment) for a completed or cancelled group.
2665+
///
2666+
/// # Rules
2667+
/// - Group must be in a terminal state (Completed or Cancelled).
2668+
/// - Caller must be a member of the group.
2669+
/// - Each member may only rate once per group.
2670+
/// - `stars` must be 1–5.
2671+
/// - `comment` must be ≤ 280 characters (pass an empty string for no comment).
2672+
///
2673+
/// # Errors
2674+
/// - `GroupNotFound` – group does not exist
2675+
/// - `InvalidState` – group is not yet in a terminal state
2676+
/// - `NotMember` – caller is not a member of the group
2677+
/// - `InvalidAmount` – stars is 0 or > 5
2678+
/// - `InvalidMetadata` – comment exceeds 280 characters
2679+
/// - `AlreadyContributed` – member has already rated this group
2680+
pub fn rate_group(
2681+
env: Env,
2682+
caller: Address,
2683+
group_id: u64,
2684+
stars: u32,
2685+
comment: String,
2686+
) -> Result<(), StellarSaveError> {
2687+
rating::rate_group(&env, caller, group_id, stars, comment)
2688+
}
2689+
2690+
/// Returns the aggregated rating summary for a group.
2691+
///
2692+
/// Returns a [`GroupRating`] with `rating_count`, `total_stars`, and
2693+
/// `average_scaled` (average × 100, e.g. 450 = 4.50 stars).
2694+
/// Returns zeroed counts if no ratings have been submitted yet.
2695+
pub fn get_group_rating(env: Env, group_id: u64) -> Result<GroupRating, StellarSaveError> {
2696+
rating::get_group_rating(&env, group_id)
2697+
}
2698+
2699+
/// Returns the individual rating submitted by a specific member for a group.
2700+
/// Returns `None` if the member has not yet rated the group.
2701+
pub fn get_member_rating(
2702+
env: Env,
2703+
group_id: u64,
2704+
member: Address,
2705+
) -> Result<Option<RatingEntry>, StellarSaveError> {
2706+
rating::get_member_rating(&env, group_id, member)
2707+
}
2708+
26622709
/// Gets the total XLM balance held by the contract.
26632710
///
26642711
/// # Arguments

0 commit comments

Comments
 (0)