File History: src/main/java/com/paymentlink/service/TaxService.java

← View file content

File Content at Commit 9c24ca4

1 package com.paymentlink.service;
2
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5 import org.springframework.beans.factory.annotation.Value;
6 import org.springframework.stereotype.Service;
7 import org.springframework.web.client.RestTemplate;
8
9 import java.util.HashMap;
10 import java.util.Map;
11
12 @Service
13 public class TaxService {
14
15 private static final Logger logger = LoggerFactory.getLogger(TaxService.class);
16
17 @Value("${tax.default.rate:0.08}")
18 private double defaultTaxRate;
19
20 @Value("${tax.api.url:}")
21 private String taxApiUrl;
22
23 @Value("${tax.api.timeout:5000}")
24 private int taxApiTimeout;
25
26 private final Map<String, Double> countryRates = new HashMap<>();
27 private final Map<String, Map<String, Double>> stateRates = new HashMap<>();
28
29 public TaxService() {
30 initializeTaxRates();
31 }
32
33 private void initializeTaxRates() {
34 // Country-specific rates
35 countryRates.put("GB", 0.20); // UK VAT
36 countryRates.put("US", 0.08); // US average
37 countryRates.put("CA", 0.13); // Canada average
38 countryRates.put("AU", 0.10); // Australia GST
39 countryRates.put("DE", 0.19); // Germany VAT
40 countryRates.put("FR", 0.20); // France VAT
41 countryRates.put("IT", 0.22); // Italy VAT
42 countryRates.put("ES", 0.21); // Spain VAT
43 countryRates.put("NL", 0.21); // Netherlands VAT
44 countryRates.put("BE", 0.21); // Belgium VAT
45
46 // US State-specific rates
47 Map<String, Double> usStates = new HashMap<>();
48 usStates.put("CA", 0.1025); // California
49 usStates.put("NY", 0.08); // New York
50 usStates.put("TX", 0.0825); // Texas
51 usStates.put("FL", 0.06); // Florida
52 usStates.put("WA", 0.101); // Washington
53 stateRates.put("US", usStates);
54
55 // Canadian Province-specific rates
56 Map<String, Double> caProvinces = new HashMap<>();
57 caProvinces.put("ON", 0.13); // Ontario HST
58 caProvinces.put("BC", 0.12); // British Columbia
59 caProvinces.put("QC", 0.14975); // Quebec
60 stateRates.put("CA", caProvinces);
61 }
62
63 /**
64 * Calculate tax amount for a subtotal
65 */
66 public long calculateTax(long subtotal, String country, String state) {
67 double rate = getTaxRate(country, state);
68 long taxAmount = Math.round(subtotal * rate);
69 logger.debug("Calculated tax: subtotal={}, country={}, state={}, rate={}, tax={}",
70 subtotal, country, state, rate, taxAmount);
71 return taxAmount;
72 }
73
74 /**
75 * Get tax rate for country/state
76 */
77 public double getTaxRate(String country, String state) {
78 // Try external API first if configured
79 if (taxApiUrl != null && !taxApiUrl.isEmpty()) {
80 try {
81 Double apiRate = fetchTaxRateFromApi(country, state);
82 if (apiRate != null) {
83 return apiRate;
84 }
85 } catch (Exception e) {
86 logger.warn("Failed to fetch tax rate from API, using local rates", e);
87 }
88 }
89
90 // Try state-specific rate
91 if (state != null && !state.isEmpty() && stateRates.containsKey(country)) {
92 Map<String, Double> states = stateRates.get(country);
93 if (states.containsKey(state)) {
94 return states.get(state);
95 }
96 }
97
98 // Try country rate
99 if (country != null && countryRates.containsKey(country)) {
100 return countryRates.get(country);
101 }
102
103 // Return default
104 return defaultTaxRate;
105 }
106
107 /**
108 * Fetch tax rate from external API
109 */
110 private Double fetchTaxRateFromApi(String country, String state) {
111 try {
112 RestTemplate restTemplate = new RestTemplate();
113 String url = taxApiUrl + "?country=" + country + "&state=" + (state != null ? state : "");
114
115 @SuppressWarnings("unchecked")
116 Map<String, Object> response = restTemplate.getForObject(url, Map.class);
117
118 if (response != null) {
119 // Try "taxRate" field
120 if (response.containsKey("taxRate")) {
121 return ((Number) response.get("taxRate")).doubleValue();
122 }
123 // Try "rate" field
124 if (response.containsKey("rate")) {
125 return ((Number) response.get("rate")).doubleValue();
126 }
127 }
128 } catch (Exception e) {
129 logger.error("Error fetching tax rate from API", e);
130 }
131 return null;
132 }
133
134 /**
135 * Get all supported countries
136 */
137 public Map<String, String> getSupportedCountries() {
138 Map<String, String> countries = new HashMap<>();
139 countries.put("US", "United States");
140 countries.put("CA", "Canada");
141 countries.put("GB", "United Kingdom");
142 countries.put("AU", "Australia");
143 countries.put("DE", "Germany");
144 countries.put("FR", "France");
145 countries.put("IT", "Italy");
146 countries.put("ES", "Spain");
147 countries.put("NL", "Netherlands");
148 countries.put("BE", "Belgium");
149 return countries;
150 }
151 }
152
153

Commits

Commit Author Date Message File SHA Actions
f0438c2 <f69e50@finnacloud.com> 1766443042 +0300 12/22/2025, 10:37:22 PM increment once more 2543040 View
188fc92 <f69e50@finnacloud.com> 1766442998 +0300 12/22/2025, 10:36:38 PM increment 2543040 View
4617f76 <f69e50@finnacloud.com> 1766442953 +0300 12/22/2025, 10:35:53 PM rename branch from main to master oops 2543040 View
e6d1548 <f69e50@finnacloud.com> 1766442769 +0300 12/22/2025, 10:32:49 PM add initial test workflow file 2543040 View
9c24ca4 <f69e50@finnacloud.com> 1766442705 +0300 12/22/2025, 10:31:45 PM add CI configuration and test script for Jenkins build 2543040 Hide
690c1f6 <f69e50@finnacloud.com> 1766368110 +0300 12/22/2025, 1:48:30 AM initialize backend structure with controllers, DTOs, and configuration files 2543040 View