diff --git a/.DS_Store b/.DS_Store index 9d4c452..6c22bef 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 4a636e1..d3aeeb0 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ api/v2/.DS_Store api/.DS_Store assets/.DS_Store assets/images/.DS_Store +assets/database/ManualUpdates.sql diff --git a/api.php b/api.php index 3bb45e5..1d00f99 100644 --- a/api.php +++ b/api.php @@ -1,6 +1,7 @@ getMessage() . " in " . $exception->getFile() . " on line " . $exception->getLine()); + }); +} + //------------------------------------------ // Header security - enabled via config //------------------------------------------ diff --git a/api/.DS_Store b/api/.DS_Store index 362cceb..25bea50 100644 Binary files a/api/.DS_Store and b/api/.DS_Store differ diff --git a/api/v0/post/application.php b/api/v0/post/application.php index 6a8a550..323d616 100644 --- a/api/v0/post/application.php +++ b/api/v0/post/application.php @@ -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]); } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/api/v1/.DS_Store b/api/v1/.DS_Store index ad7d9dd..d200a4c 100644 Binary files a/api/v1/.DS_Store and b/api/v1/.DS_Store differ diff --git a/api/v1/post/application.php b/api/v1/post/application.php index 0c397e1..73730fa 100644 --- a/api/v1/post/application.php +++ b/api/v1/post/application.php @@ -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; diff --git a/api/v2/.DS_Store b/api/v2/.DS_Store index 16d8e39..c28ab40 100644 Binary files a/api/v2/.DS_Store and b/api/v2/.DS_Store differ diff --git a/api/v2/get/software_available.php b/api/v2/get/software_available.php index 8f4e4e6..ca139d1 100644 --- a/api/v2/get/software_available.php +++ b/api/v2/get/software_available.php @@ -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); diff --git a/api/v2/get/software_update.php b/api/v2/get/software_update.php index d56a26e..18f97e4 100644 --- a/api/v2/get/software_update.php +++ b/api/v2/get/software_update.php @@ -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) } } } diff --git a/api/v2/post/equipments.php b/api/v2/post/equipments.php index f4d14cd..f7adcc8 100644 --- a/api/v2/post/equipments.php +++ b/api/v2/post/equipments.php @@ -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 diff --git a/api/v2/post/history.php b/api/v2/post/history.php index 5290e69..0861871 100644 --- a/api/v2/post/history.php +++ b/api/v2/post/history.php @@ -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 { diff --git a/api/v2/post/payment.php b/api/v2/post/payment.php index 1e79ad0..c022b53 100644 --- a/api/v2/post/payment.php +++ b/api/v2/post/payment.php @@ -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') diff --git a/assets/.DS_Store b/assets/.DS_Store index 1ba4cf5..7502f1f 100644 Binary files a/assets/.DS_Store and b/assets/.DS_Store differ diff --git a/assets/functions.php b/assets/functions.php index ed8aff8..f17faaa 100644 --- a/assets/functions.php +++ b/assets/functions.php @@ -1264,8 +1264,10 @@ function ioServer($api_call, $data){ $http_status = curl_getinfo($curl) ?? '200'; curl_close($curl); - if(debug){ - debuglog($date." - ioServer: URL=$url, HTTP Code=$http_status, Response=" . substr($resp, 0, 500) . (strlen($resp) > 500 ? '...' : '')); + + if (debug) { + $resp_log = $date . " - ioServer: URL=$url, HTTP Code= ". ($http_status['http_code'] ?? 'unknown') . ", Response=" . substr($resp, 0, 500) . (strlen($resp) > 500 ? '...' : ''); + debuglog(json_encode($resp_log)); } //Check If errorcode is returned @@ -1728,33 +1730,38 @@ function getPartnerID($str){ // overview Indicators //------------------------------------------ function overviewIndicators($warranty, $service, $sw_version, $sw_version_latest){ - include dirname(__FILE__,2).'/settings/settings_redirector.php'; - include dirname(__FILE__,2).'/settings/systemfirmware.php'; - $indicator =''; - //In warranty - if (!empty($warranty ) && $warranty > $warrantydate){ - $indicator .= 'W'; - } else { - $indicator .= 'W'; - } - //Out of Service - if (!empty($service) && $service < $servicedate){ - $indicator .= 'S'; - } else { - $indicator .= 'S'; - } + + include dirname(__FILE__,2).'/settings/settings_redirector.php'; + include dirname(__FILE__,2).'/settings/systemfirmware.php'; + + $indicator =''; + $current_date = date('Y-m-d'); + + //In warranty + if (!empty($warranty ) && $warranty >= $current_date){ + $indicator .= 'W'; + } else { + $indicator .= 'W'; + } + //Out of Service + if (!empty($service) && $service >= $current_date){ + $indicator .= 'S'; + } else { + $indicator .= 'S'; + } //Firmware if (isset($sw_version_latest)){ - if($sw_version_latest == 1){ - $indicator .= 'F'; + if($sw_version_latest == 1){ + $indicator .= 'F'; + } + else { + if ($sw_version == ''){ + $indicator .= 'F'; } else { - if ($sw_version == ''){ - $indicator .= 'F'; - } else { - $indicator .= 'F'; - } + $indicator .= 'F'; } + } } return $indicator; @@ -1783,11 +1790,12 @@ function warrantyStatus($input){ } $warranty_date_due ='Unknown'; - - if (!empty($input) && $input < $warrantydate){ - $warranty_date_due = ''.$warranty_outdated_text.''; + $current_date = date('Y-m-d'); + + if (!empty($input) && $input >= $current_date){ + $warranty_date_due = ''.$warranty_recent.' ('.$input.')'; } else { - $warranty_date_due = ''.$warranty_recent.' ('.date('Y-m-d', strtotime($input. ' + 365 days')).')'; + $warranty_date_due = ''.$warranty_outdated_text.''; } return $warranty_date_due; @@ -1814,13 +1822,15 @@ function serviceStatus($input){ else { include dirname(__FILE__,2).'/settings/translations/translations_US.php'; } - + + $current_date = date('Y-m-d'); $service_date_due ='Unknown'; - if (!empty($input) && $input < $servicedate){ - $service_date_due = ''.$service_renewal_text.''; + if (!empty($input) && $input >= $current_date){ + $service_date_due =''.$service_recent.' ('.$input.')'; } else { - $service_date_due =''.$service_recent.' ('.date('Y-m-d', strtotime($input. ' + 365 days')).')'; + $service_date_due = ''.$service_renewal_text.''; + } return $service_date_due; @@ -2976,20 +2986,29 @@ function showlog($object,$objectID){ $stmt->execute([$object,$objectID]); $changes = $stmt->fetchAll(PDO::FETCH_ASSOC); - $view = ''; - foreach($changes as $change){ - - $object_value = $change['object_value']; - - //UPDATE TO HUMANREADABLE STATUS - if ($object == 'equipment' && $change['object_field'] == 'status'){ - $object_text = 'status'.$change['object_value'].'_text'; - $object_value = $$object_text; + $view = '
'; + if ($changes) { + foreach ($changes as $change) { + $object_value = $change['object_value']; + // Human-readable status + if ($object == 'equipment' && $change['object_field'] == 'status') { + $object_text = 'status' . $change['object_value'] . '_text'; + if (isset($$object_text)) { + $object_value = $$object_text; + } + } + $entry = htmlspecialchars( $object_value . ' - ' . $change['created'] . ' - ' . $change['createdby']); + $view .= '
+ +

