stripe_shared/
tax_rate.rs

1/// Tax rates can be applied to [invoices](/invoicing/taxes/tax-rates), [subscriptions](/billing/taxes/tax-rates) and [Checkout Sessions](/payments/checkout/use-manual-tax-rates) to collect tax.
2///
3/// Related guide: [Tax rates](/billing/taxes/tax-rates)
4///
5/// For more details see <<https://stripe.com/docs/api/tax_rates/object>>.
6#[derive(Clone, Debug)]
7#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
8pub struct TaxRate {
9    /// Defaults to `true`.
10    /// When set to `false`, this tax rate cannot be used with new applications or Checkout Sessions, but will still work for subscriptions and invoices that already have it set.
11    pub active: bool,
12    /// Two-letter country code ([ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)).
13    pub country: Option<String>,
14    /// Time at which the object was created. Measured in seconds since the Unix epoch.
15    pub created: stripe_types::Timestamp,
16    /// An arbitrary string attached to the tax rate for your internal use only.
17    /// It will not be visible to your customers.
18    pub description: Option<String>,
19    /// The display name of the tax rates as it will appear to your customer on their receipt email, PDF, and the hosted invoice page.
20    pub display_name: String,
21    /// Actual/effective tax rate percentage out of 100.
22    /// For tax calculations with automatic_tax[enabled]=true,.
23    /// this percentage reflects the rate actually used to calculate tax based on the product's taxability
24    /// and whether the user is registered to collect taxes in the corresponding jurisdiction.
25    pub effective_percentage: Option<f64>,
26    /// The amount of the tax rate when the `rate_type` is `flat_amount`.
27    /// Tax rates with `rate_type` `percentage` can vary based on the transaction, resulting in this field being `null`.
28    /// This field exposes the amount and currency of the flat tax rate.
29    pub flat_amount: Option<stripe_shared::TaxRateFlatAmount>,
30    /// Unique identifier for the object.
31    pub id: stripe_shared::TaxRateId,
32    /// This specifies if the tax rate is inclusive or exclusive.
33    pub inclusive: bool,
34    /// The jurisdiction for the tax rate.
35    /// You can use this label field for tax reporting purposes.
36    /// It also appears on your customer’s invoice.
37    pub jurisdiction: Option<String>,
38    /// The level of the jurisdiction that imposes this tax rate.
39    /// Will be `null` for manually defined tax rates.
40    pub jurisdiction_level: Option<TaxRateJurisdictionLevel>,
41    /// Has the value `true` if the object exists in live mode or the value `false` if the object exists in test mode.
42    pub livemode: bool,
43    /// Set of [key-value pairs](https://stripe.com/docs/api/metadata) that you can attach to an object.
44    /// This can be useful for storing additional information about the object in a structured format.
45    pub metadata: Option<std::collections::HashMap<String, String>>,
46    /// Tax rate percentage out of 100.
47    /// For tax calculations with automatic_tax[enabled]=true, this percentage includes the statutory tax rate of non-taxable jurisdictions.
48    pub percentage: f64,
49    /// Indicates the type of tax rate applied to the taxable amount.
50    /// This value can be `null` when no tax applies to the location.
51    /// This field is only present for TaxRates created by Stripe Tax.
52    pub rate_type: Option<TaxRateRateType>,
53    /// [ISO 3166-2 subdivision code](https://en.wikipedia.org/wiki/ISO_3166-2), without country prefix.
54    /// For example, "NY" for New York, United States.
55    pub state: Option<String>,
56    /// The high-level tax type, such as `vat` or `sales_tax`.
57    pub tax_type: Option<stripe_shared::TaxRateTaxType>,
58}
59#[doc(hidden)]
60pub struct TaxRateBuilder {
61    active: Option<bool>,
62    country: Option<Option<String>>,
63    created: Option<stripe_types::Timestamp>,
64    description: Option<Option<String>>,
65    display_name: Option<String>,
66    effective_percentage: Option<Option<f64>>,
67    flat_amount: Option<Option<stripe_shared::TaxRateFlatAmount>>,
68    id: Option<stripe_shared::TaxRateId>,
69    inclusive: Option<bool>,
70    jurisdiction: Option<Option<String>>,
71    jurisdiction_level: Option<Option<TaxRateJurisdictionLevel>>,
72    livemode: Option<bool>,
73    metadata: Option<Option<std::collections::HashMap<String, String>>>,
74    percentage: Option<f64>,
75    rate_type: Option<Option<TaxRateRateType>>,
76    state: Option<Option<String>>,
77    tax_type: Option<Option<stripe_shared::TaxRateTaxType>>,
78}
79
80#[allow(
81    unused_variables,
82    irrefutable_let_patterns,
83    clippy::let_unit_value,
84    clippy::match_single_binding,
85    clippy::single_match
86)]
87const _: () = {
88    use miniserde::de::{Map, Visitor};
89    use miniserde::json::Value;
90    use miniserde::{Deserialize, Result, make_place};
91    use stripe_types::miniserde_helpers::FromValueOpt;
92    use stripe_types::{MapBuilder, ObjectDeser};
93
94    make_place!(Place);
95
96    impl Deserialize for TaxRate {
97        fn begin(out: &mut Option<Self>) -> &mut dyn Visitor {
98            Place::new(out)
99        }
100    }
101
102    struct Builder<'a> {
103        out: &'a mut Option<TaxRate>,
104        builder: TaxRateBuilder,
105    }
106
107    impl Visitor for Place<TaxRate> {
108        fn map(&mut self) -> Result<Box<dyn Map + '_>> {
109            Ok(Box::new(Builder { out: &mut self.out, builder: TaxRateBuilder::deser_default() }))
110        }
111    }
112
113    impl MapBuilder for TaxRateBuilder {
114        type Out = TaxRate;
115        fn key(&mut self, k: &str) -> Result<&mut dyn Visitor> {
116            Ok(match k {
117                "active" => Deserialize::begin(&mut self.active),
118                "country" => Deserialize::begin(&mut self.country),
119                "created" => Deserialize::begin(&mut self.created),
120                "description" => Deserialize::begin(&mut self.description),
121                "display_name" => Deserialize::begin(&mut self.display_name),
122                "effective_percentage" => Deserialize::begin(&mut self.effective_percentage),
123                "flat_amount" => Deserialize::begin(&mut self.flat_amount),
124                "id" => Deserialize::begin(&mut self.id),
125                "inclusive" => Deserialize::begin(&mut self.inclusive),
126                "jurisdiction" => Deserialize::begin(&mut self.jurisdiction),
127                "jurisdiction_level" => Deserialize::begin(&mut self.jurisdiction_level),
128                "livemode" => Deserialize::begin(&mut self.livemode),
129                "metadata" => Deserialize::begin(&mut self.metadata),
130                "percentage" => Deserialize::begin(&mut self.percentage),
131                "rate_type" => Deserialize::begin(&mut self.rate_type),
132                "state" => Deserialize::begin(&mut self.state),
133                "tax_type" => Deserialize::begin(&mut self.tax_type),
134                _ => <dyn Visitor>::ignore(),
135            })
136        }
137
138        fn deser_default() -> Self {
139            Self {
140                active: Deserialize::default(),
141                country: Deserialize::default(),
142                created: Deserialize::default(),
143                description: Deserialize::default(),
144                display_name: Deserialize::default(),
145                effective_percentage: Deserialize::default(),
146                flat_amount: Deserialize::default(),
147                id: Deserialize::default(),
148                inclusive: Deserialize::default(),
149                jurisdiction: Deserialize::default(),
150                jurisdiction_level: Deserialize::default(),
151                livemode: Deserialize::default(),
152                metadata: Deserialize::default(),
153                percentage: Deserialize::default(),
154                rate_type: Deserialize::default(),
155                state: Deserialize::default(),
156                tax_type: Deserialize::default(),
157            }
158        }
159
160        fn take_out(&mut self) -> Option<Self::Out> {
161            let (
162                Some(active),
163                Some(country),
164                Some(created),
165                Some(description),
166                Some(display_name),
167                Some(effective_percentage),
168                Some(flat_amount),
169                Some(id),
170                Some(inclusive),
171                Some(jurisdiction),
172                Some(jurisdiction_level),
173                Some(livemode),
174                Some(metadata),
175                Some(percentage),
176                Some(rate_type),
177                Some(state),
178                Some(tax_type),
179            ) = (
180                self.active,
181                self.country.take(),
182                self.created,
183                self.description.take(),
184                self.display_name.take(),
185                self.effective_percentage,
186                self.flat_amount.take(),
187                self.id.take(),
188                self.inclusive,
189                self.jurisdiction.take(),
190                self.jurisdiction_level.take(),
191                self.livemode,
192                self.metadata.take(),
193                self.percentage,
194                self.rate_type.take(),
195                self.state.take(),
196                self.tax_type.take(),
197            )
198            else {
199                return None;
200            };
201            Some(Self::Out {
202                active,
203                country,
204                created,
205                description,
206                display_name,
207                effective_percentage,
208                flat_amount,
209                id,
210                inclusive,
211                jurisdiction,
212                jurisdiction_level,
213                livemode,
214                metadata,
215                percentage,
216                rate_type,
217                state,
218                tax_type,
219            })
220        }
221    }
222
223    impl Map for Builder<'_> {
224        fn key(&mut self, k: &str) -> Result<&mut dyn Visitor> {
225            self.builder.key(k)
226        }
227
228        fn finish(&mut self) -> Result<()> {
229            *self.out = self.builder.take_out();
230            Ok(())
231        }
232    }
233
234    impl ObjectDeser for TaxRate {
235        type Builder = TaxRateBuilder;
236    }
237
238    impl FromValueOpt for TaxRate {
239        fn from_value(v: Value) -> Option<Self> {
240            let Value::Object(obj) = v else {
241                return None;
242            };
243            let mut b = TaxRateBuilder::deser_default();
244            for (k, v) in obj {
245                match k.as_str() {
246                    "active" => b.active = FromValueOpt::from_value(v),
247                    "country" => b.country = FromValueOpt::from_value(v),
248                    "created" => b.created = FromValueOpt::from_value(v),
249                    "description" => b.description = FromValueOpt::from_value(v),
250                    "display_name" => b.display_name = FromValueOpt::from_value(v),
251                    "effective_percentage" => b.effective_percentage = FromValueOpt::from_value(v),
252                    "flat_amount" => b.flat_amount = FromValueOpt::from_value(v),
253                    "id" => b.id = FromValueOpt::from_value(v),
254                    "inclusive" => b.inclusive = FromValueOpt::from_value(v),
255                    "jurisdiction" => b.jurisdiction = FromValueOpt::from_value(v),
256                    "jurisdiction_level" => b.jurisdiction_level = FromValueOpt::from_value(v),
257                    "livemode" => b.livemode = FromValueOpt::from_value(v),
258                    "metadata" => b.metadata = FromValueOpt::from_value(v),
259                    "percentage" => b.percentage = FromValueOpt::from_value(v),
260                    "rate_type" => b.rate_type = FromValueOpt::from_value(v),
261                    "state" => b.state = FromValueOpt::from_value(v),
262                    "tax_type" => b.tax_type = FromValueOpt::from_value(v),
263                    _ => {}
264                }
265            }
266            b.take_out()
267        }
268    }
269};
270#[cfg(feature = "serialize")]
271impl serde::Serialize for TaxRate {
272    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
273        use serde::ser::SerializeStruct;
274        let mut s = s.serialize_struct("TaxRate", 18)?;
275        s.serialize_field("active", &self.active)?;
276        s.serialize_field("country", &self.country)?;
277        s.serialize_field("created", &self.created)?;
278        s.serialize_field("description", &self.description)?;
279        s.serialize_field("display_name", &self.display_name)?;
280        s.serialize_field("effective_percentage", &self.effective_percentage)?;
281        s.serialize_field("flat_amount", &self.flat_amount)?;
282        s.serialize_field("id", &self.id)?;
283        s.serialize_field("inclusive", &self.inclusive)?;
284        s.serialize_field("jurisdiction", &self.jurisdiction)?;
285        s.serialize_field("jurisdiction_level", &self.jurisdiction_level)?;
286        s.serialize_field("livemode", &self.livemode)?;
287        s.serialize_field("metadata", &self.metadata)?;
288        s.serialize_field("percentage", &self.percentage)?;
289        s.serialize_field("rate_type", &self.rate_type)?;
290        s.serialize_field("state", &self.state)?;
291        s.serialize_field("tax_type", &self.tax_type)?;
292
293        s.serialize_field("object", "tax_rate")?;
294        s.end()
295    }
296}
297/// The level of the jurisdiction that imposes this tax rate.
298/// Will be `null` for manually defined tax rates.
299#[derive(Clone, Eq, PartialEq)]
300#[non_exhaustive]
301pub enum TaxRateJurisdictionLevel {
302    City,
303    Country,
304    County,
305    District,
306    Multiple,
307    State,
308    /// An unrecognized value from Stripe. Should not be used as a request parameter.
309    Unknown(String),
310}
311impl TaxRateJurisdictionLevel {
312    pub fn as_str(&self) -> &str {
313        use TaxRateJurisdictionLevel::*;
314        match self {
315            City => "city",
316            Country => "country",
317            County => "county",
318            District => "district",
319            Multiple => "multiple",
320            State => "state",
321            Unknown(v) => v,
322        }
323    }
324}
325
326impl std::str::FromStr for TaxRateJurisdictionLevel {
327    type Err = std::convert::Infallible;
328    fn from_str(s: &str) -> Result<Self, Self::Err> {
329        use TaxRateJurisdictionLevel::*;
330        match s {
331            "city" => Ok(City),
332            "country" => Ok(Country),
333            "county" => Ok(County),
334            "district" => Ok(District),
335            "multiple" => Ok(Multiple),
336            "state" => Ok(State),
337            v => {
338                tracing::warn!("Unknown value '{}' for enum '{}'", v, "TaxRateJurisdictionLevel");
339                Ok(Unknown(v.to_owned()))
340            }
341        }
342    }
343}
344impl std::fmt::Display for TaxRateJurisdictionLevel {
345    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
346        f.write_str(self.as_str())
347    }
348}
349
350impl std::fmt::Debug for TaxRateJurisdictionLevel {
351    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
352        f.write_str(self.as_str())
353    }
354}
355#[cfg(feature = "serialize")]
356impl serde::Serialize for TaxRateJurisdictionLevel {
357    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
358    where
359        S: serde::Serializer,
360    {
361        serializer.serialize_str(self.as_str())
362    }
363}
364impl miniserde::Deserialize for TaxRateJurisdictionLevel {
365    fn begin(out: &mut Option<Self>) -> &mut dyn miniserde::de::Visitor {
366        crate::Place::new(out)
367    }
368}
369
370impl miniserde::de::Visitor for crate::Place<TaxRateJurisdictionLevel> {
371    fn string(&mut self, s: &str) -> miniserde::Result<()> {
372        use std::str::FromStr;
373        self.out = Some(TaxRateJurisdictionLevel::from_str(s).expect("infallible"));
374        Ok(())
375    }
376}
377
378stripe_types::impl_from_val_with_from_str!(TaxRateJurisdictionLevel);
379#[cfg(feature = "deserialize")]
380impl<'de> serde::Deserialize<'de> for TaxRateJurisdictionLevel {
381    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
382        use std::str::FromStr;
383        let s: std::borrow::Cow<'de, str> = serde::Deserialize::deserialize(deserializer)?;
384        Ok(Self::from_str(&s).expect("infallible"))
385    }
386}
387/// Indicates the type of tax rate applied to the taxable amount.
388/// This value can be `null` when no tax applies to the location.
389/// This field is only present for TaxRates created by Stripe Tax.
390#[derive(Clone, Eq, PartialEq)]
391#[non_exhaustive]
392pub enum TaxRateRateType {
393    FlatAmount,
394    Percentage,
395    /// An unrecognized value from Stripe. Should not be used as a request parameter.
396    Unknown(String),
397}
398impl TaxRateRateType {
399    pub fn as_str(&self) -> &str {
400        use TaxRateRateType::*;
401        match self {
402            FlatAmount => "flat_amount",
403            Percentage => "percentage",
404            Unknown(v) => v,
405        }
406    }
407}
408
409impl std::str::FromStr for TaxRateRateType {
410    type Err = std::convert::Infallible;
411    fn from_str(s: &str) -> Result<Self, Self::Err> {
412        use TaxRateRateType::*;
413        match s {
414            "flat_amount" => Ok(FlatAmount),
415            "percentage" => Ok(Percentage),
416            v => {
417                tracing::warn!("Unknown value '{}' for enum '{}'", v, "TaxRateRateType");
418                Ok(Unknown(v.to_owned()))
419            }
420        }
421    }
422}
423impl std::fmt::Display for TaxRateRateType {
424    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
425        f.write_str(self.as_str())
426    }
427}
428
429impl std::fmt::Debug for TaxRateRateType {
430    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
431        f.write_str(self.as_str())
432    }
433}
434#[cfg(feature = "serialize")]
435impl serde::Serialize for TaxRateRateType {
436    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
437    where
438        S: serde::Serializer,
439    {
440        serializer.serialize_str(self.as_str())
441    }
442}
443impl miniserde::Deserialize for TaxRateRateType {
444    fn begin(out: &mut Option<Self>) -> &mut dyn miniserde::de::Visitor {
445        crate::Place::new(out)
446    }
447}
448
449impl miniserde::de::Visitor for crate::Place<TaxRateRateType> {
450    fn string(&mut self, s: &str) -> miniserde::Result<()> {
451        use std::str::FromStr;
452        self.out = Some(TaxRateRateType::from_str(s).expect("infallible"));
453        Ok(())
454    }
455}
456
457stripe_types::impl_from_val_with_from_str!(TaxRateRateType);
458#[cfg(feature = "deserialize")]
459impl<'de> serde::Deserialize<'de> for TaxRateRateType {
460    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
461        use std::str::FromStr;
462        let s: std::borrow::Cow<'de, str> = serde::Deserialize::deserialize(deserializer)?;
463        Ok(Self::from_str(&s).expect("infallible"))
464    }
465}
466impl stripe_types::Object for TaxRate {
467    type Id = stripe_shared::TaxRateId;
468    fn id(&self) -> &Self::Id {
469        &self.id
470    }
471
472    fn into_id(self) -> Self::Id {
473        self.id
474    }
475}
476stripe_types::def_id!(TaxRateId);
477#[derive(Clone, Eq, PartialEq)]
478#[non_exhaustive]
479pub enum TaxRateTaxType {
480    AmusementTax,
481    CommunicationsTax,
482    Gst,
483    Hst,
484    Igst,
485    Jct,
486    LeaseTax,
487    Pst,
488    Qst,
489    RetailDeliveryFee,
490    Rst,
491    SalesTax,
492    ServiceTax,
493    Vat,
494    /// An unrecognized value from Stripe. Should not be used as a request parameter.
495    Unknown(String),
496}
497impl TaxRateTaxType {
498    pub fn as_str(&self) -> &str {
499        use TaxRateTaxType::*;
500        match self {
501            AmusementTax => "amusement_tax",
502            CommunicationsTax => "communications_tax",
503            Gst => "gst",
504            Hst => "hst",
505            Igst => "igst",
506            Jct => "jct",
507            LeaseTax => "lease_tax",
508            Pst => "pst",
509            Qst => "qst",
510            RetailDeliveryFee => "retail_delivery_fee",
511            Rst => "rst",
512            SalesTax => "sales_tax",
513            ServiceTax => "service_tax",
514            Vat => "vat",
515            Unknown(v) => v,
516        }
517    }
518}
519
520impl std::str::FromStr for TaxRateTaxType {
521    type Err = std::convert::Infallible;
522    fn from_str(s: &str) -> Result<Self, Self::Err> {
523        use TaxRateTaxType::*;
524        match s {
525            "amusement_tax" => Ok(AmusementTax),
526            "communications_tax" => Ok(CommunicationsTax),
527            "gst" => Ok(Gst),
528            "hst" => Ok(Hst),
529            "igst" => Ok(Igst),
530            "jct" => Ok(Jct),
531            "lease_tax" => Ok(LeaseTax),
532            "pst" => Ok(Pst),
533            "qst" => Ok(Qst),
534            "retail_delivery_fee" => Ok(RetailDeliveryFee),
535            "rst" => Ok(Rst),
536            "sales_tax" => Ok(SalesTax),
537            "service_tax" => Ok(ServiceTax),
538            "vat" => Ok(Vat),
539            v => {
540                tracing::warn!("Unknown value '{}' for enum '{}'", v, "TaxRateTaxType");
541                Ok(Unknown(v.to_owned()))
542            }
543        }
544    }
545}
546impl std::fmt::Display for TaxRateTaxType {
547    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
548        f.write_str(self.as_str())
549    }
550}
551
552impl std::fmt::Debug for TaxRateTaxType {
553    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
554        f.write_str(self.as_str())
555    }
556}
557impl serde::Serialize for TaxRateTaxType {
558    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
559    where
560        S: serde::Serializer,
561    {
562        serializer.serialize_str(self.as_str())
563    }
564}
565impl miniserde::Deserialize for TaxRateTaxType {
566    fn begin(out: &mut Option<Self>) -> &mut dyn miniserde::de::Visitor {
567        crate::Place::new(out)
568    }
569}
570
571impl miniserde::de::Visitor for crate::Place<TaxRateTaxType> {
572    fn string(&mut self, s: &str) -> miniserde::Result<()> {
573        use std::str::FromStr;
574        self.out = Some(TaxRateTaxType::from_str(s).expect("infallible"));
575        Ok(())
576    }
577}
578
579stripe_types::impl_from_val_with_from_str!(TaxRateTaxType);
580#[cfg(feature = "deserialize")]
581impl<'de> serde::Deserialize<'de> for TaxRateTaxType {
582    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
583        use std::str::FromStr;
584        let s: std::borrow::Cow<'de, str> = serde::Deserialize::deserialize(deserializer)?;
585        Ok(Self::from_str(&s).expect("infallible"))
586    }
587}