Skip to main content

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