diff --git a/constants.py b/constants.py index 464debb..842965a 100644 --- a/constants.py +++ b/constants.py @@ -28,25 +28,25 @@ (900, 56.13), ], "overige": [ # For EnergySource.OVERIGE - (500, 20.00), - (600, 27.50), - (700, 35.00), - (800, 45.00), - (900, 60.00), + (500, 86.25), + (600, 103.39), + (700, 120.54), + (800, 136.65), + (900, 150.36), ], "diesel": [ # For EnergySource.DIESEL - (500, 22.50), - (600, 30.00), - (700, 37.50), - (800, 47.50), - (900, 62.50), + (500, 73.75), + (600, 87.02), + (700, 100.51), + (800, 114.25), + (900, 133.69), ], } EXCESS_RATES: Dict[str, float] = { "benzine": 15.09, - "overige": 16.50, - "diesel": 18.00, + "overige": 15.92, + "diesel": 14.48, "opcenten": 11.68, } diff --git a/taxes.py b/taxes.py index 4f26c49..bce5bbf 100644 --- a/taxes.py +++ b/taxes.py @@ -23,33 +23,13 @@ def calc_multiplier(weight: int, cut_off: int = 900, step: int = 100) -> int: return round((weight - cut_off) // step) return 0 - -def vehicle_tax(weight: int) -> float: - """Calculate base tax for weight class - source: https://wetten.overheid.nl/jci1.3:c:BWBR0006324&hoofdstuk=IV&afdeling=2&artikel=23&z=2023-01-01&g=2023-01-01 - """ - if weight <= 500: - return 18.75 - elif weight <= 600: - return 25.44 - elif weight <= 700: - return 32.33 - elif weight <= 800: - return 42.20 - # From here excess weight is calculated per 100kg - elif weight >= 900 and weight < 3300: - return 56.13 + (15.09 * calc_multiplier(weight)) - elif weight >= 3300: - return 424.29 + (10.48 * calc_multiplier(weight, cut_off=3300)) - - def calc_fuel_tax(energy_source: EnergySource, weight: int) -> float: """Calculate extra fuel tax based on energy source.""" if energy_source == EnergySource.DIESEL: return calculate_base_tax(weight, energy_source="diesel") elif energy_source == EnergySource.LPG_G3 and weight > 800: - return round(16.64 + (16.64 * (calc_multiplier(weight, cut_off=800) - 1))) - elif energy_source == EnergySource.OVERIGE: + return round(16.64 * calc_multiplier(weight, cut_off=800)) + elif energy_source in [EnergySource.LPG, EnergySource.OVERIGE]: return calculate_base_tax(weight, energy_source="overige") return 0.0 @@ -59,6 +39,7 @@ def calculate_base_tax( ) -> float: """ Generalized base tax calculator based on weight and energy source. + source: https://wetten.overheid.nl/jci1.3:c:BWBR0006324&hoofdstuk=IV&afdeling=2&artikel=23&z=2023-01-01&g=2023-01-01 Args: weight (int): Rounded weight of the vehicle. @@ -71,15 +52,17 @@ def calculate_base_tax( tax_brackets = WEIGHT_TAX_BRACKETS[energy_source] excess_rate = EXCESS_RATES[energy_source] - for max_weight, rate in tax_brackets: - if weight <= max_weight: - return rate - # Apply excess rate for weights above the cutoff if weight >= cutoff: multiplier = calc_multiplier(weight, cutoff) base_rate = tax_brackets[-1][1] # Use the last bracket's rate as the base return base_rate + (multiplier * excess_rate) + # TODO won't work for BENZINE > 3300 + # return 424.29 + (10.48 * calc_multiplier(weight, cut_off=3300)) + else: + for max_weight, rate in tax_brackets: + if weight <= max_weight: + return rate return 0.0 @@ -144,13 +127,15 @@ def calculate_tax( else: base_tax *= 1.0 # 100% of base tax + # Fuel-specific tax fuel_tax = calc_fuel_tax(energy_source, rounded_weight) base_tax += fuel_tax # Apply inflation adjustment if applicable if year in INFLATION: - base_tax *= 1 + INFLATION[year] + base_tax *= (1 + INFLATION[year]) + # Provincial opcenten tax opcenten = calc_opcenten(rounded_weight, province, year) diff --git a/tests/test_mrb.py b/tests/test_mrb.py index 7c7cd6a..6c6b237 100644 --- a/tests/test_mrb.py +++ b/tests/test_mrb.py @@ -37,7 +37,22 @@ def test_calc_opcenten(self): with self.assertRaises(KeyError): calc_opcenten(weight, "Non-existent", self.YEAR) - def test_calculate_tax(self): + def test_calculate_tax_benzine_without_excess_weight(self): + # Test cases for calculate_tax + weight = 720 + province = "noord-holland" + energy_source = EnergySource.BENZINE + result = 47 + + self.assertEqual( + calculate_tax(energy_source, weight, province, self.YEAR), result + ) + + # Edge case: Electric car before 2025 + energy_source = EnergySource.ELEKTRICITEIT + self.assertEqual(calculate_tax(energy_source, weight, province, self.YEAR), 0) + + def test_calculate_tax_with_excess_weight(self): # Test cases for calculate_tax weight = 1200 province = "noord-holland" @@ -69,7 +84,22 @@ def test_calc_opcenten(self): with self.assertRaises(KeyError): calc_opcenten(weight, "Non-existent", self.YEAR) - def test_calculate_tax(self): + def test_calculate_tax_benzine_without_excess_weight(self): + # Test cases for calculate_tax + weight = 720 + province = "noord-holland" + energy_source = EnergySource.BENZINE + result = 51 + + self.assertEqual( + calculate_tax(energy_source, weight, province, self.YEAR), result + ) + + # Edge case: Electric car before 2025 + energy_source = EnergySource.ELEKTRICITEIT + self.assertEqual(calculate_tax(energy_source, weight, province, self.YEAR), 0) + + def test_calculate_tax_benzine_with_excess_weight(self): # Test cases for calculate_tax weight = 1200 province = "noord-holland" @@ -106,5 +136,49 @@ def test_calculate_tax_lpg_g3_without_fuel_tax(self): calculate_tax(energy_source, weight, province, self.YEAR), result ) + def test_calculate_tax_lpg(self): + # Test cases for calculate_tax + weight = 720 + province = "noord-holland" + energy_source = EnergySource.LPG + result = 183 + + self.assertEqual( + calculate_tax(energy_source, weight, province, self.YEAR), result + ) + + def test_calculate_tax_lpg_with_excess_weight(self): + # Test cases for calculate_tax + weight = 1200 + province = "noord-holland" + energy_source = EnergySource.LPG + result = 382 + + self.assertEqual( + calculate_tax(energy_source, weight, province, self.YEAR), result + ) + + def test_calculate_tax_other_fuel(self): + # Test cases for calculate_tax + weight = 720 + province = "noord-holland" + energy_source = EnergySource.OVERIGE + result = 183 + + self.assertEqual( + calculate_tax(energy_source, weight, province, self.YEAR), result + ) + + def test_calculate_tax_other_with_excess_weight(self): + # Test cases for calculate_tax + weight = 1200 + province = "noord-holland" + energy_source = EnergySource.OVERIGE + result = 382 + + self.assertEqual( + calculate_tax(energy_source, weight, province, self.YEAR), result + ) + if __name__ == "__main__": unittest.main()