Skip to main content

max / makenotwork

3.4 KB · 103 lines History Blame Raw
1 //! Tip, project member, and revenue split models.
2
3 use chrono::{DateTime, Utc};
4 use serde::Serialize;
5 use sqlx::FromRow;
6
7 use super::super::id_types::{
8 ProjectId, ProjectMemberId, RevenueSplitId, TipId, TransactionId, UserId,
9 };
10 use super::super::validated_types::{Cents, StripeAccountId};
11
12 /// A one-time tip from a fan to a creator.
13 #[derive(Debug, Clone, FromRow, Serialize)]
14 pub struct DbTip {
15 pub id: TipId,
16 pub tipper_id: UserId,
17 pub recipient_id: UserId,
18 pub project_id: Option<ProjectId>,
19 pub amount_cents: Cents,
20 pub message: Option<String>,
21 pub status: super::super::TransactionStatus,
22 pub stripe_payment_intent_id: Option<String>,
23 pub stripe_checkout_session_id: Option<String>,
24 pub stripe_transfer_group: Option<String>,
25 pub created_at: DateTime<Utc>,
26 pub completed_at: Option<DateTime<Utc>>,
27 /// The recipient's settlement currency at the time of the tip. Stored rather
28 /// than re-read, so an old tip stays readable after the creator's settlement
29 /// currency changes.
30 pub currency: crate::currency::SettlementCurrency,
31 }
32
33 /// A member of a multi-author project with a revenue split.
34 #[derive(Debug, Clone, FromRow, Serialize)]
35 pub struct DbProjectMember {
36 pub id: ProjectMemberId,
37 pub project_id: ProjectId,
38 pub user_id: UserId,
39 pub role: super::super::ProjectRole,
40 pub split_percent: i16,
41 pub added_at: DateTime<Utc>,
42 pub added_by: UserId,
43 }
44
45 /// A revenue split record for a completed payment.
46 #[derive(Debug, Clone, FromRow, Serialize)]
47 pub struct DbRevenueSplit {
48 pub id: RevenueSplitId,
49 pub tip_id: Option<TipId>,
50 pub transaction_id: Option<TransactionId>,
51 pub recipient_id: UserId,
52 pub amount_cents: Cents,
53 pub split_percent: i16,
54 pub stripe_transfer_id: Option<String>,
55 pub status: super::super::TransactionStatus,
56 pub created_at: DateTime<Utc>,
57 pub completed_at: Option<DateTime<Utc>>,
58 }
59
60 /// Tip with tipper username for display in dashboard/history.
61 #[derive(Debug, Clone, FromRow)]
62 pub struct DbTipWithUser {
63 pub id: TipId,
64 pub tipper_id: UserId,
65 pub recipient_id: UserId,
66 pub project_id: Option<ProjectId>,
67 pub amount_cents: Cents,
68 pub message: Option<String>,
69 pub status: super::super::TransactionStatus,
70 pub created_at: DateTime<Utc>,
71 pub completed_at: Option<DateTime<Utc>>,
72 pub tipper_username: String,
73 pub tipper_display_name: Option<String>,
74 }
75
76 /// Project member with user info for display.
77 #[derive(Debug, Clone, FromRow)]
78 pub struct DbProjectMemberWithUser {
79 pub id: ProjectMemberId,
80 pub project_id: ProjectId,
81 pub user_id: UserId,
82 pub role: super::super::ProjectRole,
83 pub split_percent: i16,
84 pub added_at: DateTime<Utc>,
85 /// When the collaborator agreed. `None` = invited, not yet accepted: the
86 /// percentage is reserved but earns nothing until they say yes.
87 pub accepted_at: Option<DateTime<Utc>>,
88 pub username: String,
89 pub display_name: Option<String>,
90 pub stripe_account_id: Option<StripeAccountId>,
91 pub stripe_charges_enabled: bool,
92 /// The collaborator's own settlement currency, for the disclosure: if it
93 /// differs from the project's, their share converts at their payout.
94 pub settlement_currency: crate::currency::SettlementCurrency,
95 }
96
97 impl DbProjectMemberWithUser {
98 /// Whether this member's split is live.
99 pub fn is_accepted(&self) -> bool {
100 self.accepted_at.is_some()
101 }
102 }
103