//! Tip, project member, and revenue split models. use chrono::{DateTime, Utc}; use serde::Serialize; use sqlx::FromRow; use super::super::id_types::{ ProjectId, ProjectMemberId, RevenueSplitId, TipId, TransactionId, UserId, }; use super::super::validated_types::{Cents, StripeAccountId}; /// A one-time tip from a fan to a creator. #[derive(Debug, Clone, FromRow, Serialize)] pub struct DbTip { pub id: TipId, pub tipper_id: UserId, pub recipient_id: UserId, pub project_id: Option, pub amount_cents: Cents, pub message: Option, pub status: super::super::TransactionStatus, pub stripe_payment_intent_id: Option, pub stripe_checkout_session_id: Option, pub stripe_transfer_group: Option, pub created_at: DateTime, pub completed_at: Option>, /// The recipient's settlement currency at the time of the tip. Stored rather /// than re-read, so an old tip stays readable after the creator's settlement /// currency changes. pub currency: crate::currency::SettlementCurrency, } /// A member of a multi-author project with a revenue split. #[derive(Debug, Clone, FromRow, Serialize)] pub struct DbProjectMember { pub id: ProjectMemberId, pub project_id: ProjectId, pub user_id: UserId, pub role: super::super::ProjectRole, pub split_percent: i16, pub added_at: DateTime, pub added_by: UserId, } /// A revenue split record for a completed payment. #[derive(Debug, Clone, FromRow, Serialize)] pub struct DbRevenueSplit { pub id: RevenueSplitId, pub tip_id: Option, pub transaction_id: Option, pub recipient_id: UserId, pub amount_cents: Cents, pub split_percent: i16, pub stripe_transfer_id: Option, pub status: super::super::TransactionStatus, pub created_at: DateTime, pub completed_at: Option>, } /// Tip with tipper username for display in dashboard/history. #[derive(Debug, Clone, FromRow)] pub struct DbTipWithUser { pub id: TipId, pub tipper_id: UserId, pub recipient_id: UserId, pub project_id: Option, pub amount_cents: Cents, pub message: Option, pub status: super::super::TransactionStatus, pub created_at: DateTime, pub completed_at: Option>, pub tipper_username: String, pub tipper_display_name: Option, } /// Project member with user info for display. #[derive(Debug, Clone, FromRow)] pub struct DbProjectMemberWithUser { pub id: ProjectMemberId, pub project_id: ProjectId, pub user_id: UserId, pub role: super::super::ProjectRole, pub split_percent: i16, pub added_at: DateTime, /// When the collaborator agreed. `None` = invited, not yet accepted: the /// percentage is reserved but earns nothing until they say yes. pub accepted_at: Option>, pub username: String, pub display_name: Option, pub stripe_account_id: Option, pub stripe_charges_enabled: bool, /// The collaborator's own settlement currency, for the disclosure: if it /// differs from the project's, their share converts at their payout. pub settlement_currency: crate::currency::SettlementCurrency, } impl DbProjectMemberWithUser { /// Whether this member's split is live. pub fn is_accepted(&self) -> bool { self.accepted_at.is_some() } }