feat: Enhance software tool with country selection and tax calculation

- Added a helper function to generate country select options in software tool.
- Updated user info modal and payment modal to use country dropdowns instead of text inputs.
- Implemented tax calculation based on selected country in payment modal.
- Improved software options loading behavior in debug mode.
- Enhanced description formatting in payment modal.
- Added log modal for equipment updates with a link to view logs.
- Introduced a new countries settings file with tax rates for various countries.
- Minor adjustments to various PHP files for better handling of equipment and payment processes.
This commit is contained in:
“VeLiTi”
2026-01-16 16:01:31 +01:00
parent 7aebb762d3
commit 3db13b9ebf
27 changed files with 652 additions and 114 deletions

BIN
api/.DS_Store vendored

Binary file not shown.

View File

@@ -56,7 +56,9 @@ if (!empty($post_content['sn']) && !empty($post_content['testdetails'])) {
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
$user = $username;
$account = $partnerhierarchy; //string
$current_date = date("Y-m-d");
$service_date = date("Y-m-d", strtotime("+" . SERVICE_MONTHS . " months"));
$warranty_date = date("Y-m-d", strtotime("+" . WARRANTY_MONTHS . " months"));
$order_send_date = date("Y-m-d");
$input_type = $post_content['type'];
$testdetails = json_encode($post_content['testdetails']);
$serial = $post_content['sn'];
@@ -187,9 +189,9 @@ if (!empty($post_content['sn']) && !empty($post_content['testdetails'])) {
// Create equipment when not exist +++++++++++++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
if ($equipmentCreate == 1 && $total_equipment == 0){
$sql = 'INSERT INTO equipment (productrowid,created,createdby,status,accounthierarchy,serialnumber,service_date,warranty_date) VALUES (?,?,?,?,?,?,?,?)';
$sql = 'INSERT INTO equipment (productrowid,created,createdby,status,accounthierarchy,serialnumber,service_date,warranty_date,order_send_date) VALUES (?,?,?,?,?,?,?,?,?)';
$stmt = $pdo->prepare($sql);
$stmt->execute([$productrowid,$date,$user,$status0,$account,$serial,$current_date,$current_date]);
$stmt->execute([$productrowid,$date,$user,$status0,$account,$serial,$service_date,$warranty_date,$order_send_date]);
$rowID = $pdo->lastInsertId();
}
@@ -311,7 +313,7 @@ if (!empty($post_content['sn']) && !empty($post_content['testdetails'])) {
//Update Equipment record
$sql = "UPDATE equipment SET service_date = ? $whereclause";
$stmt = $pdo->prepare($sql);
$stmt->execute([$current_date]);
$stmt->execute([$service_date]);
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++

BIN
api/v1/.DS_Store vendored

Binary file not shown.

View File

@@ -84,20 +84,6 @@ switch ($action) {
$communication_check = 0; //Check communication record
$message_box = [];
$timestamp = date("Y-m-d H:i:s");
// Create history description
$history_description = [
"start_date"=>$timestamp,
"end_date"=>date("Y-m-d", strtotime("+730 days")),
"organization"=>strip_tags(trim($post_content['organization'])),
"phone"=>strip_tags(trim($post_content['phone'])),
"city"=>strip_tags(trim($post_content['city'])),
"country"=>strip_tags(trim($post_content['country'])),
"email_consent"=>strip_tags(trim($post_content['email_consent'])),
"terms_consent"=>strip_tags(trim($post_content['terms_consent']))
];
$description = json_encode($history_description, JSON_UNESCAPED_UNICODE);
// --------------------------------------------
// Check if multiple serialnumbers are provided
@@ -108,9 +94,12 @@ switch ($action) {
foreach ($serial_numbers as $sn) {
// Get equipment ID based on serial number
$rowID = getrowID($dbname, 'rowID', 'equipment', 'serialnumber="' . $sn . '"');
$sql = 'SELECT rowID, warranty_date, order_send_date from equipment where serialnumber = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$sn]);
$rowID = $stmt->fetch();
if (!$rowID) {
if (!$rowID['rowID']) {
// Serial number not recognized
$message_box[] = $sn . ' - ' . $register_message_1;
continue;
@@ -128,8 +117,45 @@ switch ($action) {
continue;
}
//define warranty_end_date
$order_send_date = $rowID['order_send_date'] ?? $rowID['warranty_date'];
// Check if order_send_date is available
if (empty($order_send_date)) {
// No valid date found - skip this serial number
$message_box[] = $sn . ' - ' . $register_message_1; // or create a specific message for missing date
continue;
}
// Calculate warranty end date based on eligibility window
$current_date = new DateTime();
$order_date = new DateTime($order_send_date);
$months_diff = $current_date->diff($order_date)->m + ($current_date->diff($order_date)->y * 12);
if ($months_diff <= WARRANTY_ELIGIBILITY_WINDOW) {
// Within eligibility window - apply extended warranty
$warranty_end_date = (clone $order_date)->modify('+' . WARRANTY_EXTENDED_MONTH . ' months')->format('Y-m-d');
} else {
// Outside eligibility window - apply standard warranty
$warranty_end_date = (clone $order_date)->modify('+' . WARRANTY_MONTHS . ' months')->format('Y-m-d');
}
// Not under warranty - process registration
$firmware_account_send = 1;
//Create history description
$history_description = [
"start_date"=>$timestamp,
"end_date"=> $warranty_end_date,
"organization"=>strip_tags(trim($post_content['organization'])),
"phone"=>strip_tags(trim($post_content['phone'])),
"city"=>strip_tags(trim($post_content['city'])),
"country"=>strip_tags(trim($post_content['country'])),
"email_consent"=>strip_tags(trim($post_content['email_consent'])),
"terms_consent"=>strip_tags(trim($post_content['terms_consent']))
];
$description = json_encode($history_description, JSON_UNESCAPED_UNICODE);
// Create history entry
$sql = 'INSERT INTO equipment_history (equipmentid, type, description, created, createdby, updatedby) VALUES (?,?,?,?,?,?)';
@@ -190,11 +216,11 @@ switch ($action) {
// Update equipment record
$sql = 'UPDATE equipment SET status = ?, warranty_date = ?, accounthierarchy = ?, updatedby = ? WHERE rowID = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute(['4', $warranty_extended, $partnerhierarchy_json, $username, $rowID['rowID']]);
$stmt->execute(['4', $warranty_end_date, $partnerhierarchy_json, $username, $rowID['rowID']]);
// Add warranty to changelog
$warranty_user = $post_content['email'] ?? 'system';
changelog($dbname, 'equipment', $rowID['rowID'], 'Warranty', $warranty_extended, $warranty_user);
changelog($dbname, 'equipment', $rowID['rowID'], 'Warranty', $warranty_end_date, $warranty_user);
// Serial number recognized
$message_box[] = $sn . ' - ' . $register_message_3;

BIN
api/v2/.DS_Store vendored

Binary file not shown.

View File

@@ -294,8 +294,9 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
FROM products_software_upgrade_paths pup
JOIN products_software_versions from_ver ON pup.from_version_id = from_ver.rowID
WHERE pup.to_version_id = ?
AND LOWER(TRIM(LEADING "0" FROM from_ver.version)) = ?
AND pup.is_active = 1';
AND (LOWER(TRIM(LEADING "0" FROM from_ver.version)) = ?
OR pup.from_version_id = 9999999)
AND pup.is_active = 1';
$stmt = $pdo->prepare($sql);
$stmt->execute([$version['version_id'], $current_sw_version]);
$upgrade_path = $stmt->fetch(PDO::FETCH_ASSOC);

View File

@@ -332,26 +332,28 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
} else {
//Part of an upgrade path system
//Only show if there's an explicit path FROM current version TO this version
// OR a wildcard path (from_version_id = 9999999)
$sql = 'SELECT pup.price, pup.currency
FROM products_software_upgrade_paths pup
JOIN products_software_versions from_ver ON pup.from_version_id = from_ver.rowID
WHERE pup.to_version_id = ?
AND LOWER(TRIM(LEADING "0" FROM from_ver.version)) = ?
AND pup.is_active = 1';
AND (LOWER(TRIM(LEADING "0" FROM from_ver.version)) = ?
OR pup.from_version_id = 9999999)
AND pup.is_active = 1';
$stmt = $pdo->prepare($sql);
$stmt->execute([$version['version_id'], $current_sw_version]);
$upgrade_path = $stmt->fetch(PDO::FETCH_ASSOC);
if ($upgrade_path) {
//Valid upgrade path found FROM current version
//Valid upgrade path found FROM current version or wildcard
$show_version = true;
$final_price = $upgrade_path['price'] ?? '0.00';
$final_currency = $upgrade_path['currency'] ?? '';
$decision_reason = 'Showing - found upgrade path FROM current (' . $current_sw_version . ') with price: ' . $final_price . ' ' . $final_currency;
$decision_reason = 'Showing - found upgrade path FROM current (' . $current_sw_version . ') or wildcard with price: ' . $final_price . ' ' . $final_currency;
} else {
$decision_reason = 'Skipped - has upgrade paths but none FROM current version (' . $current_sw_version . ')';
$decision_reason = 'Skipped - has upgrade paths but none FROM current version (' . $current_sw_version . ') or wildcard';
}
//If no path from current version exists, don't show (show_version stays false)
//If no path from current version or wildcard exists, don't show (show_version stays false)
}
}
}

View File

@@ -148,9 +148,9 @@ if ($command == 'update'){
//RESET WARRANTY AND SERVICE DATES WHEN STATUS IS CHANGED TO SEND(3)
if (isset($post_content['status']) && $post_content['status'] == 3 && $equipment_data['status'] != 3)
{
$post_content['service_date'] = $date;
$post_content['warranty_date'] = $date;
$post_content['service_date'] = date("Y-m-d", strtotime("+" . SERVICE_MONTHS . " months"));
$post_content['warranty_date'] = date("Y-m-d", strtotime("+" . WARRANTY_MONTHS . " months"));
$post_content['order_send_date'] = $date;
}
//UPDATE CHANGELOG BASED ON STATUS CHANGE
if (isset($post_content['status']) && $post_content['status'] != $equipment_data['status'])
@@ -188,8 +188,15 @@ elseif ($command == 'insert'){
$post_content['created'] = $date;
$post_content['createdby'] = $username;
$post_content['accounthierarchy'] = $accounthierarchy;
$post_content['service_date'] = $date;
$post_content['warranty_date'] = $date;
$post_content['service_date'] = date("Y-m-d", strtotime("+" . SERVICE_MONTHS . " months"));
$post_content['warranty_date'] = date("Y-m-d", strtotime("+" . WARRANTY_MONTHS . " months"));
if (isset($post_content['status']) && $post_content['status'] == 3)
{
$post_content['order_send_date'] = $date;
}
}
else {
//do nothing

View File

@@ -44,12 +44,16 @@ if (isset($post_content['sn']) && (isset($post_content['payload']) || isset($pos
$updateObject_visual = 0; //update visual inspection object
$sendServiceReport = 0; //send service report via email
$transfercartest = 0; //Update cartest table with incoming data
$create_software_license = 0; //Create software license
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
//SET DEFAULT PARAMETERS
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
$user = $username;
$account = $partnerhierarchy; //string
$current_date = date("Y-m-d");
$service_date = date("Y-m-d", strtotime("+" . SERVICE_MONTHS . " months"));
$warranty_date = date("Y-m-d", strtotime("+" . WARRANTY_MONTHS . " months"));
$order_send_date = date("Y-m-d");
$input_type = $post_content['type'];
$testdetails = json_encode($post_content['payload']);
$serial = $post_content['sn'];
@@ -146,6 +150,11 @@ if (isset($post_content['sn']) && (isset($post_content['payload']) || isset($pos
$transfercartest = 1;
break;
case 12: //customer_consent
$historytype = 'Customer_consent';
$create_software_license = 1;
break;
case 'firmware': //update from Portal
$historytype = $HistoryType_2;
$equipmentUpdate = 1;
@@ -164,14 +173,14 @@ if (isset($post_content['sn']) && (isset($post_content['payload']) || isset($pos
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Connect to DB
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Get whereclause based on serialnumber
$whereclause = checkSerial($serial);
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
//CHECK if EQUIPMENT EXISTS
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
$sql = "SELECT count(rowID) as total, rowID FROM equipment $whereclause";
$sql = "SELECT count(rowID) as total, rowID, hw_version FROM equipment $whereclause";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$total = $stmt->fetchAll(PDO::FETCH_ASSOC);
@@ -182,9 +191,9 @@ if (isset($post_content['sn']) && (isset($post_content['payload']) || isset($pos
// Create equipment when not exist +++++++++++++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
if ($equipmentCreate == 1 && $total_equipment == 0){
$sql = 'INSERT INTO equipment (productrowid,created,createdby,status,accounthierarchy,serialnumber,service_date,warranty_date) VALUES (?,?,?,?,?,?,?,?)';
$sql = 'INSERT INTO equipment (productrowid,created,createdby,status,accounthierarchy,serialnumber,service_date,warranty_date,order_send_date) VALUES (?,?,?,?,?,?,?,?,?)';
$stmt = $pdo->prepare($sql);
$stmt->execute([$productrowid,$date,$user,$status0,$account,$serial,$current_date,$current_date]);
$stmt->execute([$productrowid,$date,$user,$status0,$account,$serial,$service_date,$warranty_date,$order_send_date]);
$rowID = $pdo->lastInsertId();
}
@@ -305,7 +314,7 @@ if (isset($post_content['sn']) && (isset($post_content['payload']) || isset($pos
//Update Equipment record
$sql = "UPDATE equipment SET service_date = ? $whereclause";
$stmt = $pdo->prepare($sql);
$stmt->execute([$current_date]);
$stmt->execute([$service_date]);
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -357,6 +366,49 @@ if (isset($post_content['sn']) && (isset($post_content['payload']) || isset($pos
if ($transfercartest == 1){
convertCartest();
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
// create software license ++++++++++++++++++++++++++
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
if ($create_software_license == 1){
// Generate unique license key
$license_key = generateUniqueLicenseKey();
$sw_version_consent = strtolower($post_content['testdetails']['logdetails']['FW'] ?? '');// version_id
$eq_version_hw = strtolower($rowID['hw_version'] ?? '');
//GET VERSION_ID FROM VERSION TABLE
$sql = 'SELECT rowID FROM products_software_versions WHERE version = ? and hw_version = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$sw_version_consent, $eq_version_hw]);
$version_row = $stmt->fetch(PDO::FETCH_ASSOC);
//GET VERSION_ID or use WILDCARD
$sw_version_consent = $version_row['rowID'] ?? '9999999';
// Create license
$sql = 'INSERT INTO products_software_licenses
(version_id, license_type, license_key, status, starts_at, expires_at, transaction_id, created, createdby)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)';
$stmt = $pdo->prepare($sql);
$stmt->execute([
$sw_version_consent,
1, // license_type (1 = upgrade)
$license_key,
1, // status = active
date('Y-m-d H:i:s'),
'2099-12-31 23:59:59', // effectively permanent
'Customer_consent',
date('Y-m-d H:i:s'),
$user
]);
// Update equipment.sw_version_license
$sql = 'UPDATE equipment SET sw_version_license = ? WHERE rowID = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$license_key, $rowID]);
}
}
else
{

View File

@@ -25,6 +25,11 @@ $user_data = $post_content['user_data'] ?? [];
// Read payment_provider from top level first, then fallback to user_data
$payment_provider = $post_content['payment_provider'] ?? $user_data['payment_provider'] ?? 'mollie';
// Extract tax information from user_data (sent from frontend)
$item_price = $user_data['item_price'] ?? null; // Price without VAT
$tax_amount = $user_data['tax_amount'] ?? 0; // VAT amount
$payment_amount = $user_data['payment_amount'] ?? null; // Total including VAT
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
// STEP 1: Get equipment data from serial_number
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -165,8 +170,17 @@ if (debug) {
// STEP 7: Create payment based on provider
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
try {
// Use payment_amount (with tax) if provided, otherwise use final_price
$amount_to_charge = $payment_amount ? (float)$payment_amount : (float)$final_price;
// Format price (must be string with 2 decimals)
$formatted_price = number_format((float)$final_price, 2, '.', '');
$formatted_price = number_format($amount_to_charge, 2, '.', '');
if (debug) {
debuglog("DEBUG: Item Price (excl. VAT): " . ($item_price ?? $final_price));
debuglog("DEBUG: Tax Amount: " . $tax_amount);
debuglog("DEBUG: Total Amount (incl. VAT): " . $amount_to_charge);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
// STEP 7A: Generate transaction ID BEFORE creating payment
@@ -252,7 +266,7 @@ try {
throw new Exception("No approval URL received from PayPal");
}
$payment_method_id = 1; // PayPal
$payment_method_id = 3; // PayPal
$payment_metadata = 'paypal_order_id';
} else {
@@ -291,7 +305,7 @@ try {
debuglog("DEBUG: Checkout URL: $checkout_url");
}
$payment_method_id = 0; // Mollie
$payment_method_id = 1; // Mollie
$payment_metadata = 'mollie_payment_id';
}
@@ -313,13 +327,14 @@ try {
// BUILD UP PARTNERHIERARCHY FROM USER
$partner_product = json_encode(array("salesid"=>$partner->salesid,"soldto"=>$partner->soldto), JSON_UNESCAPED_UNICODE);
$sql = 'INSERT INTO transactions (txn_id, payment_amount, payment_status, payer_email, first_name, last_name,
$sql = 'INSERT INTO transactions (txn_id, payment_amount, tax_amount, payment_status, payer_email, first_name, last_name,
address_street, address_city, address_state, address_zip, address_country, account_id, payment_method, accounthierarchy, created)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
$stmt = $pdo->prepare($sql);
$stmt->execute([
$txn_id,
$final_price,
$amount_to_charge, // Total amount including tax
$tax_amount, // Tax amount
0, // 0 = pending
$user_data['email'] ?? '',
$first_name,
@@ -348,13 +363,16 @@ try {
$payment_metadata => $payment_id // Store payment provider ID
], JSON_UNESCAPED_UNICODE);
// Use item_price (without VAT) if provided, otherwise use final_price
$item_price_to_store = $item_price ? (float)$item_price : (float)$final_price;
$sql = 'INSERT INTO transactions_items (txn_id, item_id, item_price, item_quantity, item_options, created)
VALUES (?, ?, ?, ?, ?, ?)';
$stmt = $pdo->prepare($sql);
$stmt->execute([
$transaction_id,
$version_id,
$final_price,
$item_price_to_store, // Price without VAT
1,
$item_options,
date('Y-m-d H:i:s')