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