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    Pst,
510    Qst,
511    RetailDeliveryFee,
512    Rst,
513    SalesTax,
514    ServiceTax,
515    Vat,
516    /// An unrecognized value from Stripe. Should not be used as a request parameter.
517    Unknown(String),
518}
519impl TaxRateTaxType {
520    pub fn as_str(&self) -> &str {
521        use TaxRateTaxType::*;
522        match self {
523            AmusementTax => "amusement_tax",
524            CommunicationsTax => "communications_tax",
525            Gst => "gst",
526            Hst => "hst",
527            Igst => "igst",
528            Jct => "jct",
529            LeaseTax => "lease_tax",
530            Pst => "pst",
531            Qst => "qst",
532            RetailDeliveryFee => "retail_delivery_fee",
533            Rst => "rst",
534            SalesTax => "sales_tax",
535            ServiceTax => "service_tax",
536            Vat => "vat",
537            Unknown(v) => v,
538        }
539    }
540}
541
542impl std::str::FromStr for TaxRateTaxType {
543    type Err = std::convert::Infallible;
544    fn from_str(s: &str) -> Result<Self, Self::Err> {
545        use TaxRateTaxType::*;
546        match s {
547            "amusement_tax" => Ok(AmusementTax),
548            "communications_tax" => Ok(CommunicationsTax),
549            "gst" => Ok(Gst),
550            "hst" => Ok(Hst),
551            "igst" => Ok(Igst),
552            "jct" => Ok(Jct),
553            "lease_tax" => Ok(LeaseTax),
554            "pst" => Ok(Pst),
555            "qst" => Ok(Qst),
556            "retail_delivery_fee" => Ok(RetailDeliveryFee),
557            "rst" => Ok(Rst),
558            "sales_tax" => Ok(SalesTax),
559            "service_tax" => Ok(ServiceTax),
560            "vat" => Ok(Vat),
561            v => {
562                tracing::warn!("Unknown value '{}' for enum '{}'", v, "TaxRateTaxType");
563                Ok(Unknown(v.to_owned()))
564            }
565        }
566    }
567}
568impl std::fmt::Display for TaxRateTaxType {
569    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
570        f.write_str(self.as_str())
571    }
572}
573
574#[cfg(not(feature = "redact-generated-debug"))]
575impl std::fmt::Debug for TaxRateTaxType {
576    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
577        f.write_str(self.as_str())
578    }
579}
580#[cfg(feature = "redact-generated-debug")]
581impl std::fmt::Debug for TaxRateTaxType {
582    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
583        f.debug_struct(stringify!(TaxRateTaxType)).finish_non_exhaustive()
584    }
585}
586impl serde::Serialize for TaxRateTaxType {
587    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
588    where
589        S: serde::Serializer,
590    {
591        serializer.serialize_str(self.as_str())
592    }
593}
594impl miniserde::Deserialize for TaxRateTaxType {
595    fn begin(out: &mut Option<Self>) -> &mut dyn miniserde::de::Visitor {
596        crate::Place::new(out)
597    }
598}
599
600impl miniserde::de::Visitor for crate::Place<TaxRateTaxType> {
601    fn string(&mut self, s: &str) -> miniserde::Result<()> {
602        use std::str::FromStr;
603        self.out = Some(TaxRateTaxType::from_str(s).expect("infallible"));
604        Ok(())
605    }
606}
607
608stripe_types::impl_from_val_with_from_str!(TaxRateTaxType);
609#[cfg(feature = "deserialize")]
610impl<'de> serde::Deserialize<'de> for TaxRateTaxType {
611    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
612        use std::str::FromStr;
613        let s: std::borrow::Cow<'de, str> = serde::Deserialize::deserialize(deserializer)?;
614        Ok(Self::from_str(&s).expect("infallible"))
615    }
616}