tax_conformance_kit 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6f7af37d7149859cbb18692e8040e9a710027fbef9f0716eacca6ed9c491c301
4
- data.tar.gz: 2dc3af404778b6b2e4c8939aa3e5b49b8fb2040ec0cba3ffd07987dea906e294
3
+ metadata.gz: a235723261c9de5283189e206244af4fc50b7d163b3f7298116520b54828d3c8
4
+ data.tar.gz: 731f67e297702bf3cfa2819caa842f1f99b00484da1f95ca0d5bbc33805edb05
5
5
  SHA512:
6
- metadata.gz: 9fb939964451a20c444da3f8ecab844203cca7472a11eb331229c8bb1623cc5ad5fa7c18bcec40abe0e1040f3ac5c03354eb4f17e186e6331dc34f08688d9a76
7
- data.tar.gz: 5fbc537124e7698d4276b0b5b13d4ffe0197d437f90160283640a37c1274e5cfb7e0e996e9ef82483fdde2c0ec8fc12516de7d33573d815569f4ecfc021f6f93
6
+ metadata.gz: f35d5ab45ae4e8b008bb11755af5b3a356628d6f04f677427bd7e86617e6fc17dd30cd1e0b09233fe32a521f6029c969410550ba0395653e219f6522a9f91752
7
+ data.tar.gz: 5c8e06176a28a065201ac3eb110d45814af4cc986aec92033439fbda1c927912d44fe041ac99cb66ebb2fbd57ea8b5d0a31ea2944de0b8a7380116924d3cf570
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Odeva
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -31,6 +31,8 @@ require "tax_conformance_kit"
31
31
 
32
32
  client = TaxConformanceKit::TaxctlClient.new
33
33
  response = client.evaluate(ruleset: ruleset_hash, booking_input: booking_input_hash)
