1#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
5pub enum TaxSystem {
6 Vat,
8 Gst,
10 Sst,
12 Consumption,
14}
15
16impl TaxSystem {
17 pub fn as_str(self) -> &'static str {
19 match self {
20 Self::Vat => "VAT",
21 Self::Gst => "GST",
22 Self::Sst => "SST",
23 Self::Consumption => "CONSUMPTION",
24 }
25 }
26
27 pub fn parse(s: &str) -> Option<Self> {
29 match s.trim().to_ascii_uppercase().as_str() {
30 "VAT" => Some(Self::Vat),
31 "GST" => Some(Self::Gst),
32 "SST" | "SALES" | "SERVICE" => Some(Self::Sst),
33 "CONSUMPTION" | "CT" => Some(Self::Consumption),
34 _ => None,
35 }
36 }
37}
38
39#[derive(Debug, Clone, PartialEq, Eq)]
44pub struct TaxCategory {
45 pub system: TaxSystem,
47 pub code: String,
50 pub percent: Option<crate::numeric::Percentage>,
52}
53
54impl TaxCategory {
55 pub fn vat(code: impl Into<String>, percent: impl Into<crate::numeric::Percentage>) -> Self {
57 Self {
58 system: TaxSystem::Vat,
59 code: code.into(),
60 percent: Some(percent.into()),
61 }
62 }
63
64 pub fn sst(code: impl Into<String>, percent: impl Into<crate::numeric::Percentage>) -> Self {
66 Self {
67 system: TaxSystem::Sst,
68 code: code.into(),
69 percent: Some(percent.into()),
70 }
71 }
72
73 pub fn gst(code: impl Into<String>, percent: impl Into<crate::numeric::Percentage>) -> Self {
75 Self {
76 system: TaxSystem::Gst,
77 code: code.into(),
78 percent: Some(percent.into()),
79 }
80 }
81
82 pub fn out_of_scope() -> Self {
84 Self {
85 system: TaxSystem::Vat,
86 code: "O".into(),
87 percent: None,
88 }
89 }
90
91 pub fn ttx() -> Self {
93 Self {
94 system: TaxSystem::Sst,
95 code: "TTX".into(),
96 percent: None,
97 }
98 }
99}
100
101pub fn wire_scheme(
103 profile: crate::profile::Profile,
104 system: TaxSystem,
105 category: &str,
106) -> &'static str {
107 use crate::profile::Profile;
108 match profile {
109 Profile::En16931 | Profile::PeppolBis3 => "VAT",
110 Profile::PintMy if category.eq_ignore_ascii_case("TTX") => "AAL",
111 Profile::PintMy => "VAT",
112 Profile::Pint => match system {
113 TaxSystem::Gst => "GST",
114 _ => "VAT",
115 },
116 Profile::Unknown => "VAT",
118 }
119}
120
121pub fn pint_my_category(code: &str) -> bool {
123 matches!(code, "SA" | "SE" | "HVG" | "LVG" | "TTX" | "E" | "O")
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129
130 #[test]
131 fn vat_cgst_is_not_vat() {
132 assert_eq!(TaxSystem::parse("VAT/CGST"), None);
133 assert_eq!(TaxSystem::parse("VAT"), Some(TaxSystem::Vat));
134 }
135}