| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
pub fn stripe_timestamp(ts: i64) -> chrono::DateTime<chrono::Utc> { |
| 5 |
chrono::DateTime::from_timestamp(ts, 0).unwrap_or_else(chrono::Utc::now) |
| 6 |
} |
| 7 |
|
| 8 |
|
| 9 |
|
| 10 |
|
| 11 |
|
| 12 |
pub fn estimate_stripe_fee(price_cents: i32) -> (i32, i32) { |
| 13 |
if price_cents <= 0 { |
| 14 |
return (0, 0); |
| 15 |
} |
| 16 |
let fee = (price_cents as f64 * crate::constants::STRIPE_FEE_PERCENTAGE |
| 17 |
+ crate::constants::STRIPE_FEE_FIXED_CENTS) as i32; |
| 18 |
let creator_receives = (price_cents - fee).max(0); |
| 19 |
(fee.min(price_cents), creator_receives) |
| 20 |
} |
| 21 |
|
| 22 |
#[cfg(test)] |
| 23 |
mod tests { |
| 24 |
use super::*; |
| 25 |
|
| 26 |
|
| 27 |
|
| 28 |
#[test] |
| 29 |
fn stripe_fee_standard_price() { |
| 30 |
let (fee, receives) = estimate_stripe_fee(1000); |
| 31 |
assert_eq!(fee, 59); |
| 32 |
assert_eq!(receives, 941); |
| 33 |
} |
| 34 |
|
| 35 |
#[test] |
| 36 |
fn stripe_fee_small_price() { |
| 37 |
let (fee, receives) = estimate_stripe_fee(100); |
| 38 |
assert_eq!(fee, 32); |
| 39 |
assert_eq!(receives, 68); |
| 40 |
} |
| 41 |
|
| 42 |
#[test] |
| 43 |
fn stripe_fee_zero_is_free() { |
| 44 |
let (fee, receives) = estimate_stripe_fee(0); |
| 45 |
assert_eq!(fee, 0); |
| 46 |
assert_eq!(receives, 0); |
| 47 |
} |
| 48 |
|
| 49 |
#[test] |
| 50 |
fn stripe_fee_negative_price() { |
| 51 |
let (fee, receives) = estimate_stripe_fee(-100); |
| 52 |
assert_eq!(fee, 0); |
| 53 |
assert_eq!(receives, 0); |
| 54 |
} |
| 55 |
|
| 56 |
#[test] |
| 57 |
fn stripe_fee_plus_receives_equals_price() { |
| 58 |
for price in [50, 100, 250, 500, 999, 1000, 2500, 5000, 10000, 50000] { |
| 59 |
let (fee, receives) = estimate_stripe_fee(price); |
| 60 |
assert_eq!( |
| 61 |
fee + receives, |
| 62 |
price, |
| 63 |
"fee + receives should equal price for {price} cents" |
| 64 |
); |
| 65 |
} |
| 66 |
} |
| 67 |
|
| 68 |
|
| 69 |
|
| 70 |
#[test] |
| 71 |
fn stripe_timestamp_zero() { |
| 72 |
assert_eq!(stripe_timestamp(0).timestamp(), 0); |
| 73 |
} |
| 74 |
|
| 75 |
#[test] |
| 76 |
fn stripe_timestamp_valid() { |
| 77 |
assert_eq!(stripe_timestamp(1_714_400_000).timestamp(), 1_714_400_000); |
| 78 |
} |
| 79 |
|
| 80 |
|
| 81 |
|
| 82 |
proptest::proptest! { |
| 83 |
#[test] |
| 84 |
fn prop_stripe_fee_invariant(price in 1..=1_000_000i32) { |
| 85 |
let (fee, receives) = estimate_stripe_fee(price); |
| 86 |
proptest::prop_assert_eq!(fee + receives, price, |
| 87 |
"fee ({}) + receives ({}) must equal price ({})", fee, receives, price); |
| 88 |
proptest::prop_assert!(fee > 0, "Fee should be positive for price {}", price); |
| 89 |
proptest::prop_assert!(receives >= 0, "Receives should be non-negative"); |
| 90 |
} |
| 91 |
} |
| 92 |
} |
| 93 |
|