Merge branch 'development' into test

This commit is contained in:
“VeLiTi”
2026-02-05 16:15:40 +01:00
12 changed files with 408 additions and 165 deletions

View File

@@ -70,6 +70,11 @@ if ($stmt->rowCount() == 1) {
$stmt_service->execute([$user_data['service'], $user_data['id']]);
}
$user_data['refreshkey'] = bin2hex(random_bytes(25));
$sql_refreshkey = 'UPDATE users SET refreshkey = ? WHERE id = ?';
$stmt_refreshkey = $pdo->prepare($sql_refreshkey);
$stmt_refreshkey->execute([$user_data['refreshkey'], $user_data['id']]);
$token = createCommunicationToken($user_data['userkey']);
//RETURN JWT AND CLIENTSECRET
@@ -78,6 +83,7 @@ if ($stmt->rowCount() == 1) {
'token' => $token,
'token_valid' => date('Y-m-d H:i:s',time() + 1800),
'userkey' => $user_data['userkey'],
'refreshkey' => $user_data['refreshkey'],
'language' => $user_data['language']
);

View File

@@ -26,7 +26,7 @@ if(isset($get_content) && $get_content!=''){
foreach ($requests as $y){
$v = explode("=", $y);
//INCLUDE VARIABLES IN ARRAY
$criterias[$v[0]] = $v[1];
$criterias[$v[0]] = $v[1] ?? '';
if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='list' || $v[0] =='history'|| $v[0] =='success_msg'){
//do nothing

View File

@@ -0,0 +1,93 @@
<?php
defined($security_key) or exit;
//------------------------------------------
// User Role Assignments
//------------------------------------------
//Connect to DB
$pdo = dbConnect($dbname);
//------------------------------------------
//NEW ARRAY
//------------------------------------------
$criterias = [];
$user_permissions = [];
//------------------------------------------
//Check for $_GET variables and build up clause
//------------------------------------------
if(isset($get_content) && $get_content!=''){
//GET VARIABLES FROM URL
$requests = explode("&", $get_content);
//Check for keys and values
foreach ($requests as $y){
$v = explode("=", $y);
//INCLUDE VARIABLES IN ARRAY
$criterias[$v[0]] = $v[1];
}
}
$token_refresh = $criterias['refreshkey'] ?? null;
if (!$token_refresh) {
http_response_code(400);
exit(json_encode(['error_code' => 'API_INPUT_1','error' => 'refreshkey is required']));
}
//GET USER_DATA
$stmt = $pdo->prepare('SELECT * FROM users WHERE refreshkey = ?');
$stmt->execute([$token_refresh]);
if ($stmt->rowCount() == 1) {
//Get results
$user_data = $stmt->fetch();
//Check valid userkey
$valid_key = strtotime('+30 minutes',strtotime($user_data['lastlogin']));
$valid = ($valid_key <= time())?0:1;
//REFRESH USERKEY
if ($user_data['userkey'] != '' && $valid == 0){
$user_data['userkey'] = bin2hex(random_bytes(25));
$sql_userkey = 'UPDATE users SET userkey = ? WHERE id = ?';
$stmt_userkey = $pdo->prepare($sql_userkey);
$stmt_userkey->execute([$user_data['userkey'], $user_data['id']]);
}
//REFRESH USERKEY
if ($user_data['service'] != '' && $valid == 0){
$user_data['service'] = bin2hex(random_bytes(25));
$sql_service = 'UPDATE users SET service = ? WHERE id = ?';
$stmt_service = $pdo->prepare($sql_service);
$stmt_service->execute([$user_data['service'], $user_data['id']]);
}
//Refresh REFRESHKEY
$user_data['refreshkey'] = bin2hex(random_bytes(25));
$sql_refreshkey = 'UPDATE users SET refreshkey = ? WHERE id = ?';
$stmt_refreshkey = $pdo->prepare($sql_refreshkey);
$stmt_refreshkey->execute([$user_data['refreshkey'], $user_data['id']]);
$token = createCommunicationToken($user_data['userkey']);
//RETURN JWT AND CLIENTSECRET
$user = array(
'clientID' => $user_data['username'],
'token' => $token,
'token_valid' => date('Y-m-d H:i:s',time() + 1800),
'userkey' => $user_data['userkey'],
'refreshkey' => $user_data['refreshkey'],
'language' => $user_data['language']
);
//+++++++++++++++++++++++++++++++++++++++++++
//Return as JSON
//+++++++++++++++++++++++++++++++++++++++++++
echo json_encode($user, JSON_UNESCAPED_UNICODE);
}
else {
http_response_code(404);
exit(json_encode(['error_code' => 'API_NOT_FOUND','error' => 'Refresh not succesfull']));
}
?>

View File

@@ -4,6 +4,8 @@ TRUNCATE TABLE `role_access_permissions`;
TRUNCATE TABLE `user_roles`;
TRUNCATE TABLE `access_elements`;
ALTER TABLE taxes ADD COLUMN eu TINYINT(1) DEFAULT 0;
INSERT INTO access_elements (access_name,access_path,description,is_active,created,createdby,updated,updatedby,access_group) VALUES
('Access Element','access_element','Auto-scanned: access_element',1,'2026-01-18 18:49:49','0','2026-01-18 18:49:49',NULL,'Views'),
('Access Element Manage','access_element_manage','Auto-scanned: access_element_manage',1,'2026-01-18 18:49:49','0','2026-01-18 18:49:49',NULL,'Views'),
@@ -919,5 +921,16 @@ UPDATE equipment
SET warranty_date = DATE_ADD(warranty_date, INTERVAL 1 YEAR)
WHERE warranty_date IS NOT NULL;
alter table users add refreshkey varchar(255);
UPDATE taxes SET eu = 1 WHERE country IN (
'Austria', 'Belgium', 'Bulgaria', 'Croatia', 'Cyprus', 'Czech Republic',
'Denmark', 'Estonia', 'Finland', 'France', 'Germany', 'Greece',
'Hungary', 'Ireland', 'Italy', 'Latvia', 'Lithuania', 'Luxembourg',
'Malta', 'Netherlands', 'Poland', 'Portugal', 'Romania', 'Slovakia',
'Slovenia', 'Spain', 'Sweden'
);
UPDATE taxes SET rate = 0.00 WHERE eu = 0 OR eu IS NULL;
SET FOREIGN_KEY_CHECKS=1;

View File

@@ -1725,6 +1725,7 @@ function getProfile($profile, $permission){
// Always allowed collections: [collection => allowed_actions_string]
$always_allowed = [
'com_log' => 'CRU',
'token_refresh' => 'R',
'application' => 'CRU',
'user_roles' => 'R',
'user_role_assignments' => 'R',
@@ -5626,12 +5627,12 @@ function generateSoftwareInvoice($invoice_data, $order_id, $language = 'US') {
// Extract customer data
$customer = $invoice_data['customer'] ?? [];
$customer_email = $customer['email'] ?? $invoice_data['payer_email'] ?? '';
$customer_name = trim(($customer['first_name'] ?? '') . ' ' . ($customer['last_name'] ?? ''));
$customer_address = $customer['address_street'] ?? '';
$customer_city = $customer['address_city'] ?? '';
$customer_state = $customer['address_state'] ?? '';
$customer_zip = $customer['address_zip'] ?? '';
$customer_country = $customer['address_country'] ?? '';
$customer_name = $customer['name'] ?? trim(($customer['first_name'] ?? '') . ' ' . ($customer['last_name'] ?? ''));
$customer_address = $customer['street'] ?? $customer['address_street'] ?? '';
$customer_city = $customer['city'] ?? $customer['address_city'] ?? '';
$customer_state = $customer['state'] ?? $customer['address_state'] ?? '';
$customer_zip = $customer['zip'] ?? $customer['address_zip'] ?? '';
$customer_country = $customer['country'] ?? $customer['address_country'] ?? '';
// Extract transaction data
$pricing = $invoice_data['pricing'] ?? [];
@@ -5743,6 +5744,54 @@ function generateSoftwareInvoice($invoice_data, $order_id, $language = 'US') {
}
}
// Calculate VAT note based on country and VAT number
$vat_note = '';
$customer_vat_number = $customer['vat_number'] ?? '';
// Load countries array
include dirname(__FILE__,2).'/settings/countries.php';
debuglog("Customer Country: " . ($customer_country ?? 'NULL'));
debuglog("Customer VAT: " . ($customer_vat_number ?? 'NULL'));
if (!empty($customer_country) && isset($countries)) {
// Find country data
$country_data = null;
foreach ($countries as $country_info) {
if ($country_info['country'] === $customer_country) {
$country_data = $country_info;
break;
}
}
if ($country_data) {
$is_eu = $country_data['eu'] === 1;
$is_netherlands = $customer_country === 'Netherlands';
if ($is_netherlands) {
// Netherlands: no special note needed
$vat_note = '';
} elseif ($is_eu) {
if (!empty($customer_vat_number)) {
// EU with VAT number: reverse charge
$vat_note = 'Reverse charge VAT';
} else {
// EU without VAT number: local VAT
$vat_note = 'Local VAT';
}
} else {
// Non-EU: out of scope
$vat_note = 'Out of scope of EU VAT. Buyer is responsible for local taxes and duties';
}
debuglog("VAT Note set to: " . ($vat_note ?: 'EMPTY'));
} else {
debuglog("Country NOT found in array: " . $customer_country);
}
} else {
debuglog("Empty customer_country or countries not loaded");
}
// Build HTML for PDF and EMAIL
include dirname(__FILE__,2).'/assets/mail/email_template_invoice.php';
include dirname(__FILE__,2).'/assets/mail/pdf_template_invoice.php';
@@ -5815,7 +5864,8 @@ function generateCountriesFile($token){
foreach($taxes as $tax){
$countries[$tax['id']] = [
'country' => $tax['country'] ?? '',
'taxes' => $tax['rate'] ?? 0
'taxes' => $tax['rate'] ?? 0,
'eu' => $tax['eu'] ?? 0
];
}
@@ -5825,7 +5875,7 @@ function generateCountriesFile($token){
$fileContent .= "// Generated on: " . date('Y-m-d H:i:s') . "\n\n";
$fileContent .= "\$countries = [\n";
foreach($countries as $id => $data){
$fileContent .= " " . $id . " => ['country' => '" . addslashes($data['country']) . "', 'taxes' => " . $data['taxes'] . "],\n";
$fileContent .= " " . $id . " => ['country' => '" . addslashes($data['country']) . "', 'taxes' => " . $data['taxes'] . ",'eu' => " . $data['eu'] . "],\n";
}
$fileContent .= "];\n";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 88 KiB

View File

@@ -1,5 +1,6 @@
<?php
$payment_method = 'payment_method_'.$invoice_data['header']['payment_method'];
$invoice_identifcation_number = date('ymd', strtotime($invoice_date)) . '-' . $invoice_data['header']['id'];
$message = '
<!DOCTYPE html>
@@ -50,7 +51,7 @@ $message = '
</tr>
<tr>
<td style="padding: 3px 0;"><strong>Invoice Number:</strong></td>
<td style="padding: 3px 0;">' . htmlspecialchars($order_id) . '</td>
<td style="padding: 3px 0;">' . htmlspecialchars($invoice_identifcation_number) . '</td>
</tr>
<tr>
<td style="padding: 3px 0;"><strong>Your Vat Number:</strong></td>
@@ -121,14 +122,24 @@ $message .= '</tbody>
</tr>';
if ($tax_amount > 0) {
$tax_percentage = ($subtotal > 0) ? round(($tax_amount / $subtotal) * 100, 2) : 0;
$vat_label = htmlspecialchars($lbl_tax) . ' (' . $tax_percentage . '%)';
if (!empty($vat_note)) {
$vat_label .= ' <small style="font-size: 11px; color: #888;">(' . htmlspecialchars($vat_note) . ')</small>';
}
$message .= '<tr>
<td style="text-align: left; padding: 5px 0;">' . htmlspecialchars($lbl_tax) . '</td>
<td style="text-align: left; padding: 5px 0;">' . $vat_label . '</td>
<td style="text-align: right; padding: 5px 0;">€ ' . number_format($tax_amount, 2) . '</td>
</tr>';
} else {
$vat_label = 'VAT';
if (!empty($vat_note)) {
$vat_label .= ' <small style="font-size: 11px; color: #888;">(' . htmlspecialchars($vat_note) . ')</small>';
}
$vat_amount_display = !empty($vat_note) ? '€ 0.00' : 'included';
$message .= '<tr>
<td style="text-align: left; padding: 5px 0;">VAT</td>
<td style="text-align: right; padding: 5px 0;">included</td>
<td style="text-align: left; padding: 5px 0;">' . $vat_label . '</td>
<td style="text-align: right; padding: 5px 0;">' . $vat_amount_display . '</td>
</tr>';
}

View File

@@ -1,5 +1,6 @@
<?php
$payment_method = 'payment_method_'.$invoice_data['header']['payment_method'];
$invoice_identifcation_number = date('ymd', strtotime($invoice_date)) . '-' . $invoice_data['header']['id'];
$pdf = '<!DOCTYPE html>
<html lang="' . strtolower($language) . '">
@@ -232,7 +233,7 @@ $pdf = '<!DOCTYPE html>
</div>
<div class="detail-row">
<div class="detail-label">Invoice Number</div>
<div class="detail-value">: ' . htmlspecialchars($order_id) . '</div>
<div class="detail-value">: ' . htmlspecialchars($invoice_identifcation_number) . '</div>
</div>
<div class="detail-row">
<div class="detail-label">Your Vat Number</div>
@@ -298,14 +299,23 @@ $pdf .= '</tbody>
if ($tax_amount > 0) {
$tax_percentage = ($subtotal > 0) ? round(($tax_amount / $subtotal) * 100, 2) : 0;
$vat_label = htmlspecialchars($lbl_tax) . ' (' . $tax_percentage . '%)';
if (!empty($vat_note)) {
$vat_label .= ' <small style="font-size: 9px; color: #666;">(' . htmlspecialchars($vat_note) . ')</small>';
}
$pdf .= '<div class="total-row">
<div class="total-label">' . htmlspecialchars($lbl_tax) . ' (' . $tax_percentage . '%)</div>
<div class="total-label">' . $vat_label . '</div>
<div class="total-amount">€ ' . number_format($tax_amount, 2) . '</div>
</div>';
} else {
$vat_label = 'VAT';
if (!empty($vat_note)) {
$vat_label .= ' <small style="font-size: 9px; color: #666;">(' . htmlspecialchars($vat_note) . ')</small>';
}
$vat_amount_display = !empty($vat_note) ? '€ 0.00' : 'included';
$pdf .= '<div class="total-row">
<div class="total-label">VAT</div>
<div class="total-amount">included</div>
<div class="total-label">' . $vat_label . '</div>
<div class="total-amount">' . $vat_amount_display . '</div>
</div>';
}

View File

@@ -1485,12 +1485,35 @@ function showPaymentModal(option) {
// Function to calculate and update tax
function updateTaxDisplay() {
const selectedCountry = document.getElementById("paymentCountry").value;
const vatNumber = document.getElementById("paymentVatNumber").value.trim();
let taxRate = 0;
let vatNote = '';
if (selectedCountry && typeof COUNTRIES !== 'undefined' && COUNTRIES) {
const countryData = Object.values(COUNTRIES).find(c => c.country === selectedCountry);
if (countryData) {
taxRate = parseFloat(countryData.taxes) || 0;
const isEU = countryData.eu === 1;
const isNetherlands = selectedCountry === 'Netherlands';
const countryTaxRate = parseFloat(countryData.taxes) || 0;
if (isNetherlands) {
// Netherlands: always take the tax percentage
taxRate = countryTaxRate;
} else if (isEU) {
if (vatNumber) {
// EU with VAT number: 0% VAT, reverse charge
taxRate = 0;
vatNote = 'Reverse charge VAT';
} else {
// EU without VAT number: use country VAT
taxRate = countryTaxRate;
vatNote = 'Local VAT';
}
} else {
// Non-EU: use country tax percentage (usually 0)
taxRate = countryTaxRate;
vatNote = 'Out of scope of EU VAT. Buyer is responsible for local taxes and duties';
}
}
}
@@ -1503,13 +1526,13 @@ function showPaymentModal(option) {
if (taxRate > 0) {
taxDisplay.innerHTML = `
<span>VAT (${taxRate}%):</span>
<span>VAT (${taxRate}%)${vatNote ? ' <small style="font-size: 9px; color: #888;">(' + vatNote + ')</small>' : ''}:</span>
<span style="font-weight: 600;">${currency} ${taxAmount.toFixed(2)}</span>
`;
} else {
taxDisplay.innerHTML = `
<span>VAT:</span>
<span style="font-weight: 600;">-</span>
<span>VAT${vatNote ? ' <small style="font-size: 9px; color: #888;">(' + vatNote + ')</small>' : ''}:</span>
<span style="font-weight: 600;">${vatNote ? '0%' : '-'}</span>
`;
}
@@ -1541,8 +1564,9 @@ function showPaymentModal(option) {
}
}
// Add event listener to country select to update tax
// Add event listeners to country select and VAT number to update tax
document.getElementById("paymentCountry").addEventListener('change', updateTaxDisplay);
document.getElementById("paymentVatNumber").addEventListener('input', updateTaxDisplay);
// Close modal on cancel
document.getElementById("cancelPayment").onclick = () => {

View File

@@ -41,6 +41,42 @@ include dirname(__FILE__).'/assets/functions.php';
include dirname(__FILE__).'/settings/settings_redirector.php';
include_once dirname(__FILE__).'/settings/countries.php';
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//TOKEN REFRESH LOGIC
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Token refresh buffer: refresh token 5 minutes (300 seconds) before expiry
$token_refresh_buffer = 300;
// Check if API token exists and is still valid
if (!isset($_SESSION['authorization']['userkey']) ||
!isset($_SESSION['authorization']['token_valid']) ||
time() >= (strtotime($_SESSION['authorization']['token_valid']) - $token_refresh_buffer)) {
// Token missing, expired, or about to expire - get new token
if (isset($_SESSION['authorization']['refreshkey'])) {
$api_url = '/v2/token_refresh/refreshkey='.$_SESSION['authorization']['refreshkey'];
$responses = ioServer($api_url, '');
//Decode Payload
if (!empty($responses)){$responses = json_decode($responses,true);}else{$responses = null;}
if (isset($responses['userkey']) && isset($responses['token_valid'])) {
// Update session with complete response (same as login.php)
$_SESSION['authorization'] = $responses;
} else {
// Token refresh failed - redirect to login
session_destroy();
header('location: login.php?error=session_expired');
die();
}
} else {
// No refreshkey available - redirect to login
session_destroy();
header('location: login.php?error=session_expired');
die();
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//GET USER PERMISSION ASSIGNED
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

View File

@@ -1,148 +1,148 @@
<?php
// Auto-generated countries file from taxes API
// Generated on: 2026-01-16 14:21:38
// Generated on: 2026-02-05 14:44:35
$countries = [
1 => ['country' => 'Austria', 'taxes' => 20.00],
2 => ['country' => 'Belgium', 'taxes' => 21.00],
3 => ['country' => 'Bulgaria', 'taxes' => 20.00],
4 => ['country' => 'Croatia', 'taxes' => 25.00],
5 => ['country' => 'Cyprus', 'taxes' => 19.00],
6 => ['country' => 'Czech Republic', 'taxes' => 21.00],
7 => ['country' => 'Denmark', 'taxes' => 25.00],
8 => ['country' => 'Estonia', 'taxes' => 24.00],
9 => ['country' => 'Finland', 'taxes' => 25.50],
10 => ['country' => 'France', 'taxes' => 20.00],
11 => ['country' => 'Germany', 'taxes' => 19.00],
12 => ['country' => 'Greece', 'taxes' => 24.00],
13 => ['country' => 'Hungary', 'taxes' => 27.00],
14 => ['country' => 'Ireland', 'taxes' => 23.00],
15 => ['country' => 'Italy', 'taxes' => 22.00],
16 => ['country' => 'Latvia', 'taxes' => 21.00],
17 => ['country' => 'Lithuania', 'taxes' => 21.00],
18 => ['country' => 'Luxembourg', 'taxes' => 16.00],
19 => ['country' => 'Malta', 'taxes' => 18.00],
20 => ['country' => 'Netherlands', 'taxes' => 21.00],
21 => ['country' => 'Poland', 'taxes' => 23.00],
22 => ['country' => 'Portugal', 'taxes' => 23.00],
23 => ['country' => 'Romania', 'taxes' => 19.00],
24 => ['country' => 'Slovakia', 'taxes' => 23.00],
25 => ['country' => 'Slovenia', 'taxes' => 22.00],
26 => ['country' => 'Spain', 'taxes' => 21.00],
27 => ['country' => 'Sweden', 'taxes' => 25.00],
28 => ['country' => 'United Kingdom', 'taxes' => 20.00],
29 => ['country' => 'Switzerland', 'taxes' => 8.10],
30 => ['country' => 'Norway', 'taxes' => 25.00],
31 => ['country' => 'Iceland', 'taxes' => 24.00],
32 => ['country' => 'Albania', 'taxes' => 20.00],
33 => ['country' => 'Serbia', 'taxes' => 20.00],
34 => ['country' => 'North Macedonia', 'taxes' => 18.00],
35 => ['country' => 'Bosnia and Herzegovina', 'taxes' => 17.00],
36 => ['country' => 'Montenegro', 'taxes' => 21.00],
37 => ['country' => 'Moldova', 'taxes' => 20.00],
38 => ['country' => 'Ukraine', 'taxes' => 20.00],
39 => ['country' => 'Belarus', 'taxes' => 20.00],
40 => ['country' => 'Turkey', 'taxes' => 20.00],
41 => ['country' => 'Andorra', 'taxes' => 4.50],
42 => ['country' => 'Australia', 'taxes' => 10.00],
43 => ['country' => 'New Zealand', 'taxes' => 15.00],
44 => ['country' => 'Japan', 'taxes' => 10.00],
45 => ['country' => 'China', 'taxes' => 13.00],
46 => ['country' => 'India', 'taxes' => 18.00],
47 => ['country' => 'South Korea', 'taxes' => 10.00],
48 => ['country' => 'Singapore', 'taxes' => 9.00],
49 => ['country' => 'Indonesia', 'taxes' => 11.00],
50 => ['country' => 'Thailand', 'taxes' => 7.00],
51 => ['country' => 'Vietnam', 'taxes' => 8.00],
52 => ['country' => 'Philippines', 'taxes' => 12.00],
53 => ['country' => 'Malaysia', 'taxes' => 0.00],
54 => ['country' => 'Taiwan', 'taxes' => 5.00],
55 => ['country' => 'Pakistan', 'taxes' => 18.00],
56 => ['country' => 'Bangladesh', 'taxes' => 15.00],
57 => ['country' => 'Sri Lanka', 'taxes' => 18.00],
58 => ['country' => 'Nepal', 'taxes' => 13.00],
59 => ['country' => 'Cambodia', 'taxes' => 10.00],
60 => ['country' => 'Myanmar', 'taxes' => 5.00],
61 => ['country' => 'Laos', 'taxes' => 10.00],
62 => ['country' => 'Mongolia', 'taxes' => 10.00],
63 => ['country' => 'Kazakhstan', 'taxes' => 12.00],
64 => ['country' => 'Uzbekistan', 'taxes' => 12.00],
65 => ['country' => 'Armenia', 'taxes' => 20.00],
66 => ['country' => 'Georgia', 'taxes' => 18.00],
67 => ['country' => 'Azerbaijan', 'taxes' => 18.00],
68 => ['country' => 'Fiji', 'taxes' => 9.00],
69 => ['country' => 'Papua New Guinea', 'taxes' => 10.00],
70 => ['country' => 'Samoa', 'taxes' => 15.00],
71 => ['country' => 'Tonga', 'taxes' => 15.00],
72 => ['country' => 'Vanuatu', 'taxes' => 15.00],
73 => ['country' => 'Bhutan', 'taxes' => 7.00],
74 => ['country' => 'Saudi Arabia', 'taxes' => 15.00],
75 => ['country' => 'United Arab Emirates', 'taxes' => 5.00],
76 => ['country' => 'Bahrain', 'taxes' => 10.00],
77 => ['country' => 'Kuwait', 'taxes' => 0.00],
78 => ['country' => 'Oman', 'taxes' => 5.00],
79 => ['country' => 'Qatar', 'taxes' => 0.00],
80 => ['country' => 'Israel', 'taxes' => 17.00],
81 => ['country' => 'Jordan', 'taxes' => 16.00],
82 => ['country' => 'Lebanon', 'taxes' => 11.00],
83 => ['country' => 'Egypt', 'taxes' => 14.00],
85 => ['country' => 'South Africa', 'taxes' => 15.00],
86 => ['country' => 'Nigeria', 'taxes' => 7.50],
87 => ['country' => 'Kenya', 'taxes' => 16.00],
88 => ['country' => 'Ghana', 'taxes' => 15.00],
89 => ['country' => 'Morocco', 'taxes' => 20.00],
90 => ['country' => 'Tunisia', 'taxes' => 19.00],
91 => ['country' => 'Algeria', 'taxes' => 19.00],
92 => ['country' => 'Egypt', 'taxes' => 14.00],
93 => ['country' => 'Ethiopia', 'taxes' => 15.00],
94 => ['country' => 'Tanzania', 'taxes' => 18.00],
95 => ['country' => 'Uganda', 'taxes' => 18.00],
96 => ['country' => 'Zimbabwe', 'taxes' => 15.00],
97 => ['country' => 'Zambia', 'taxes' => 16.00],
98 => ['country' => 'Botswana', 'taxes' => 14.00],
99 => ['country' => 'Mauritius', 'taxes' => 15.00],
100 => ['country' => 'Namibia', 'taxes' => 15.00],
101 => ['country' => 'Rwanda', 'taxes' => 18.00],
102 => ['country' => 'Senegal', 'taxes' => 18.00],
103 => ['country' => 'Ivory Coast', 'taxes' => 18.00],
104 => ['country' => 'Cameroon', 'taxes' => 19.25],
105 => ['country' => 'Angola', 'taxes' => 14.00],
106 => ['country' => 'Mozambique', 'taxes' => 16.00],
107 => ['country' => 'Madagascar', 'taxes' => 20.00],
108 => ['country' => 'Mali', 'taxes' => 18.00],
109 => ['country' => 'Burkina Faso', 'taxes' => 18.00],
110 => ['country' => 'Niger', 'taxes' => 19.00],
111 => ['country' => 'Benin', 'taxes' => 18.00],
112 => ['country' => 'Togo', 'taxes' => 18.00],
113 => ['country' => 'Guinea', 'taxes' => 18.00],
114 => ['country' => 'Malawi', 'taxes' => 16.50],
115 => ['country' => 'Gabon', 'taxes' => 18.00],
116 => ['country' => 'Mauritania', 'taxes' => 16.00],
117 => ['country' => 'Lesotho', 'taxes' => 15.00],
118 => ['country' => 'Eswatini', 'taxes' => 15.00],
119 => ['country' => 'Liberia', 'taxes' => 18.00],
120 => ['country' => 'Canada', 'taxes' => 5.00],
121 => ['country' => 'United States', 'taxes' => 10.00],
122 => ['country' => 'Mexico', 'taxes' => 16.00],
123 => ['country' => 'Argentina', 'taxes' => 21.00],
124 => ['country' => 'Brazil', 'taxes' => 17.00],
125 => ['country' => 'Chile', 'taxes' => 19.00],
126 => ['country' => 'Colombia', 'taxes' => 19.00],
127 => ['country' => 'Peru', 'taxes' => 18.00],
128 => ['country' => 'Ecuador', 'taxes' => 15.00],
129 => ['country' => 'Uruguay', 'taxes' => 22.00],
130 => ['country' => 'Paraguay', 'taxes' => 10.00],
131 => ['country' => 'Bolivia', 'taxes' => 13.00],
132 => ['country' => 'Venezuela', 'taxes' => 16.00],
133 => ['country' => 'Costa Rica', 'taxes' => 13.00],
134 => ['country' => 'Panama', 'taxes' => 7.00],
135 => ['country' => 'Guatemala', 'taxes' => 12.00],
136 => ['country' => 'Honduras', 'taxes' => 15.00],
137 => ['country' => 'El Salvador', 'taxes' => 13.00],
138 => ['country' => 'Nicaragua', 'taxes' => 15.00],
139 => ['country' => 'Dominican Republic', 'taxes' => 18.00],
140 => ['country' => 'Jamaica', 'taxes' => 15.00],
141 => ['country' => 'Trinidad and Tobago', 'taxes' => 12.50],
142 => ['country' => 'Barbados', 'taxes' => 17.50],
143 => ['country' => 'Bahamas', 'taxes' => 10.00],
1 => ['country' => 'Austria', 'taxes' => 20.00,'eu' => 1],
2 => ['country' => 'Belgium', 'taxes' => 21.00,'eu' => 1],
3 => ['country' => 'Bulgaria', 'taxes' => 20.00,'eu' => 1],
4 => ['country' => 'Croatia', 'taxes' => 25.00,'eu' => 1],
5 => ['country' => 'Cyprus', 'taxes' => 19.00,'eu' => 1],
6 => ['country' => 'Czech Republic', 'taxes' => 21.00,'eu' => 1],
7 => ['country' => 'Denmark', 'taxes' => 25.00,'eu' => 1],
8 => ['country' => 'Estonia', 'taxes' => 24.00,'eu' => 1],
9 => ['country' => 'Finland', 'taxes' => 25.50,'eu' => 1],
10 => ['country' => 'France', 'taxes' => 20.00,'eu' => 1],
11 => ['country' => 'Germany', 'taxes' => 19.00,'eu' => 1],
12 => ['country' => 'Greece', 'taxes' => 24.00,'eu' => 1],
13 => ['country' => 'Hungary', 'taxes' => 27.00,'eu' => 1],
14 => ['country' => 'Ireland', 'taxes' => 23.00,'eu' => 1],
15 => ['country' => 'Italy', 'taxes' => 22.00,'eu' => 1],
16 => ['country' => 'Latvia', 'taxes' => 21.00,'eu' => 1],
17 => ['country' => 'Lithuania', 'taxes' => 21.00,'eu' => 1],
18 => ['country' => 'Luxembourg', 'taxes' => 16.00,'eu' => 1],
19 => ['country' => 'Malta', 'taxes' => 18.00,'eu' => 1],
20 => ['country' => 'Netherlands', 'taxes' => 21.00,'eu' => 1],
21 => ['country' => 'Poland', 'taxes' => 23.00,'eu' => 1],
22 => ['country' => 'Portugal', 'taxes' => 23.00,'eu' => 1],
23 => ['country' => 'Romania', 'taxes' => 19.00,'eu' => 1],
24 => ['country' => 'Slovakia', 'taxes' => 23.00,'eu' => 1],
25 => ['country' => 'Slovenia', 'taxes' => 22.00,'eu' => 1],
26 => ['country' => 'Spain', 'taxes' => 21.00,'eu' => 1],
27 => ['country' => 'Sweden', 'taxes' => 25.00,'eu' => 1],
28 => ['country' => 'United Kingdom', 'taxes' => 0.00,'eu' => 0],
29 => ['country' => 'Switzerland', 'taxes' => 0.00,'eu' => 0],
30 => ['country' => 'Norway', 'taxes' => 0.00,'eu' => 0],
31 => ['country' => 'Iceland', 'taxes' => 0.00,'eu' => 0],
32 => ['country' => 'Albania', 'taxes' => 0.00,'eu' => 0],
33 => ['country' => 'Serbia', 'taxes' => 0.00,'eu' => 0],
34 => ['country' => 'North Macedonia', 'taxes' => 0.00,'eu' => 0],
35 => ['country' => 'Bosnia and Herzegovina', 'taxes' => 0.00,'eu' => 0],
36 => ['country' => 'Montenegro', 'taxes' => 0.00,'eu' => 0],
37 => ['country' => 'Moldova', 'taxes' => 0.00,'eu' => 0],
38 => ['country' => 'Ukraine', 'taxes' => 0.00,'eu' => 0],
39 => ['country' => 'Belarus', 'taxes' => 0.00,'eu' => 0],
40 => ['country' => 'Turkey', 'taxes' => 0.00,'eu' => 0],
41 => ['country' => 'Andorra', 'taxes' => 0.00,'eu' => 0],
42 => ['country' => 'Australia', 'taxes' => 0.00,'eu' => 0],
43 => ['country' => 'New Zealand', 'taxes' => 0.00,'eu' => 0],
44 => ['country' => 'Japan', 'taxes' => 0.00,'eu' => 0],
45 => ['country' => 'China', 'taxes' => 0.00,'eu' => 0],
46 => ['country' => 'India', 'taxes' => 0.00,'eu' => 0],
47 => ['country' => 'South Korea', 'taxes' => 0.00,'eu' => 0],
48 => ['country' => 'Singapore', 'taxes' => 0.00,'eu' => 0],
49 => ['country' => 'Indonesia', 'taxes' => 0.00,'eu' => 0],
50 => ['country' => 'Thailand', 'taxes' => 0.00,'eu' => 0],
51 => ['country' => 'Vietnam', 'taxes' => 0.00,'eu' => 0],
52 => ['country' => 'Philippines', 'taxes' => 0.00,'eu' => 0],
53 => ['country' => 'Malaysia', 'taxes' => 0.00,'eu' => 0],
54 => ['country' => 'Taiwan', 'taxes' => 0.00,'eu' => 0],
55 => ['country' => 'Pakistan', 'taxes' => 0.00,'eu' => 0],
56 => ['country' => 'Bangladesh', 'taxes' => 0.00,'eu' => 0],
57 => ['country' => 'Sri Lanka', 'taxes' => 0.00,'eu' => 0],
58 => ['country' => 'Nepal', 'taxes' => 0.00,'eu' => 0],
59 => ['country' => 'Cambodia', 'taxes' => 0.00,'eu' => 0],
60 => ['country' => 'Myanmar', 'taxes' => 0.00,'eu' => 0],
61 => ['country' => 'Laos', 'taxes' => 0.00,'eu' => 0],
62 => ['country' => 'Mongolia', 'taxes' => 0.00,'eu' => 0],
63 => ['country' => 'Kazakhstan', 'taxes' => 0.00,'eu' => 0],
64 => ['country' => 'Uzbekistan', 'taxes' => 0.00,'eu' => 0],
65 => ['country' => 'Armenia', 'taxes' => 0.00,'eu' => 0],
66 => ['country' => 'Georgia', 'taxes' => 0.00,'eu' => 0],
67 => ['country' => 'Azerbaijan', 'taxes' => 0.00,'eu' => 0],
68 => ['country' => 'Fiji', 'taxes' => 0.00,'eu' => 0],
69 => ['country' => 'Papua New Guinea', 'taxes' => 0.00,'eu' => 0],
70 => ['country' => 'Samoa', 'taxes' => 0.00,'eu' => 0],
71 => ['country' => 'Tonga', 'taxes' => 0.00,'eu' => 0],
72 => ['country' => 'Vanuatu', 'taxes' => 0.00,'eu' => 0],
73 => ['country' => 'Bhutan', 'taxes' => 0.00,'eu' => 0],
74 => ['country' => 'Saudi Arabia', 'taxes' => 0.00,'eu' => 0],
75 => ['country' => 'United Arab Emirates', 'taxes' => 0.00,'eu' => 0],
76 => ['country' => 'Bahrain', 'taxes' => 0.00,'eu' => 0],
77 => ['country' => 'Kuwait', 'taxes' => 0.00,'eu' => 0],
78 => ['country' => 'Oman', 'taxes' => 0.00,'eu' => 0],
79 => ['country' => 'Qatar', 'taxes' => 0.00,'eu' => 0],
80 => ['country' => 'Israel', 'taxes' => 0.00,'eu' => 0],
81 => ['country' => 'Jordan', 'taxes' => 0.00,'eu' => 0],
82 => ['country' => 'Lebanon', 'taxes' => 0.00,'eu' => 0],
83 => ['country' => 'Egypt', 'taxes' => 0.00,'eu' => 0],
85 => ['country' => 'South Africa', 'taxes' => 0.00,'eu' => 0],
86 => ['country' => 'Nigeria', 'taxes' => 0.00,'eu' => 0],
87 => ['country' => 'Kenya', 'taxes' => 0.00,'eu' => 0],
88 => ['country' => 'Ghana', 'taxes' => 0.00,'eu' => 0],
89 => ['country' => 'Morocco', 'taxes' => 0.00,'eu' => 0],
90 => ['country' => 'Tunisia', 'taxes' => 0.00,'eu' => 0],
91 => ['country' => 'Algeria', 'taxes' => 0.00,'eu' => 0],
92 => ['country' => 'Egypt', 'taxes' => 0.00,'eu' => 0],
93 => ['country' => 'Ethiopia', 'taxes' => 0.00,'eu' => 0],
94 => ['country' => 'Tanzania', 'taxes' => 0.00,'eu' => 0],
95 => ['country' => 'Uganda', 'taxes' => 0.00,'eu' => 0],
96 => ['country' => 'Zimbabwe', 'taxes' => 0.00,'eu' => 0],
97 => ['country' => 'Zambia', 'taxes' => 0.00,'eu' => 0],
98 => ['country' => 'Botswana', 'taxes' => 0.00,'eu' => 0],
99 => ['country' => 'Mauritius', 'taxes' => 0.00,'eu' => 0],
100 => ['country' => 'Namibia', 'taxes' => 0.00,'eu' => 0],
101 => ['country' => 'Rwanda', 'taxes' => 0.00,'eu' => 0],
102 => ['country' => 'Senegal', 'taxes' => 0.00,'eu' => 0],
103 => ['country' => 'Ivory Coast', 'taxes' => 0.00,'eu' => 0],
104 => ['country' => 'Cameroon', 'taxes' => 0.00,'eu' => 0],
105 => ['country' => 'Angola', 'taxes' => 0.00,'eu' => 0],
106 => ['country' => 'Mozambique', 'taxes' => 0.00,'eu' => 0],
107 => ['country' => 'Madagascar', 'taxes' => 0.00,'eu' => 0],
108 => ['country' => 'Mali', 'taxes' => 0.00,'eu' => 0],
109 => ['country' => 'Burkina Faso', 'taxes' => 0.00,'eu' => 0],
110 => ['country' => 'Niger', 'taxes' => 0.00,'eu' => 0],
111 => ['country' => 'Benin', 'taxes' => 0.00,'eu' => 0],
112 => ['country' => 'Togo', 'taxes' => 0.00,'eu' => 0],
113 => ['country' => 'Guinea', 'taxes' => 0.00,'eu' => 0],
114 => ['country' => 'Malawi', 'taxes' => 0.00,'eu' => 0],
115 => ['country' => 'Gabon', 'taxes' => 0.00,'eu' => 0],
116 => ['country' => 'Mauritania', 'taxes' => 0.00,'eu' => 0],
117 => ['country' => 'Lesotho', 'taxes' => 0.00,'eu' => 0],
118 => ['country' => 'Eswatini', 'taxes' => 0.00,'eu' => 0],
119 => ['country' => 'Liberia', 'taxes' => 0.00,'eu' => 0],
120 => ['country' => 'Canada', 'taxes' => 0.00,'eu' => 0],
121 => ['country' => 'United States', 'taxes' => 0.00,'eu' => 0],
122 => ['country' => 'Mexico', 'taxes' => 0.00,'eu' => 0],
123 => ['country' => 'Argentina', 'taxes' => 0.00,'eu' => 0],
124 => ['country' => 'Brazil', 'taxes' => 0.00,'eu' => 0],
125 => ['country' => 'Chile', 'taxes' => 0.00,'eu' => 0],
126 => ['country' => 'Colombia', 'taxes' => 0.00,'eu' => 0],
127 => ['country' => 'Peru', 'taxes' => 0.00,'eu' => 0],
128 => ['country' => 'Ecuador', 'taxes' => 0.00,'eu' => 0],
129 => ['country' => 'Uruguay', 'taxes' => 0.00,'eu' => 0],
130 => ['country' => 'Paraguay', 'taxes' => 0.00,'eu' => 0],
131 => ['country' => 'Bolivia', 'taxes' => 0.00,'eu' => 0],
132 => ['country' => 'Venezuela', 'taxes' => 0.00,'eu' => 0],
133 => ['country' => 'Costa Rica', 'taxes' => 0.00,'eu' => 0],
134 => ['country' => 'Panama', 'taxes' => 0.00,'eu' => 0],
135 => ['country' => 'Guatemala', 'taxes' => 0.00,'eu' => 0],
136 => ['country' => 'Honduras', 'taxes' => 0.00,'eu' => 0],
137 => ['country' => 'El Salvador', 'taxes' => 0.00,'eu' => 0],
138 => ['country' => 'Nicaragua', 'taxes' => 0.00,'eu' => 0],
139 => ['country' => 'Dominican Republic', 'taxes' => 0.00,'eu' => 0],
140 => ['country' => 'Jamaica', 'taxes' => 0.00,'eu' => 0],
141 => ['country' => 'Trinidad and Tobago', 'taxes' => 0.00,'eu' => 0],
142 => ['country' => 'Barbados', 'taxes' => 0.00,'eu' => 0],
143 => ['country' => 'Bahamas', 'taxes' => 0.00,'eu' => 0],
];