Skip to main content

stripe_shared/
customer_balance_transaction.rs

1/// Each customer has a [Balance](https://docs.stripe.com/api/customers/object#customer_object-balance) value,.
2/// which denotes a debit or credit that's automatically applied to their next invoice upon finalization.
3/// You may modify the value directly by using the [update customer API](https://docs.stripe.com/api/customers/update),.
4/// or by creating a Customer Balance Transaction, which increments or decrements the customer's `balance` by the specified `amount`.
5///
6/// Related guide: [Customer balance](https://docs.stripe.com/billing/customer/balance)
7///
8/// For more details see <<https://stripe.com/docs/api/customer_balance_transactions/object>>.
9#[derive(Clone)]
10#[cfg_attr(not(feature = "redact-generated-debug"), derive(Debug))]
11#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
12pub struct CustomerBalanceTransaction {
13    /// The amount of the transaction.
14    /// A negative value is a credit for the customer's balance, and a positive value is a debit to the customer's `balance`.
15    pub amount: i64,
16    /// The ID of the checkout session (if any) that created the transaction.
17    pub checkout_session: Option<stripe_types::Expandable<stripe_shared::CheckoutSession>>,
18    /// Time at which the object was created. Measured in seconds since the Unix epoch.
19    pub created: stripe_types::Timestamp,
20    /// The ID of the credit note (if any) related to the transaction.
21    pub credit_note: Option<stripe_types::Expandable<stripe_shared::CreditNote>>,
22    /// Three-letter [ISO currency code](https://www.iso.org/iso-4217-currency-codes.html), in lowercase.
23    /// Must be a [supported currency](https://stripe.com/docs/currencies).
24    pub currency: stripe_types::Currency,
25    /// The ID of the customer the transaction belongs to.
26    pub customer: stripe_types::Expandable<stripe_shared::Customer>,
27    /// The ID of an Account representing a customer that the transaction belongs to.
28    pub customer_account: Option<String>,
29    /// An arbitrary string attached to the object. Often useful for displaying to users.
30    pub description: Option<String>,
31    /// The customer's `balance` after the transaction was applied.
32    /// A negative value decreases the amount due on the customer's next invoice.
33    /// A positive value increases the amount due on the customer's next invoice.
34    pub ending_balance: i64,
35    /// Unique identifier for the object.
36    pub id: stripe_shared::CustomerBalanceTransactionId,
37    /// The ID of the invoice (if any) related to the transaction.
38    pub invoice: Option<stripe_types::Expandable<stripe_shared::Invoice>>,
39    /// If the object exists in live mode, the value is `true`.
40    /// If the object exists in test mode, the value is `false`.
41    pub livemode: bool,
42    /// Set of [key-value pairs](https://docs.stripe.com/api/metadata) that you can attach to an object.
43    /// This can be useful for storing additional information about the object in a structured format.
44    pub metadata: Option<std::collections::HashMap<String, String>>,
45    /// Transaction type: `adjustment`, `applied_to_invoice`, `credit_note`, `initial`, `invoice_overpaid`, `invoice_too_large`, `invoice_too_small`, `unspent_receiver_credit`, `unapplied_from_invoice`, `checkout_session_subscription_payment`, or `checkout_session_subscription_payment_canceled`.
46    /// See the [Customer Balance page](https://docs.stripe.com/billing/customer/balance#types) to learn more about transaction types.
47    #[cfg_attr(feature = "deserialize", serde(rename = "type"))]
48    pub type_: CustomerBalanceTransactionType,
49}
50#[cfg(feature = "redact-generated-debug")]
51impl std::fmt::Debug for CustomerBalanceTransaction {
52    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
53        f.debug_struct("CustomerBalanceTransaction").finish_non_exhaustive()
54    }
55}
56#[doc(hidden)]
57pub struct CustomerBalanceTransactionBuilder {
58    amount: Option<i64>,
59    checkout_session: Option<Option<stripe_types::Expandable<stripe_shared::CheckoutSession>>>,
60    created: Option<stripe_types::Timestamp>,
61    credit_note: Option<Option<stripe_types::Expandable<stripe_shared::CreditNote>>>,
62    currency: Option<stripe_types::Currency>,
63    customer: Option<stripe_types::Expandable<stripe_shared::Customer>>,
64    customer_account: Option<Option<String>>,
65    description: Option<Option<String>>,
66    ending_balance: Option<i64>,
67    id: Option<stripe_shared::CustomerBalanceTransactionId>,
68    invoice: Option<Option<stripe_types::Expandable<stripe_shared::Invoice>>>,
69    livemode: Option<bool>,
70    metadata: Option<Option<std::collections::HashMap<String, String>>>,
71    type_: Option<CustomerBalanceTransactionType>,
72}
73
74#[allow(
75    unused_variables,
76    irrefutable_let_patterns,
77    clippy::let_unit_value,
78    clippy::match_single_binding,
79    clippy::single_match
80)]
81const _: () = {
82    use miniserde::de::{Map, Visitor};
83    use miniserde::json::Value;
84    use miniserde::{Deserialize, Result, make_place};
85    use stripe_types::miniserde_helpers::FromValueOpt;
86    use stripe_types::{MapBuilder, ObjectDeser};
87
88    make_place!(Place);
89
90    impl Deserialize for CustomerBalanceTransaction {
91        fn begin(out: &mut Option<Self>) -> &mut dyn Visitor {
92            Place::new(out)
93        }
94    }
95
96    struct Builder<'a> {
97        out: &'a mut Option<CustomerBalanceTransaction>,
98        builder: CustomerBalanceTransactionBuilder,
99    }
100
101    impl Visitor for Place<CustomerBalanceTransaction> {
102        fn map(&mut self) -> Result<Box<dyn Map + '_>> {
103            Ok(Box::new(Builder {
104                out: &mut self.out,
105                builder: CustomerBalanceTransactionBuilder::deser_default(),
106            }))
107        }
108    }
109
110    impl MapBuilder for CustomerBalanceTransactionBuilder {
111        type Out = CustomerBalanceTransaction;
112        fn key(&mut self, k: &str) -> Result<&mut dyn Visitor> {
113            Ok(match k {
114                "amount" => Deserialize::begin(&mut self.amount),
115                "checkout_session" => Deserialize::begin(&mut self.checkout_session),
116                "created" => Deserialize::begin(&mut self.created),
117                "credit_note" => Deserialize::begin(&mut self.credit_note),
118                "currency" => Deserialize::begin(&mut self.currency),
119                "customer" => Deserialize::begin(&mut self.customer),
120                "customer_account" => Deserialize::begin(&mut self.customer_account),
121                "description" => Deserialize::begin(&mut self.description),
122                "ending_balance" => Deserialize::begin(&mut self.ending_balance),
123                "id" => Deserialize::begin(&mut self.id),
124                "invoice" => Deserialize::begin(&mut self.invoice),
125                "livemode" => Deserialize::begin(&mut self.livemode),
126                "metadata" => Deserialize::begin(&mut self.metadata),
127                "type" => Deserialize::begin(&mut self.type_),
128                _ => <dyn Visitor>::ignore(),
129            })
130        }
131
132        fn deser_default() -> Self {
133            Self {
134                amount: None,
135                checkout_session: Some(None),
136                created: None,
137                credit_note: Some(None),
138                currency: None,
139                customer: None,
140                customer_account: Some(None),
141                description: Some(None),
142                ending_balance: None,
143                id: None,
144                invoice: Some(None),
145                livemode: None,
146                metadata: Some(None),
147                type_: None,
148            }
149        }
150
151        fn take_out(&mut self) -> Option<Self::Out> {
152            let (
153                Some(amount),
154                Some(checkout_session),
155                Some(created),
156                Some(credit_note),
157                Some(currency),
158                Some(customer),
159                Some(customer_account),
160                Some(description),
161                Some(ending_balance),
162                Some(id),
163                Some(invoice),
164                Some(livemode),
165                Some(metadata),
166                Some(type_),
167            ) = (
168                self.amount,
169                self.checkout_session.take(),
170                self.created,
171                self.credit_note.take(),
172                self.currency.take(),
173                self.customer.take(),
174                self.customer_account.take(),
175                self.description.take(),
176                self.ending_balance,
177                self.id.take(),
178                self.invoice.take(),
179                self.livemode,
180                self.metadata.take(),
181                self.type_.take(),
182            )
183            else {
184                return None;
185            };
186            Some(Self::Out {
187                amount,
188                checkout_session,
189                created,
190                credit_note,
191                currency,
192                customer,
193                customer_account,
194                description,
195                ending_balance,
196                id,
197                invoice,
198                livemode,
199                metadata,
200                type_,
201            })
202        }
203    }
204
205    impl Map for Builder<'_> {
206        fn key(&mut self, k: &str) -> Result<&mut dyn Visitor> {
207            self.builder.key(k)
208        }
209
210        fn finish(&mut self) -> Result<()> {
211            *self.out = self.builder.take_out();
212            Ok(())
213        }
214    }
215
216    impl ObjectDeser for CustomerBalanceTransaction {
217        type Builder = CustomerBalanceTransactionBuilder;
218    }
219
220    impl FromValueOpt for CustomerBalanceTransaction {
221        fn from_value(v: Value) -> Option<Self> {
222            let Value::Object(obj) = v else {
223                return None;
224            };
225            let mut b = CustomerBalanceTransactionBuilder::deser_default();
226            for (k, v) in obj {
227                match k.as_str() {
228                    "amount" => b.amount = FromValueOpt::from_value(v),
229                    "checkout_session" => b.checkout_session = FromValueOpt::from_value(v),
230                    "created" => b.created = FromValueOpt::from_value(v),
231                    "credit_note" => b.credit_note = FromValueOpt::from_value(v),
232                    "currency" => b.currency = FromValueOpt::from_value(v),
233                    "customer" => b.customer = FromValueOpt::from_value(v),
234                    "customer_account" => b.customer_account = FromValueOpt::from_value(v),
235                    "description" => b.description = FromValueOpt::from_value(v),
236                    "ending_balance" => b.ending_balance = FromValueOpt::from_value(v),
237                    "id" => b.id = FromValueOpt::from_value(v),
238                    "invoice" => b.invoice = FromValueOpt::from_value(v),
239                    "livemode" => b.livemode = FromValueOpt::from_value(v),
240                    "metadata" => b.metadata = FromValueOpt::from_value(v),
241                    "type" => b.type_ = FromValueOpt::from_value(v),
242                    _ => {}
243                }
244            }
245            b.take_out()
246        }
247    }
248};
249#[cfg(feature = "serialize")]
250impl serde::Serialize for CustomerBalanceTransaction {
251    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
252        use serde::ser::SerializeStruct;
253        let mut s = s.serialize_struct("CustomerBalanceTransaction", 15)?;
254        s.serialize_field("amount", &self.amount)?;
255        s.serialize_field("checkout_session", &self.checkout_session)?;
256        s.serialize_field("created", &self.created)?;
257        s.serialize_field("credit_note", &self.credit_note)?;
258        s.serialize_field("currency", &self.currency)?;
259        s.serialize_field("customer", &self.customer)?;
260        s.serialize_field("customer_account", &self.customer_account)?;
261        s.serialize_field("description", &self.description)?;
262        s.serialize_field("ending_balance", &self.ending_balance)?;
263        s.serialize_field("id", &self.id)?;
264        s.serialize_field("invoice", &self.invoice)?;
265        s.serialize_field("livemode", &self.livemode)?;
266        s.serialize_field("metadata", &self.metadata)?;
267        s.serialize_field("type", &self.type_)?;
268
269        s.serialize_field("object", "customer_balance_transaction")?;
270        s.end()
271    }
272}
273/// Transaction type: `adjustment`, `applied_to_invoice`, `credit_note`, `initial`, `invoice_overpaid`, `invoice_too_large`, `invoice_too_small`, `unspent_receiver_credit`, `unapplied_from_invoice`, `checkout_session_subscription_payment`, or `checkout_session_subscription_payment_canceled`.
274/// See the [Customer Balance page](https://docs.stripe.com/billing/customer/balance#types) to learn more about transaction types.
275#[derive(Clone, Eq, PartialEq)]
276#[non_exhaustive]
277pub enum CustomerBalanceTransactionType {
278    Adjustment,
279    AppliedToInvoice,
280    CheckoutSessionSubscriptionPayment,
281    CheckoutSessionSubscriptionPaymentCanceled,
282    CreditNote,
283    Initial,
284    InvoiceOverpaid,
285    InvoiceTooLarge,
286    InvoiceTooSmall,
287    Migration,
288    UnappliedFromInvoice,
289    UnspentReceiverCredit,
290    /// An unrecognized value from Stripe. Should not be used as a request parameter.
291    Unknown(String),
292}
293impl CustomerBalanceTransactionType {
294    pub fn as_str(&self) -> &str {
295        use CustomerBalanceTransactionType::*;
296        match self {
297            Adjustment => "adjustment",
298            AppliedToInvoice => "applied_to_invoice",
299            CheckoutSessionSubscriptionPayment => "checkout_session_subscription_payment",
300            CheckoutSessionSubscriptionPaymentCanceled => {
301                "checkout_session_subscription_payment_canceled"
302            }
303            CreditNote => "credit_note",
304            Initial => "initial",
305            InvoiceOverpaid => "invoice_overpaid",
306            InvoiceTooLarge => "invoice_too_large",
307            InvoiceTooSmall => "invoice_too_small",
308            Migration => "migration",
309            UnappliedFromInvoice => "unapplied_from_invoice",
310            UnspentReceiverCredit => "unspent_receiver_credit",
311            Unknown(v) => v,
312        }
313    }
314}
315
316impl std::str::FromStr for CustomerBalanceTransactionType {
317    type Err = std::convert::Infallible;
318    fn from_str(s: &str) -> Result<Self, Self::Err> {
319        use CustomerBalanceTransactionType::*;
320        match s {
321            "adjustment" => Ok(Adjustment),
322            "applied_to_invoice" => Ok(AppliedToInvoice),
323            "checkout_session_subscription_payment" => Ok(CheckoutSessionSubscriptionPayment),
324            "checkout_session_subscription_payment_canceled" => {
325                Ok(CheckoutSessionSubscriptionPaymentCanceled)
326            }
327            "credit_note" => Ok(CreditNote),
328            "initial" => Ok(Initial),
329            "invoice_overpaid" => Ok(InvoiceOverpaid),
330            "invoice_too_large" => Ok(InvoiceTooLarge),
331            "invoice_too_small" => Ok(InvoiceTooSmall),
332            "migration" => Ok(Migration),
333            "unapplied_from_invoice" => Ok(UnappliedFromInvoice),
334            "unspent_receiver_credit" => Ok(UnspentReceiverCredit),
335            v => {
336                tracing::warn!(
337                    "Unknown value '{}' for enum '{}'",
338                    v,
339                    "CustomerBalanceTransactionType"
340                );
341                Ok(Unknown(v.to_owned()))
342            }
343        }
344    }
345}
346impl std::fmt::Display for CustomerBalanceTransactionType {
347    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
348        f.write_str(self.as_str())
349    }
350}
351
352#[cfg(not(feature = "redact-generated-debug"))]
353impl std::fmt::Debug for CustomerBalanceTransactionType {
354    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
355        f.write_str(self.as_str())
356    }
357}
358#[cfg(feature = "redact-generated-debug")]
359impl std::fmt::Debug for CustomerBalanceTransactionType {
360    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
361        f.debug_struct(stringify!(CustomerBalanceTransactionType)).finish_non_exhaustive()
362    }
363}
364#[cfg(feature = "serialize")]
365impl serde::Serialize for CustomerBalanceTransactionType {
366    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
367    where
368        S: serde::Serializer,
369    {
370        serializer.serialize_str(self.as_str())
371    }
372}
373impl miniserde::Deserialize for CustomerBalanceTransactionType {
374    fn begin(out: &mut Option<Self>) -> &mut dyn miniserde::de::Visitor {
375        crate::Place::new(out)
376    }
377}
378
379impl miniserde::de::Visitor for crate::Place<CustomerBalanceTransactionType> {
380    fn string(&mut self, s: &str) -> miniserde::Result<()> {
381        use std::str::FromStr;
382        self.out = Some(CustomerBalanceTransactionType::from_str(s).expect("infallible"));
383        Ok(())
384    }
385}
386
387stripe_types::impl_from_val_with_from_str!(CustomerBalanceTransactionType);
388#[cfg(feature = "deserialize")]
389impl<'de> serde::Deserialize<'de> for CustomerBalanceTransactionType {
390    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
391        use std::str::FromStr;
392        let s: std::borrow::Cow<'de, str> = serde::Deserialize::deserialize(deserializer)?;
393        Ok(Self::from_str(&s).expect("infallible"))
394    }
395}
396impl stripe_types::Object for CustomerBalanceTransaction {
397    type Id = stripe_shared::CustomerBalanceTransactionId;
398    fn id(&self) -> &Self::Id {
399        &self.id
400    }
401
402    fn into_id(self) -> Self::Id {
403        self.id
404    }
405}
406stripe_types::def_id!(CustomerBalanceTransactionId);