//! Self-service refund endpoint for creators. use axum::Json; use axum::extract::{Path, State}; use axum::response::IntoResponse; use serde::Deserialize; use sqlx::PgPool; use crate::{ Billing, auth::AuthUser, db::{ItemId, TransactionId}, error::Result, }; #[derive(Debug, Deserialize)] pub(crate) struct RefundRequest { pub transaction_id: TransactionId, } /// Issue a line-scoped refund for one transaction on this item. /// /// A thin wrapper over [`crate::payments::refund::refund`], which holds every /// check and the atomic claim. The described Sales panel /// (`crate::quasi::item_sales`) calls the same core from its writes-only nest, /// so the money path exists once (`b25dd957`). This route stays for API /// consumers. #[tracing::instrument(skip_all, name = "items::refund_transaction")] pub(in crate::routes::api) async fn refund_transaction( State(db): State, State(payments): State, AuthUser(user): AuthUser, Path(id): Path, Json(req): Json, ) -> Result { crate::payments::refund::refund( &db, payments.payment_caps.refundable.as_ref(), &user, id, req.transaction_id, ) .await?; Ok(Json(serde_json::json!({ "ok": true }))) }