Allow servers to be unprovisioned without issuing a refund (#3534)

* Allow servers to be unprovisioned without issuing a refund

for very specific weird circumstances where a server gets stuck/etc; useful for support

* still create a charge

* Fix compile
This commit is contained in:
Emma Alexia 2025-04-19 00:39:18 -04:00 committed by GitHub
parent d0aef27f7b
commit 84a28e045b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 48 additions and 40 deletions

View File

@ -277,7 +277,7 @@ const refunding = ref(false);
const refundModal = ref(); const refundModal = ref();
const selectedCharge = ref(null); const selectedCharge = ref(null);
const refundType = ref("full"); const refundType = ref("full");
const refundTypes = ref(["full", "partial"]); const refundTypes = ref(["full", "partial", "none"]);
const refundAmount = ref(0); const refundAmount = ref(0);
const unprovision = ref(false); const unprovision = ref(false);

View File

@ -135,6 +135,7 @@ pub async fn subscriptions(
pub enum ChargeRefundAmount { pub enum ChargeRefundAmount {
Full, Full,
Partial { amount: u64 }, Partial { amount: u64 },
None,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -189,6 +190,7 @@ pub async fn refund_charge(
let refund_amount = match body.0.amount { let refund_amount = match body.0.amount {
ChargeRefundAmount::Full => refundable, ChargeRefundAmount::Full => refundable,
ChargeRefundAmount::Partial { amount } => amount as i64, ChargeRefundAmount::Partial { amount } => amount as i64,
ChargeRefundAmount::None => 0,
}; };
if charge.status != ChargeStatus::Succeeded { if charge.status != ChargeStatus::Succeeded {
@ -197,55 +199,61 @@ pub async fn refund_charge(
)); ));
} }
if (refundable - refund_amount) < 0 || refund_amount == 0 { if (refundable - refund_amount) < 0 {
return Err(ApiError::InvalidInput( return Err(ApiError::InvalidInput(
"You cannot refund more than the amount of the charge!" "You cannot refund more than the amount of the charge!"
.to_string(), .to_string(),
)); ));
} }
let (id, net) = match charge.payment_platform { let (id, net) = if refund_amount != 0 {
PaymentPlatform::Stripe => { (None, None)
if let Some(payment_platform_id) = charge } else {
.payment_platform_id match charge.payment_platform {
.and_then(|x| stripe::PaymentIntentId::from_str(&x).ok()) PaymentPlatform::Stripe => {
{ if let Some(payment_platform_id) =
let mut metadata = HashMap::new(); charge.payment_platform_id.and_then(|x| {
stripe::PaymentIntentId::from_str(&x).ok()
})
{
let mut metadata = HashMap::new();
metadata.insert( metadata.insert(
"modrinth_user_id".to_string(), "modrinth_user_id".to_string(),
to_base62(user.id.0), to_base62(user.id.0),
); );
metadata.insert( metadata.insert(
"modrinth_charge_id".to_string(), "modrinth_charge_id".to_string(),
to_base62(charge.id.0 as u64), to_base62(charge.id.0 as u64),
); );
let refund = stripe::Refund::create( let refund = stripe::Refund::create(
&stripe_client, &stripe_client,
CreateRefund { CreateRefund {
amount: Some(refund_amount), amount: Some(refund_amount),
metadata: Some(metadata), metadata: Some(metadata),
payment_intent: Some(payment_platform_id), payment_intent: Some(payment_platform_id),
expand: &["balance_transaction"], expand: &["balance_transaction"],
..Default::default() ..Default::default()
}, },
) )
.await?; .await?;
( (
refund.id.to_string(), Some(refund.id.to_string()),
refund refund
.balance_transaction .balance_transaction
.and_then(|x| x.into_object()) .and_then(|x| x.into_object())
.map(|x| x.net), .map(|x| x.net),
) )
} else { } else {
return Err(ApiError::InvalidInput( return Err(ApiError::InvalidInput(
"Charge does not have attached payment id!".to_string(), "Charge does not have attached payment id!"
)); .to_string(),
));
}
} }
} }
}; };
@ -266,7 +274,7 @@ pub async fn refund_charge(
subscription_id: charge.subscription_id, subscription_id: charge.subscription_id,
subscription_interval: charge.subscription_interval, subscription_interval: charge.subscription_interval,
payment_platform: charge.payment_platform, payment_platform: charge.payment_platform,
payment_platform_id: Some(id), payment_platform_id: id,
parent_charge_id: Some(charge.id), parent_charge_id: Some(charge.id),
net, net,
} }