Refactor permission checks across multiple files to utilize isAllowed function for better access control management. Updated hierarchy level checks in account, contracts, equipments, partners, users, and API endpoints to streamline permission validation. Enhanced download options visibility based on user permissions in various reports and management pages. Improved modal behavior and auto-installation process in software tool after payment success. Added new helper functions for building dynamic where clauses based on user hierarchy levels.

This commit is contained in:
“VeLiTi”
2026-01-28 14:32:49 +01:00
parent f7733b4113
commit 9e5f5581be
20 changed files with 360 additions and 133 deletions

View File

@@ -124,16 +124,19 @@ if ($payment_return && $payment_return_status) {
$payment_modal = '
<div id="paymentModal" class="modal" style="display: flex; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center;">
<div class="modal-content" style="background: white; border-radius: 12px; max-width: 500px; margin: 20px; box-shadow: 0 10px 40px rgba(0,0,0,0.3); position: relative;">
<span class="close" onclick="closePaymentModal()" style="position: absolute; top: 15px; right: 20px; font-size: 28px; font-weight: bold; color: #999; cursor: pointer;">&times;</span>
<div style="text-align: center; padding: 40px 30px;">
<i class="fa-solid fa-check-circle" style="font-size: 64px; color: #28a745; margin-bottom: 20px;"></i>
<i class="fa-solid fa-spinner fa-spin" style="font-size: 64px; color: #28a745; margin-bottom: 20px;"></i>
<h2 style="color: #155724; margin-bottom: 15px;">Payment Successful!</h2>
<p style="margin-bottom: 10px; color: #333;">Your payment has been processed. Please reconnect your device to apply the software upgrade.</p>
<p style="margin-bottom: 10px; color: #333;">Preparing your software installation...</p>
<p style="font-size: 12px; color: #666; margin-bottom: 25px;">Order ID: '.htmlspecialchars($payment_return).'</p>
<button onclick="closePaymentModal()" class="btn" style="padding: 12px 30px;">Continue</button>
<p style="font-size: 14px; color: #666;">Please keep your device connected</p>
</div>
</div>
</div>';
</div>
<script>
// Trigger automatic installation after payment success
window.PAYMENT_SUCCESS_ORDER_ID = "'.htmlspecialchars($payment_return).'";
</script>';
} else if ($transaction['payment_status'] == 0 || $transaction['payment_status'] == 101) {
// Payment pending
$payment_modal = '
@@ -362,6 +365,132 @@ echo '
}
};
// Automatically trigger installation after successful payment
window.triggerAutoInstallAfterPayment = async function() {
if (typeof window.PAYMENT_SUCCESS_ORDER_ID === \'undefined\') {
return; // Not a payment success return
}
const orderId = window.PAYMENT_SUCCESS_ORDER_ID;
console.log("Payment success detected for order:", orderId);
try {
// Step 1: Connect to device and read serial number, version, hardware
console.log("Step 1: Connecting to device and reading information...");
await connectDeviceForSoftware();
// Wait for device reading to complete
await new Promise(resolve => setTimeout(resolve, 2000));
// Step 2: Verify device is connected and serial number is read
if (!deviceSerialNumber) {
throw new Error("Device not connected or serial number not read. Please ensure your device is connected.");
}
console.log("Device connected - SN:", deviceSerialNumber, "Version:", deviceVersion, "HW:", deviceHwVersion);
// Step 3: Fetch payment details to get the purchased version_id
console.log("Step 2: Fetching payment details...");
const serviceToken = document.getElementById("servicetoken")?.innerHTML || \'\';
const paymentResponse = await fetch(link + `/v2/payment?payment_id=${orderId}`, {
method: "GET",
headers: {
"Authorization": "Bearer " + serviceToken
}
});
if (!paymentResponse.ok) {
throw new Error("Could not verify payment details");
}
const paymentData = await paymentResponse.json();
console.log("Payment data:", paymentData);
const purchasedVersionId = paymentData.version_id;
if (!purchasedVersionId) {
throw new Error("No version_id found in payment data");
}
console.log("Purchased version_id:", purchasedVersionId);
// Step 4: Call software_update API to get available options
// After payment, the purchased version should now be free (price = 0)
console.log("Step 3: Fetching software options from software_update...");
const updateUrl = link + "/v2/software_update/sn=" + deviceSerialNumber +
(deviceVersion ? "&version=" + deviceVersion : "") +
(deviceHwVersion ? "&hw_version=" + deviceHwVersion : "");
const updateResponse = await fetch(updateUrl, {
method: "GET",
headers: {
"Authorization": "Bearer " + serviceToken,
"Content-Type": "application/json"
}
});
const options = await updateResponse.json();
console.log("Software options received:", options);
if (options.error || !options || options.length === 0) {
throw new Error("No software updates available for this device");
}
// Step 5: Find the purchased version by matching version_id
// After payment, it should be returned with price = 0 (free/licensed)
const selectedOption = options.find(opt => opt.version_id === purchasedVersionId);
if (!selectedOption) {
throw new Error(`Purchased version (ID: ${purchasedVersionId}) not found in available options. Please try manually.`);
}
// Verify it has a download source
if (!selectedOption.source) {
throw new Error("Selected software option has no download link");
}
console.log("Found purchased version:", selectedOption);
console.log("Version price:", selectedOption.price, "(should be 0 after license activation)");
await logCommunication(`Auto-install: Starting installation of ${selectedOption.name} v${selectedOption.version} (version_id: ${purchasedVersionId})`, \'sent\');
// Step 6: Start automatic installation
console.log("Step 4: Starting installation...");
await downloadAndInstallSoftware(selectedOption);
// Close the payment modal after starting installation
setTimeout(() => {
closePaymentModal();
}, 2000);
} catch (error) {
console.error("Auto-installation failed:", error);
await logCommunication(`Auto-installation error: ${error.message}`, \'error\');
// Update modal to show error with actionable message
const modal = document.getElementById("paymentModal");
if (modal) {
const modalContent = modal.querySelector(\'.modal-content > div\');
if (modalContent) {
modalContent.innerHTML = `
<i class="fa-solid fa-exclamation-circle" style="font-size: 64px; color: #dc3545; margin-bottom: 20px;"></i>
<h2 style="color: #721c24; margin-bottom: 15px;">Auto-Installation Failed</h2>
<p style="margin-bottom: 10px; color: #333;">${error.message}</p>
<p style="font-size: 14px; color: #666; margin-bottom: 25px;">Please close this popup and manually connect your device to install the software.</p>
<button onclick="closePaymentModal()" class="btn" style="padding: 12px 30px;">Continue</button>
`;
}
}
}
};
// Trigger auto-install when payment success is detected
if (typeof window.PAYMENT_SUCCESS_ORDER_ID !== \'undefined\') {
// Wait for page to fully load and JavaScript to initialize, then trigger
setTimeout(() => {
triggerAutoInstallAfterPayment();
}, 2000);
}
// Close modal on background click
document.addEventListener("click", function(e) {
const helpModal = document.getElementById("helpModal");