'.$entry.'

+
'; + + } + } else { + $view .= '
No changelog entries found.
'; } - $view .= ''; - } - - return $view; + $view .= '
'; + return $view; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -5577,4 +5596,48 @@ function updateSoftwareLatestFlags($pdo, $version_id, $hw_version) { $stmt->execute([$version['rowID']]); } } +} + +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Generate Countries File from Taxes API +++++++++++++++++ +// +++++++++++++++++++++++++++++++++++++++++++++++++++++++ +function generateCountriesFile($token){ + + //API call to get all taxes + $api_url = '/v2/taxes'; + $response = ioAPIv2($api_url, '', $token); + + if(!empty($response)){ + //decode the API response + $taxes = json_decode($response, true); + + if(!empty($taxes) && is_array($taxes)){ + //Build the countries array - id as key, with country name and tax rate + $countries = []; + foreach($taxes as $tax){ + $countries[$tax['id']] = [ + 'country' => $tax['country'] ?? '', + 'taxes' => $tax['rate'] ?? 0 + ]; + } + + //Generate PHP file content + $fileContent = " $data){ + $fileContent .= " " . $id . " => ['country' => '" . addslashes($data['country']) . "', 'taxes' => " . $data['taxes'] . "],\n"; + } + $fileContent .= "];\n"; + + //Write to settings/countries.php + $filePath = dirname(__FILE__, 2) . '/settings/countries.php'; + $result = file_put_contents($filePath, $fileContent); + + return ($result !== false); + } + } + + return false; } \ No newline at end of file diff --git a/assets/images/.DS_Store b/assets/images/.DS_Store index 12648ae..a97d4fb 100644 Binary files a/assets/images/.DS_Store and b/assets/images/.DS_Store differ diff --git a/assets/softwaretool.js b/assets/softwaretool.js index a5db168..31b6125 100644 --- a/assets/softwaretool.js +++ b/assets/softwaretool.js @@ -10,6 +10,26 @@ let deviceVersion = ""; let deviceHwVersion = ""; let selectedSoftwareUrl = ""; +// Helper function to generate country select options +function generateCountryOptions(selectedCountry = '') { + if (typeof COUNTRIES === 'undefined' || !COUNTRIES) { + return ``; + } + + // Sort countries alphabetically + const sortedCountries = Object.values(COUNTRIES).sort((a, b) => { + return a.country.localeCompare(b.country); + }); + + let options = ''; + sortedCountries.forEach(data => { + const selected = (selectedCountry === data.country) ? 'selected' : ''; + options += ``; + }); + + return options; +} + // Serial port variables (port, writer, textEncoder, writableStreamClosed declared in PHP) let reader; let readableStreamClosed; @@ -528,8 +548,18 @@ async function fetchSoftwareOptions() { document.getElementById("softwareOptionsContainer").style.display = "block"; progressBar("100", "Software options loaded", "#04AA6D"); - // Show user info modal immediately - showUserInfoModal(); + // Show user info modal immediately (skip in debug mode) + if (typeof DEBUG === 'undefined' || !DEBUG) { + showUserInfoModal(); + } else { + // In debug mode, reveal software options immediately + const softwareOptions = document.getElementById("softwareOptions"); + if (softwareOptions) { + softwareOptions.style.filter = "none"; + softwareOptions.style.opacity = "1"; + softwareOptions.style.pointerEvents = "auto"; + } + } } catch (error) { await logCommunication(`Software options error: ${error.message}`, 'error'); @@ -665,7 +695,7 @@ function displaySoftwareOptions(options) { } else { priceText.innerHTML = isFree ? 'Free' - : `${option.currency || "€"} ${price.toFixed(2)}`; + : `${option.currency || "€"} ${price.toFixed(2)} (excl. VAT)`; } priceSection.appendChild(priceText); @@ -777,7 +807,9 @@ function showUserInfoModal() {
- +
@@ -967,7 +999,9 @@ function showFreeInstallModal(option) {
- +
@@ -1045,6 +1079,17 @@ function showPaymentModal(option) { const price = parseFloat(option.price || 0); const currency = option.currency || "€"; + // Format description as bullet points + const formatDescription = (desc) => { + if (!desc) return ''; + // Split by bullet points or newlines and filter out empty lines + const lines = desc.split(/[•·\n]/).map(line => line.trim()).filter(line => line.length > 0); + if (lines.length <= 1) return desc; // Return as-is if no multiple lines + return ''; + }; + // Create modal overlay const modal = document.createElement("div"); modal.id = "paymentModal"; @@ -1082,9 +1127,20 @@ function showPaymentModal(option) {

${option.name || "Software Update"}

Version: ${option.version || "N/A"}

-

${option.description || ""}

-
- ${currency} ${price.toFixed(2)} +
${formatDescription(option.description)}
+
+
+ Price (excl. VAT): + ${currency} ${price.toFixed(2)} +
+
+ VAT: + - +
+
+ Total: + ${currency} ${price.toFixed(2)} +
@@ -1105,7 +1161,9 @@ function showPaymentModal(option) {
- +
@@ -1134,6 +1192,45 @@ function showPaymentModal(option) { modal.appendChild(modalContent); document.body.appendChild(modal); + // Function to calculate and update tax + function updateTaxDisplay() { + const selectedCountry = document.getElementById("paymentCountry").value; + let taxRate = 0; + + if (selectedCountry && typeof COUNTRIES !== 'undefined' && COUNTRIES) { + const countryData = Object.values(COUNTRIES).find(c => c.country === selectedCountry); + if (countryData) { + taxRate = parseFloat(countryData.taxes) || 0; + } + } + + const taxAmount = price * (taxRate / 100); + const totalAmount = price + taxAmount; + + // Update display + const taxDisplay = document.getElementById("taxDisplay"); + const totalDisplay = document.getElementById("totalDisplay"); + + if (taxRate > 0) { + taxDisplay.innerHTML = ` + VAT (${taxRate}%): + ${currency} ${taxAmount.toFixed(2)} + `; + } else { + taxDisplay.innerHTML = ` + VAT: + - + `; + } + + totalDisplay.textContent = `${currency} ${totalAmount.toFixed(2)}`; + + // Store tax info for form submission + modal.taxRate = taxRate; + modal.taxAmount = taxAmount; + modal.totalAmount = totalAmount; + } + // Prefill form with customer data from sessionStorage if available const savedCustomerData = sessionStorage.getItem('customerData'); if (savedCustomerData) { @@ -1144,12 +1241,18 @@ function showPaymentModal(option) { if (customerData.address) document.getElementById("paymentAddress").value = customerData.address; if (customerData.city) document.getElementById("paymentCity").value = customerData.city; if (customerData.postal) document.getElementById("paymentPostal").value = customerData.postal; - if (customerData.country) document.getElementById("paymentCountry").value = customerData.country; + if (customerData.country) { + document.getElementById("paymentCountry").value = customerData.country; + updateTaxDisplay(); // Calculate tax based on saved country + } } catch (e) { console.warn('Error parsing saved customer data:', e); } } + // Add event listener to country select to update tax + document.getElementById("paymentCountry").addEventListener('change', updateTaxDisplay); + // Close modal on cancel document.getElementById("cancelPayment").onclick = () => { document.body.removeChild(modal); @@ -1160,15 +1263,15 @@ function showPaymentModal(option) { e.preventDefault(); const formData = new FormData(e.target); const paymentMethod = formData.get("payment_method"); - + // Auto-determine payment provider based on payment method let paymentProvider = 'mollie'; // default - if (paymentMethod === 'paypal') { + if (paymentMethod === '3') { // PayPal payment method ID paymentProvider = 'paypal'; - } else if (paymentMethod === 'credit_card' || paymentMethod === 'bank_transfer') { + } else if (paymentMethod === '1' || paymentMethod === 'bank_transfer') { // Mollie (Credit Card) or Bank Transfer paymentProvider = 'mollie'; } - + const paymentData = { name: formData.get("name"), email: formData.get("email"), @@ -1179,7 +1282,9 @@ function showPaymentModal(option) { payment_method: paymentMethod, payment_provider: paymentProvider, version_id: option.version_id, - price: price, + item_price: price, // Price without VAT + tax_amount: modal.taxAmount || 0, // Tax amount + payment_amount: modal.totalAmount || price, // Total price including tax currency: currency }; diff --git a/custom/morvalwatches/style/VeLiTi-Logo2.png b/custom/morvalwatches/style/VeLiTi-Logo2.png old mode 100755 new mode 100644 diff --git a/equipment.php b/equipment.php index e800dd3..5175107 100644 --- a/equipment.php +++ b/equipment.php @@ -441,7 +441,7 @@ $view .= '
'.$general_updated.' - '.getRelativeTime($responses->updated).' + '.getRelativeTime($responses->updated).'
@@ -704,6 +704,32 @@ if ($latest_customer || $latest_warranty) { '; } +// Modal for log +echo ' + + +'; + template_footer() ?> \ No newline at end of file diff --git a/equipment_manage.php b/equipment_manage.php index c0f8adc..46563e9 100644 --- a/equipment_manage.php +++ b/equipment_manage.php @@ -87,11 +87,12 @@ if (isset($_GET['equipmentID'])) { $data = json_encode($_POST, JSON_UNESCAPED_UNICODE); //API call $responses = ioServer('/v2/equipments', $data); + if ($responses === 'NOK'){ } else { - header('Location: index.php?page=equipment&equipmentID='.$equipment_ID.'&success_msg=2'); - exit; + header('Location: index.php?page=equipment&equipmentID='.$equipment_ID.'&success_msg=2'); + exit; } } } diff --git a/equipments.php b/equipments.php index 2f4f7dd..35708d5 100644 --- a/equipments.php +++ b/equipments.php @@ -52,6 +52,12 @@ $responses = ioServer($api_url,''); //Decode Payload if (!empty($responses)){$responses = json_decode($responses);}else{$responses = null;} +// Redirect if only one equipment is found +if (is_array($responses) && count($responses) === 1 && isset($responses[0]->equipmentID)) { + header('Location: index.php?page=equipment&equipmentID=' . $responses[0]->equipmentID); + exit; +} + //Return QueryTotal from API $total_url = ((!empty($GET_VALUES) && $GET_VALUES !='') ? '&totals=' : 'totals=' ); $api_url = '/v2/equipments/'.$GET_VALUES.$total_url; diff --git a/index.php b/index.php index a6d652d..817a9ab 100644 --- a/index.php +++ b/index.php @@ -15,9 +15,21 @@ if (debug && debug_id == $_SESSION['id']){ error_reporting(E_ALL); } +if (debug){ + set_error_handler(function($errno, $errstr, $errfile, $errline) { + debuglog("PHP ERROR [$errno]: $errstr in $errfile on line $errline"); + return false; + }); + + set_exception_handler(function($exception) { + debuglog("PHP EXCEPTION: " . $exception->getMessage() . " in " . $exception->getFile() . " on line " . $exception->getLine()); + }); +} + //INCLUDE FUNCTIONS AND SETTINGS include dirname(__FILE__).'/assets/functions.php'; include dirname(__FILE__).'/settings/settings_redirector.php'; +include_once dirname(__FILE__).'/settings/countries.php'; //===================================== //TRANSLATION FILE LOCATION diff --git a/maintenance.php b/maintenance.php index 8b66507..06728ab 100644 --- a/maintenance.php +++ b/maintenance.php @@ -40,6 +40,9 @@ if ($update_allowed === 1){ if (isset($_POST['generateDealerInformation'])){ generateDealerInformation($_SESSION['userkey']); } + if (isset($_POST['generateCountriesFile'])){ + generateCountriesFile($_SESSION['userkey']); + } } // Handle success messages @@ -91,6 +94,10 @@ $view .= '
+
+ + +
'; } diff --git a/products_software_upgrade_paths_manage.php b/products_software_upgrade_paths_manage.php index c37f2a6..2261f80 100644 --- a/products_software_upgrade_paths_manage.php +++ b/products_software_upgrade_paths_manage.php @@ -186,7 +186,8 @@ $view .= '
- +
'.$register_3_email_consent.'
diff --git a/settings/countries.php b/settings/countries.php new file mode 100644 index 0000000..1b97ff3 --- /dev/null +++ b/settings/countries.php @@ -0,0 +1,148 @@ + ['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], +]; diff --git a/softwaretool.php b/softwaretool.php index 96c3b84..398d1b4 100644 --- a/softwaretool.php +++ b/softwaretool.php @@ -22,6 +22,24 @@ $payment_return = isset($_GET['order_id']) ? $_GET['order_id'] : null; $payment_return_status = isset($_GET['payment_return']) ? $_GET['payment_return'] : null; $paypal_token = isset($_GET['token']) ? $_GET['token'] : null; // PayPal returns with ?token= +// Handle payment cancellation - mark order as cancelled +if ($payment_return && $payment_return_status === 'cancelled') { + try { + $pdo = dbConnect($dbname); + $sql = 'UPDATE transactions SET payment_status = 999 WHERE txn_id = ?'; + $stmt = $pdo->prepare($sql); + $stmt->execute([$payment_return]); + + if (debug) { + debuglog("Payment cancelled - Order ID: {$payment_return} marked as cancelled (999)"); + } + } catch (Exception $e) { + if (debug) { + debuglog("Error marking order as cancelled: " . $e->getMessage()); + } + } +} + // Handle PayPal return - capture the order directly if ($paypal_token && $payment_return) { try { @@ -134,8 +152,23 @@ if ($payment_return && $payment_return_status) { // Auto-refresh every 3 seconds to check payment status setTimeout(function() { location.reload(); }, 3000); '; + } else if ($transaction['payment_status'] == 999) { + // Payment cancelled + $payment_modal = ' + '; } else { - // Payment failed/cancelled + // Payment failed/expired $payment_modal = '