34
+ resolved = client.evaluate_resolved(booking_input: booking_input_hash)
35
+ grouped = client.evaluate_resolved_assessment(assessment_input: assessment_input_hash)
34
36
  ```
35
37
 
36
38
  ### Advanced: override `command:`
data/bin/taxctl CHANGED
Binary file
@@ -50,13 +50,31 @@
50
50
  }
51
51
  },
52
52
  "generic.per_person_per_night": {
53
- "description": "Flat amount per guest per night. Guests = adults + children unless a predicate narrows the set.",
53
+ "description": "Flat amount per taxable guest per night. Guests = adults + children unless taxable_guest_age_gte narrows the count. max_nights caps the taxable stay units.",
54
54
  "since": "v1",
55
55
  "params_schema": {
56
56
  "type": "object",
57
57
  "required": ["amount"],
58
58
  "properties": {
59
- "amount": { "type": "number", "minimum": 0 }
59
+ "amount": { "type": "number", "minimum": 0 },
60
+ "max_nights": { "type": "integer", "minimum": 0 },
61
+ "taxable_guest_age_gte": { "type": "integer", "minimum": 0 }
62
+ },
63
+ "additionalProperties": false
64
+ }
65
+ },
66
+ "generic.per_person_per_night_discount_after_nights": {
67
+ "description": "Flat amount per taxable guest per night, with a discounted tail from a configurable night onward. Useful for regimes such as the Balearic Islands where nights 9+ are charged at 50%.",
68
+ "since": "v1",
69
+ "params_schema": {
70
+ "type": "object",
71
+ "required": ["amount", "discount_start_night", "discount_multiplier"],
72
+ "properties": {
73
+ "amount": { "type": "number", "minimum": 0 },
74
+ "discount_start_night": { "type": "integer", "minimum": 1 },
75
+ "discount_multiplier": { "type": "number", "minimum": 0 },
76
+ "max_nights": { "type": "integer", "minimum": 0 },
77
+ "taxable_guest_age_gte": { "type": "integer", "minimum": 0 }
60
78
  },
61
79
  "additionalProperties": false
62
80
  }
@@ -311,6 +329,22 @@
311
329
  },
312
330
  "additionalProperties": false
313
331
  }
332
+ },
333
+ "location.property_locality_code_not_in": {
334
+ "description": "True when the property's locality code is not in the configured list. Useful for region-wide rules that exclude one municipality, such as Catalonia tariffs outside Barcelona city.",
335
+ "since": "v1",
336
+ "params_schema": {
337
+ "type": "object",
338
+ "required": ["values"],
339
+ "properties": {
340
+ "values": {
341
+ "type": "array",
342
+ "items": { "type": "string" },
343
+ "minItems": 1
344
+ }
345
+ },
346
+ "additionalProperties": false
347
+ }
314
348
  }
315
349
  }
316
350
  }
@@ -0,0 +1,168 @@
1
+ {
2
+ "id": "es-catalonia-barcelona-city-2026-04-01",
3
+ "domain": "tourist_tax",
4
+ "lifecycle": "reviewed",
5
+ "jurisdiction": {
6
+ "country_code": "ES",
7
+ "country_name": "Spain",
8
+ "region_code": "ES-CT",
9
+ "region_name": "Catalonia"
10
+ },
11
+ "assessment_policy": {
12
+ "period": "calendar_half_year",
13
+ "notes": "Catalonia files the IEET twice per year: 1-20 April for stays accrued from October through March, and 1-20 October for stays accrued from April through September."
14
+ },
15
+ "notes": "Reviewed fixture based on the Catalonia Tax Agency's official IEET quota table effective April 1, 2026. Rates below include Barcelona city's municipal surcharge where applicable. Minors under 17 are exempt and the tax is capped at seven stay units per person.",
16
+ "rules": [
17
+ {
18
+ "id": "es-ct-bcn-city-2026-hotel-5-star",
19
+ "location_scope": {
20
+ "country_code": "ES",
21
+ "region_code": "ES-CT",
22
+ "locality_kind": "municipality",
23
+ "locality_code": "08019",
24
+ "locality_name": "Barcelona"
25
+ },
26
+ "valid_from": "2026-04-01",
27
+ "valid_to": null,
28
+ "applies_to": {
29
+ "accommodation_types": ["hotel_5_star", "luxury_hotel", "cruise"]
30
+ },
31
+ "calculation": {
32
+ "kind": "generic.per_person_per_night",
33
+ "params": {
34
+ "amount": 12.0,
35
+ "max_nights": 7,
36
+ "taxable_guest_age_gte": 17
37
+ },
38
+ "currency": "EUR"
39
+ },
40
+ "source": {
41
+ "source_url": "https://atc.gencat.cat/es/tributs/ieet/quota-tributaria",
42
+ "reviewed_at": null
43
+ },
44
+ "confidence": "reviewed",
45
+ "notes": "Barcelona city rate from April 1, 2026: EUR 12.00 for 5-star and luxury hotels, campings de lujo, and cruises."
46
+ },
47
+ {
48
+ "id": "es-ct-bcn-city-2026-hotel-4-star",
49
+ "location_scope": {
50
+ "country_code": "ES",
51
+ "region_code": "ES-CT",
52
+ "locality_kind": "municipality",
53
+ "locality_code": "08019",
54
+ "locality_name": "Barcelona"
55
+ },
56
+ "valid_from": "2026-04-01",
57
+ "valid_to": null,
58
+ "applies_to": {
59
+ "accommodation_types": ["hotel_4_star", "superior_hotel"]
60
+ },
61
+ "calculation": {
62
+ "kind": "generic.per_person_per_night",
63
+ "params": {
64
+ "amount": 8.0,
65
+ "max_nights": 7,
66
+ "taxable_guest_age_gte": 17
67
+ },
68
+ "currency": "EUR"
69
+ },
70
+ "source": {
71
+ "source_url": "https://atc.gencat.cat/es/tributs/ieet/quota-tributaria",
72
+ "reviewed_at": null
73
+ },
74
+ "confidence": "reviewed",
75
+ "notes": "Barcelona city rate from April 1, 2026: EUR 8.00 for 4-star and 4-star superior hotels."
76
+ },
77
+ {
78
+ "id": "es-ct-bcn-city-2026-tourist-home",
79
+ "location_scope": {
80
+ "country_code": "ES",
81
+ "region_code": "ES-CT",
82
+ "locality_kind": "municipality",
83
+ "locality_code": "08019",
84
+ "locality_name": "Barcelona"
85
+ },
86
+ "valid_from": "2026-04-01",
87
+ "valid_to": null,
88
+ "applies_to": {
89
+ "accommodation_types": ["tourist_apartment", "tourist_home", "private_room"]
90
+ },
91
+ "calculation": {
92
+ "kind": "generic.per_person_per_night",
93
+ "params": {
94
+ "amount": 9.5,
95
+ "max_nights": 7,
96
+ "taxable_guest_age_gte": 17
97
+ },
98
+ "currency": "EUR"
99
+ },
100
+ "source": {
101
+ "source_url": "https://atc.gencat.cat/es/tributs/ieet/quota-tributaria",
102
+ "reviewed_at": null
103
+ },
104
+ "confidence": "reviewed",
105
+ "notes": "Barcelona city rate from April 1, 2026: EUR 9.50 for tourist-use homes, tourist apartments, and private-room establishments."
106
+ },
107
+ {
108
+ "id": "es-ct-bcn-city-2026-hostel",
109
+ "location_scope": {
110
+ "country_code": "ES",
111
+ "region_code": "ES-CT",
112
+ "locality_kind": "municipality",
113
+ "locality_code": "08019",
114
+ "locality_name": "Barcelona"
115
+ },
116
+ "valid_from": "2026-04-01",
117
+ "valid_to": null,
118
+ "applies_to": {
119
+ "accommodation_types": ["hostel", "guesthouse", "boarding_house", "rural_lodging"]
120
+ },
121
+ "calculation": {
122
+ "kind": "generic.per_person_per_night",
123
+ "params": {
124
+ "amount": 6.0,
125
+ "max_nights": 7,
126
+ "taxable_guest_age_gte": 17
127
+ },
128
+ "currency": "EUR"
129
+ },
130
+ "source": {
131
+ "source_url": "https://atc.gencat.cat/es/tributs/ieet/quota-tributaria",
132
+ "reviewed_at": null
133
+ },
134
+ "confidence": "reviewed",
135
+ "notes": "Barcelona city rate from April 1, 2026: EUR 6.00 for hostels, pensions, guesthouses, rural tourism, and similar categories."
136
+ },
137
+ {
138
+ "id": "es-ct-bcn-city-2026-camping",
139
+ "location_scope": {
140
+ "country_code": "ES",
141
+ "region_code": "ES-CT",
142
+ "locality_kind": "municipality",
143
+ "locality_code": "08019",
144
+ "locality_name": "Barcelona"
145
+ },
146
+ "valid_from": "2026-04-01",
147
+ "valid_to": null,
148
+ "applies_to": {
149
+ "accommodation_types": ["camping", "camping_luxury"]
150
+ },
151
+ "calculation": {
152
+ "kind": "generic.per_person_per_night",
153
+ "params": {
154
+ "amount": 7.0,
155
+ "max_nights": 7,
156
+ "taxable_guest_age_gte": 17
157
+ },
158
+ "currency": "EUR"
159
+ },
160
+ "source": {
161
+ "source_url": "https://atc.gencat.cat/es/tributs/ieet/quota-tributaria",
162
+ "reviewed_at": null
163
+ },
164
+ "confidence": "reviewed",
165
+ "notes": "Barcelona city rate from April 1, 2026: EUR 7.00 for campsites and campings de lujo."
166
+ }
167
+ ]
168
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "id": "es-catalonia-barcelona-city-dutch-operator-hotel-5-star",
3
+ "description": "A Dutch operator with a Barcelona 5-star hotel is charged the Barcelona city IEET rate, capped at 7 nights and excluding the 15-year-old guest.",
4
+ "rule_set_path": "../2026-04-01.json",
5
+ "booking_input": {
6
+ "stay_date": "2026-06-15",
7
+ "nights": 10,
8
+ "adults": 2,
9
+ "children": 1,
10
+ "guests": [
11
+ { "age": 34, "role": "guest" },
12
+ { "age": 38, "role": "guest" },
13
+ { "age": 15, "role": "guest" }
14
+ ],
15
+ "property_location": {
16
+ "country_code": "ES",
17
+ "region_code": "ES-CT",
18
+ "locality_kind": "municipality",
19
+ "locality_code": "08019",
20
+ "locality_name": "Barcelona"
21
+ },
22
+ "operator": {
23
+ "legal_country_code": "NL",
24
+ "legal_name": "Canal Stays BV"
25
+ },
26
+ "accommodation_type": "hotel_5_star",
27
+ "subtotal": 4000
28
+ },
29
+ "expected": {
30
+ "total_tax": 168.0,
31
+ "matched_rule_ids": ["es-ct-bcn-city-2026-hotel-5-star"]
32
+ }
33
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "id": "es-catalonia-barcelona-city-tourist-home-age-17-taxed",
3
+ "description": "Barcelona city tourist-home stays tax 17-year-olds because only minors under 17 are exempt.",
4
+ "rule_set_path": "../2026-04-01.json",
5
+ "booking_input": {
6
+ "stay_date": "2026-09-10",
7
+ "nights": 3,
8
+ "adults": 1,
9
+ "children": 1,
10
+ "guests": [
11
+ { "age": 41, "role": "guest" },
12
+ { "age": 17, "role": "guest" }
13
+ ],
14
+ "property_location": {
15
+ "country_code": "ES",
16
+ "region_code": "ES-CT",
17
+ "locality_kind": "municipality",
18
+ "locality_code": "08019",
19
+ "locality_name": "Barcelona"
20
+ },
21
+ "accommodation_type": "tourist_home",
22
+ "subtotal": 900
23
+ },
24
+ "expected": {
25
+ "total_tax": 57.0,
26
+ "matched_rule_ids": ["es-ct-bcn-city-2026-tourist-home"]
27
+ }
28
+ }
@@ -0,0 +1,183 @@
1
+ {
2
+ "id": "es-catalonia-rest-of-catalonia-2026-04-01",
3
+ "domain": "tourist_tax",
4
+ "lifecycle": "reviewed",
5
+ "jurisdiction": {
6
+ "country_code": "ES",
7
+ "country_name": "Spain",
8
+ "region_code": "ES-CT",
9
+ "region_name": "Catalonia"
10
+ },
11
+ "assessment_policy": {
12
+ "period": "calendar_half_year",
13
+ "notes": "Catalonia files the IEET twice per year: 1-20 April for stays accrued from October through March, and 1-20 October for stays accrued from April through September."
14
+ },
15
+ "notes": "Reviewed fixture based on the Catalonia Tax Agency's official IEET quota table effective April 1, 2026 for the rest of Catalonia. Barcelona city is excluded explicitly through locality-code predicates. Minors under 17 are exempt and the tax is capped at seven stay units per person.",
16
+ "rules": [
17
+ {
18
+ "id": "es-ct-rest-2026-hotel-5-star",
19
+ "location_scope": {
20
+ "country_code": "ES",
21
+ "region_code": "ES-CT"
22
+ },
23
+ "valid_from": "2026-04-01",
24
+ "valid_to": null,
25
+ "applies_to": {
26
+ "accommodation_types": ["hotel_5_star", "luxury_hotel", "cruise"]
27
+ },
28
+ "predicates": [
29
+ {
30
+ "kind": "location.property_locality_code_not_in",
31
+ "params": { "values": ["08019"] }
32
+ }
33
+ ],
34
+ "calculation": {
35
+ "kind": "generic.per_person_per_night",
36
+ "params": {
37
+ "amount": 4.5,
38
+ "max_nights": 7,
39
+ "taxable_guest_age_gte": 17
40
+ },
41
+ "currency": "EUR"
42
+ },
43
+ "source": {
44
+ "source_url": "https://atc.gencat.cat/es/tributs/ieet/quota-tributaria",
45
+ "reviewed_at": null
46
+ },
47
+ "confidence": "reviewed",
48
+ "notes": "Rest of Catalonia rate from April 1, 2026: EUR 4.50 for 5-star and luxury hotels, campings de lujo, and cruises."
49
+ },
50
+ {
51
+ "id": "es-ct-rest-2026-hotel-4-star",
52
+ "location_scope": {
53
+ "country_code": "ES",
54
+ "region_code": "ES-CT"
55
+ },
56
+ "valid_from": "2026-04-01",
57
+ "valid_to": null,
58
+ "applies_to": {
59
+ "accommodation_types": ["hotel_4_star", "superior_hotel"]
60
+ },
61
+ "predicates": [
62
+ {
63
+ "kind": "location.property_locality_code_not_in",
64
+ "params": { "values": ["08019"] }
65
+ }
66
+ ],
67
+ "calculation": {
68
+ "kind": "generic.per_person_per_night",
69
+ "params": {
70
+ "amount": 1.8,
71
+ "max_nights": 7,
72
+ "taxable_guest_age_gte": 17
73
+ },
74
+ "currency": "EUR"
75
+ },
76
+ "source": {
77
+ "source_url": "https://atc.gencat.cat/es/tributs/ieet/quota-tributaria",
78
+ "reviewed_at": null
79
+ },
80
+ "confidence": "reviewed",
81
+ "notes": "Rest of Catalonia rate from April 1, 2026: EUR 1.80 for 4-star and 4-star superior hotels."
82
+ },
83
+ {
84
+ "id": "es-ct-rest-2026-tourist-home",
85
+ "location_scope": {
86
+ "country_code": "ES",
87
+ "region_code": "ES-CT"
88
+ },
89
+ "valid_from": "2026-04-01",
90
+ "valid_to": null,
91
+ "applies_to": {
92
+ "accommodation_types": ["tourist_apartment", "tourist_home", "private_room"]
93
+ },
94
+ "predicates": [
95
+ {
96
+ "kind": "location.property_locality_code_not_in",
97
+ "params": { "values": ["08019"] }
98
+ }
99
+ ],
100
+ "calculation": {
101
+ "kind": "generic.per_person_per_night",
102
+ "params": {
103
+ "amount": 1.75,
104
+ "max_nights": 7,
105
+ "taxable_guest_age_gte": 17
106
+ },
107
+ "currency": "EUR"
108
+ },
109
+ "source": {
110
+ "source_url": "https://atc.gencat.cat/es/tributs/ieet/quota-tributaria",
111
+ "reviewed_at": null
112
+ },
113
+ "confidence": "reviewed",
114
+ "notes": "Rest of Catalonia rate from April 1, 2026: EUR 1.75 for tourist-use homes, tourist apartments, and private-room establishments."
115
+ },
116
+ {
117
+ "id": "es-ct-rest-2026-hostel",
118
+ "location_scope": {
119
+ "country_code": "ES",
120
+ "region_code": "ES-CT"
121
+ },
122
+ "valid_from": "2026-04-01",
123
+ "valid_to": null,
124
+ "applies_to": {
125
+ "accommodation_types": ["hostel", "guesthouse", "boarding_house", "rural_lodging"]
126
+ },
127
+ "predicates": [
128
+ {
129
+ "kind": "location.property_locality_code_not_in",
130
+ "params": { "values": ["08019"] }
131
+ }
132
+ ],
133
+ "calculation": {
134
+ "kind": "generic.per_person_per_night",
135
+ "params": {
136
+ "amount": 0.8,
137
+ "max_nights": 7,
138
+ "taxable_guest_age_gte": 17
139
+ },
140
+ "currency": "EUR"
141
+ },
142
+ "source": {
143
+ "source_url": "https://atc.gencat.cat/es/tributs/ieet/quota-tributaria",
144
+ "reviewed_at": null
145
+ },
146
+ "confidence": "reviewed",
147
+ "notes": "Rest of Catalonia rate from April 1, 2026: EUR 0.80 for hostels, pensions, guesthouses, rural tourism, and similar categories."
148
+ },
149
+ {
150
+ "id": "es-ct-rest-2026-camping",
151
+ "location_scope": {
152
+ "country_code": "ES",
153
+ "region_code": "ES-CT"
154
+ },
155
+ "valid_from": "2026-04-01",
156
+ "valid_to": null,
157
+ "applies_to": {
158
+ "accommodation_types": ["camping", "camping_luxury"]
159
+ },
160
+ "predicates": [
161
+ {
162
+ "kind": "location.property_locality_code_not_in",
163
+ "params": { "values": ["08019"] }
164
+ }
165
+ ],
166
+ "calculation": {
167
+ "kind": "generic.per_person_per_night",
168
+ "params": {
169
+ "amount": 0.9,
170
+ "max_nights": 7,
171
+ "taxable_guest_age_gte": 17
172
+ },
173
+ "currency": "EUR"
174
+ },
175
+ "source": {
176
+ "source_url": "https://atc.gencat.cat/es/tributs/ieet/quota-tributaria",
177
+ "reviewed_at": null
178
+ },
179
+ "confidence": "reviewed",
180
+ "notes": "Rest of Catalonia rate from April 1, 2026: EUR 0.90 for campsites and campings de lujo."
181
+ }
182
+ ]
183
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "id": "es-catalonia-rest-barcelona-city-excluded",
3
+ "description": "The rest-of-Catalonia ruleset excludes Barcelona city's locality code.",
4
+ "rule_set_path": "../2026-04-01.json",
5
+ "booking_input": {
6
+ "stay_date": "2026-07-20",
7
+ "nights": 2,
8
+ "adults": 2,
9
+ "children": 0,
10
+ "property_location": {
11
+ "country_code": "ES",
12
+ "region_code": "ES-CT",
13
+ "locality_kind": "municipality",
14
+ "locality_code": "08019",
15
+ "locality_name": "Barcelona"
16
+ },
17
+ "accommodation_type": "hotel_4_star",
18
+ "subtotal": 500
19
+ },
20
+ "expected": {
21
+ "total_tax": 0,
22
+ "matched_rule_ids": []
23
+ }
24
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "id": "es-catalonia-rest-girona-hotel-4-star",
3
+ "description": "A Girona 4-star hotel outside Barcelona city uses the rest-of-Catalonia IEET tariff.",
4
+ "rule_set_path": "../2026-04-01.json",
5
+ "booking_input": {
6
+ "stay_date": "2026-07-20",
7
+ "nights": 2,
8
+ "adults": 2,
9
+ "children": 0,
10
+ "guests": [
11
+ { "age": 42, "role": "guest" },
12
+ { "age": 36, "role": "guest" }
13
+ ],
14
+ "property_location": {
15
+ "country_code": "ES",
16
+ "region_code": "ES-CT",
17
+ "locality_kind": "municipality",
18
+ "locality_code": "17079",
19
+ "locality_name": "Girona"
20
+ },
21
+ "accommodation_type": "hotel_4_star",
22
+ "subtotal": 500
23
+ },
24
+ "expected": {
25
+ "total_tax": 7.2,
26
+ "matched_rule_ids": ["es-ct-rest-2026-hotel-4-star"]
27
+ }
28
+ }
@@ -0,0 +1,166 @@
1
+ {
2
+ "id": "es-balearic-islands-2025-05-17",
3
+ "domain": "tourist_tax",
4
+ "lifecycle": "reviewed",
5
+ "jurisdiction": {
6
+ "country_code": "ES",
7
+ "country_name": "Spain",
8
+ "region_code": "ES-IB",
9
+ "region_name": "Illes Balears"
10
+ },
11
+ "assessment_policy": {
12
+ "period": "calendar_quarter",
13
+ "notes": "ATIB files the Balearic tourist-stay tax by quarter using model 700."
14
+ },
15
+ "notes": "Reviewed fixture based on the consolidated Balearic tourist-stay tax law and ATIB guidance. Guests under 16 are exempt. A 75% seasonal reduction applies from 1 November through 30 April, and from the ninth day onward the quota is reduced by 50%.",
16
+ "rules": [
17
+ {
18
+ "id": "es-ib-2025-hotel-4-star-high-season",
19
+ "location_scope": {
20
+ "country_code": "ES",
21
+ "region_code": "ES-IB"
22
+ },
23
+ "valid_from": "2025-05-17",
24
+ "valid_to": null,
25
+ "applies_to": {
26
+ "accommodation_types": ["hotel_4_star", "superior_hotel"]
27
+ },
28
+ "predicates": [
29
+ {
30
+ "kind": "stay.seasonal_window",
31
+ "params": {
32
+ "start_mmdd": "05-01",
33
+ "end_mmdd": "10-31"
34
+ }
35
+ }
36
+ ],
37
+ "calculation": {
38
+ "kind": "generic.per_person_per_night_discount_after_nights",
39
+ "params": {
40
+ "amount": 3.0,
41
+ "discount_start_night": 9,
42
+ "discount_multiplier": 0.5,
43
+ "taxable_guest_age_gte": 16
44
+ },
45
+ "currency": "EUR"
46
+ },
47
+ "source": {
48
+ "source_url": "https://www.boe.es/buscar/act.php?id=BOE-A-2016-4175",
49
+ "reviewed_at": null
50
+ },
51
+ "confidence": "reviewed",
52
+ "notes": "Balearic Islands high-season rate: EUR 3.00 for 4-star hotels and 3-star superior hotels. The law reduces the quota by 50% from the ninth day onward."
53
+ },
54
+ {
55
+ "id": "es-ib-2025-hotel-4-star-low-season",
56
+ "location_scope": {
57
+ "country_code": "ES",
58
+ "region_code": "ES-IB"
59
+ },
60
+ "valid_from": "2025-05-17",
61
+ "valid_to": null,
62
+ "applies_to": {
63
+ "accommodation_types": ["hotel_4_star", "superior_hotel"]
64
+ },
65
+ "predicates": [
66
+ {
67
+ "kind": "stay.seasonal_window",
68
+ "params": {
69
+ "start_mmdd": "11-01",
70
+ "end_mmdd": "04-30"
71
+ }
72
+ }
73
+ ],
74
+ "calculation": {
75
+ "kind": "generic.per_person_per_night_discount_after_nights",
76
+ "params": {
77
+ "amount": 0.75,
78
+ "discount_start_night": 9,
79
+ "discount_multiplier": 0.5,
80
+ "taxable_guest_age_gte": 16
81
+ },
82
+ "currency": "EUR"
83
+ },
84
+ "source": {
85
+ "source_url": "https://www.boe.es/buscar/act.php?id=BOE-A-2016-4175",
86
+ "reviewed_at": null
87
+ },
88
+ "confidence": "reviewed",
89
+ "notes": "Low season applies a 75% reduction to the EUR 3.00 high-season rate, yielding EUR 0.75 before the ninth-day discount."
90
+ },
91
+ {
92
+ "id": "es-ib-2025-tourist-home-high-season",
93
+ "location_scope": {
94
+ "country_code": "ES",
95
+ "region_code": "ES-IB"
96
+ },
97
+ "valid_from": "2025-05-17",
98
+ "valid_to": null,
99
+ "applies_to": {
100
+ "accommodation_types": ["tourist_home", "tourist_apartment", "vacation_rental"]
101
+ },
102
+ "predicates": [
103
+ {
104
+ "kind": "stay.seasonal_window",
105
+ "params": {
106
+ "start_mmdd": "05-01",
107
+ "end_mmdd": "10-31"
108
+ }
109
+ }
110
+ ],
111
+ "calculation": {
112
+ "kind": "generic.per_person_per_night_discount_after_nights",
113
+ "params": {
114
+ "amount": 2.0,
115
+ "discount_start_night": 9,
116
+ "discount_multiplier": 0.5,
117
+ "taxable_guest_age_gte": 16
118
+ },
119
+ "currency": "EUR"
120
+ },
121
+ "source": {
122
+ "source_url": "https://www.boe.es/buscar/act.php?id=BOE-A-2016-4175",
123
+ "reviewed_at": null
124
+ },
125
+ "confidence": "reviewed",
126
+ "notes": "Balearic Islands high-season rate: EUR 2.00 for tourist homes, holiday rentals, and tourist apartments."
127
+ },
128
+ {
129
+ "id": "es-ib-2025-tourist-home-low-season",
130
+ "location_scope": {
131
+ "country_code": "ES",
132
+ "region_code": "ES-IB"
133
+ },
134
+ "valid_from": "2025-05-17",
135
+ "valid_to": null,
136
+ "applies_to": {
137
+ "accommodation_types": ["tourist_home", "tourist_apartment", "vacation_rental"]
138
+ },
139
+ "predicates": [
140
+ {
141
+ "kind": "stay.seasonal_window",
142
+ "params": {
143
+ "start_mmdd": "11-01",
144
+ "end_mmdd": "04-30"
145
+ }
146
+ }
147
+ ],
148
+ "calculation": {
149
+ "kind": "generic.per_person_per_night_discount_after_nights",
150
+ "params": {
151
+ "amount": 0.5,
152
+ "discount_start_night": 9,
153
+ "discount_multiplier": 0.5,
154
+ "taxable_guest_age_gte": 16
155
+ },
156
+ "currency": "EUR"
157
+ },
158
+ "source": {
159
+ "source_url": "https://www.boe.es/buscar/act.php?id=BOE-A-2016-4175",
160
+ "reviewed_at": null
161
+ },
162
+ "confidence": "reviewed",
163
+ "notes": "Low season applies a 75% reduction to the EUR 2.00 high-season rate, yielding EUR 0.50 before the ninth-day discount."
164
+ }
165
+ ]
166
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "id": "es-balearic-palma-hotel-4-star-high-season-long-stay",
3
+ "description": "Balearic high-season stays charge the first eight nights in full and reduce nights 9+ by 50%; guests under 16 remain exempt.",
4
+ "rule_set_path": "../2025-05-17.json",
5
+ "booking_input": {
6
+ "stay_date": "2026-07-10",
7
+ "nights": 10,
8
+ "adults": 2,
9
+ "children": 1,
10
+ "guests": [
11
+ { "age": 40, "role": "guest" },
12
+ { "age": 34, "role": "guest" },
13
+ { "age": 14, "role": "guest" }
14
+ ],
15
+ "property_location": {
16
+ "country_code": "ES",
17
+ "region_code": "ES-IB",
18
+ "locality_kind": "municipality",
19
+ "locality_name": "Palma"
20
+ },
21
+ "operator": {
22
+ "legal_country_code": "NL",
23
+ "legal_name": "Canal Stays BV"
24
+ },
25
+ "accommodation_type": "hotel_4_star",
26
+ "subtotal": 2200
27
+ },
28
+ "expected": {
29
+ "total_tax": 54.0,
30
+ "matched_rule_ids": ["es-ib-2025-hotel-4-star-high-season"]
31
+ }
32
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "id": "es-balearic-tourist-home-low-season",
3
+ "description": "Balearic low-season tourist-home stays apply the 75% seasonal reduction to the base per-person nightly rate.",
4
+ "rule_set_path": "../2025-05-17.json",
5
+ "booking_input": {
6
+ "stay_date": "2026-11-15",
7
+ "nights": 3,
8
+ "adults": 2,
9
+ "children": 0,
10
+ "guests": [
11
+ { "age": 31, "role": "guest" },
12
+ { "age": 29, "role": "guest" }
13
+ ],
14
+ "property_location": {
15
+ "country_code": "ES",
16
+ "region_code": "ES-IB",
17
+ "locality_kind": "municipality",
18
+ "locality_name": "Sant Antoni de Portmany"
19
+ },
20
+ "accommodation_type": "tourist_home",
21
+ "subtotal": 700
22
+ },
23
+ "expected": {
24
+ "total_tax": 3.0,
25
+ "matched_rule_ids": ["es-ib-2025-tourist-home-low-season"]
26
+ }
27
+ }
@@ -27,6 +27,15 @@ module TaxConformanceKit
27
27
  })
28
28
  end
29
29
 
30
+ def evaluate_resolved(booking_input:, fixture_root: nil, domain: nil, kind_registry: nil)
31
+ run_json("runtime-resolve-evaluate", {
32
+ fixture_root: fixture_root,
33
+ domain: domain,
34
+ booking_input: booking_input,
35
+ kind_registry: kind_registry
36
+ })
37
+ end
38
+
30
39
  def evaluate_assessment(ruleset:, assessment_input:, kind_registry: nil)
31
40
  run_json("runtime-evaluate-assessment", {
32
41
  ruleset: ruleset,
@@ -35,6 +44,15 @@ module TaxConformanceKit
35
44
  })
36
45
  end
37
46
 
47
+ def evaluate_resolved_assessment(assessment_input:, fixture_root: nil, domain: nil, kind_registry: nil)
48
+ run_json("runtime-resolve-evaluate-assessment", {
49
+ fixture_root: fixture_root,
50
+ domain: domain,
51
+ assessment_input: assessment_input,
52
+ kind_registry: kind_registry
53
+ })
54
+ end
55
+
38
56
  private
39
57
 
40
58
  def normalize_command(command)
@@ -1,3 +1,3 @@
1
1
  module TaxConformanceKit
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,24 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tax_conformance_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
- - Urban Heroes
7
+ - ramones
8
8
  bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: Ruby adapter for runtime-validate, runtime-evaluate, and runtime-evaluate-assessment.
13
13
  email:
14
- - dev@urbanheroes.dev
14
+ - ramonvansprundel@gmail.com
15
15
  executables: []
16
16
  extensions: []
17
17
  extra_rdoc_files: []
18
18
  files:
19
+ - LICENSE
19
20
  - README.md
20
21
  - bin/taxctl
21
22
  - data/kind-registry.v1.json
23
+ - data/regulation/es/impuesto_estancias_turisticas/catalonia/barcelona_city/2026-04-01.json
24
+ - data/regulation/es/impuesto_estancias_turisticas/catalonia/barcelona_city/conformance/dutch_operator_barcelona_hotel_5_star.json
25
+ - data/regulation/es/impuesto_estancias_turisticas/catalonia/barcelona_city/conformance/tourist_home_age_17_taxed.json
26
+ - data/regulation/es/impuesto_estancias_turisticas/catalonia/rest_of_catalonia/2026-04-01.json
27
+ - data/regulation/es/impuesto_estancias_turisticas/catalonia/rest_of_catalonia/conformance/barcelona_city_excluded.json
28
+ - data/regulation/es/impuesto_estancias_turisticas/catalonia/rest_of_catalonia/conformance/girona_hotel_4_star.json
29
+ - data/regulation/es/impuesto_turismo_sostenible/balearic_islands/2025-05-17.json
30
+ - data/regulation/es/impuesto_turismo_sostenible/balearic_islands/conformance/palma_hotel_4_star_high_season_long_stay.json
31
+ - data/regulation/es/impuesto_turismo_sostenible/balearic_islands/conformance/tourist_home_low_season.json
22
32
  - data/regulation/nl/gemeentelijke_verordening/aa_en_hunze/2024-11-29.json
23
33
  - data/regulation/nl/gemeentelijke_verordening/aa_en_hunze/2025-11-28.json
24
34
  - data/regulation/nl/gemeentelijke_verordening/aalten/2024-12-23.json